embedded
contributed by <Cayonliow
>
tags: gprof
loop unrolling
Inline
template programming
gcc version
king1224
cayon@cayon-X550JX:~$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 60
Model name: Intel(R) Core(TM) i7-4720HQ CPU @ 2.60GHz
Stepping: 3
CPU MHz: 2423.484
CPU max MHz: 3600.0000
CPU min MHz: 800.0000
BogoMIPS: 5188.45
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 6144K
NUMA node0 CPU(s): 0-7
Loop unrolling
Template metaprogramming
Inline
研究 gprof, 在臉書討論區看見 gcc 版本問題,去檢查自己的 gcc 版本
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
沒有 gcc6 的問題, 所以不用重灌,相關文章
$ make
, 然後 $ ./raytracing
# Rendering scene
Done!
Execution time of raytracing() : 2.393859 sec
$ make clean
$ make PROFILE=1
$ ./raytracing
$ gprof ./raytacing | less
執行時間:
# Rendering scene
Done!
Execution time of raytracing() : 5.026474 sec
輸出結果:
subtract_vector
被呼叫 56956357 次、佔用了 20.34% 的時間; dot_product
被呼叫 69646433 次、佔用了15.94 的時間, 這兩個函式最爲耗時Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
20.34 0.37 0.37 56956357 0.00 0.00 subtract_vector
15.94 0.66 0.29 69646433 0.00 0.00 dot_product
11.27 0.87 0.21 17836094 0.00 0.00 add_vector
10.45 1.06 0.19 10598450 0.00 0.00 normalize
8.25 1.21 0.15 31410180 0.00 0.00 multiply_vector
6.32 1.32 0.12 13861875 0.00 0.00 rayRectangularIntersection
5.77 1.43 0.11 13861875 0.00 0.00 raySphereIntersection
4.95 1.52 0.09 17821809 0.00 0.00 cross_product
3.85 1.59 0.07 4620625 0.00 0.00 ray_hit_object
3.85 1.66 0.07 1048576 0.00 0.00 ray_color
2.20 1.70 0.04 4221152 0.00 0.00 multiply_vectors
1.92 1.73 0.04 1048576 0.00 0.00 rayConstruction
1.65 1.76 0.03 1241598 0.00 0.00 refraction
1.10 1.78 0.02 2110576 0.00 0.00 localColor
0.55 1.79 0.01 1241598 0.00 0.00 reflection
0.55 1.80 0.01 1204003 0.00 0.00 idx_stack_push
0.55 1.81 0.01 1 0.01 1.82 raytracing
0.27 1.82 0.01 3838091 0.00 0.00 length
static inline
double dot_product(const double *v1, const double *v2)
{
return (v1[0] * v2[0]) + (v1[1] * v2[1]) + (v1[2] * v2[2]);
}
執行時間:
# Rendering scene
Done!
Execution time of raytracing() : 4.517215 sec
math-toolkit.h
裏頭的函式都用 loop unrolling 的手法改寫
# Rendering scene
Done!
Execution time of raytracing() : 4.266808 sec
請注意程式碼排版,縮排為四個空白
課程助教好的 謝謝助教
Cayon
// general template for loop unrolling
template <int N>
int dot_product (const int* a, const int* b)
{
return ((*a) * (*b)) + dot_product<N-1> (a + 1, b + 1);
}
// template specialization
template <>
int dot_product<1> (const int* a, const int* b)
{
return (*a) * (*b);
}
// usage
dot_product<3>(a, b);
out.ppm 變成這樣..
經過版本一的優化,利用 gprof 來看執行時間的分布
subtract_vector
, dot_product
最爲明顯Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
15.10 0.18 0.18 56956357 0.00 0.00 subtract_vector
13.80 0.34 0.16 69646433 0.00 0.00 dot_product
11.21 0.47 0.13 10598450 0.00 0.00 normalize
9.06 0.57 0.11 17821809 0.00 0.00 cross_product
7.76 0.66 0.09 13861875 0.00 0.00 raySphereIntersection
7.76 0.75 0.09 4620625 0.00 0.00 ray_hit_object
6.90 0.83 0.08 1048576 0.00 0.00 ray_color
5.61 0.90 0.07 31410180 0.00 0.00 multiply_vector
4.74 0.95 0.06 17836094 0.00 0.00 add_vector
3.45 0.99 0.04 13861875 0.00 0.00 rayRectangularIntersection
3.45 1.03 0.04 1 0.04 1.16 raytracing
2.59 1.06 0.03 4221152 0.00 0.00 multiply_vectors
2.59 1.09 0.03 2110576 0.00 0.00 compute_specular_diffuse
1.73 1.11 0.02 2110576 0.00 0.00 localColor
0.86 1.12 0.01 3838091 0.00 0.00 length
0.86 1.13 0.01 2520791 0.00 0.00 idx_stack_top
0.86 1.14 0.01 1241598 0.00 0.00 protect_color_overflow
0.86 1.15 0.01 1241598 0.00 0.00 refraction
0.86 1.16 0.01 1048576 0.00 0.00 rayConstruction
0.00 1.16 0.00 2558386 0.00 0.00 idx_stack_empty
0.00 1.16 0.00 1241598 0.00 0.00 reflection
0.00 1.16 0.00 1204003 0.00 0.00 idx_stack_push
0.00 1.16 0.00 1048576 0.00 0.00 idx_stack_init
0.00 1.16 0.00 113297 0.00 0.00 fresnel
0.00 1.16 0.00 37595 0.00 0.00 idx_stack_pop
0.00 1.16 0.00 3 0.00 0.00 append_rectangular
0.00 1.16 0.00 3 0.00 0.00 append_sphere
引用:[C++]內嵌函數(inline function)筆記
即便加入inline想要使用內嵌函數,編譯時也不一定就會實作,編譯器會選擇,如果你執行的函數中程式碼所需時間大於處理呼叫函數的時間,則能節省的時間比較少,反之若是你的函數中程式碼執行的時間很短,則使用內前函數可以省去較多的呼叫函數的時間,並且如果常常會使用到此函數,使用內嵌的效率也會比較好
math-toolkit.h
中的函式在第一行都有宣告 static inline, 但是由於關閉了編譯器最佳化, 因此編譯器會將所有函式的 static function 忽略, 不會有任何 inline function
所以要強制函數永遠以 inline 的形式調用
static inline __attribute__((always_inline))
double dot_product(const double *v1, const double *v2)
{
return (v1[0] * v2[0]) + (v1[1] * v2[1]) + (v1[2] * v2[2]);
}
執行結果:
# Rendering scene
Done!
Execution time of raytracing() : 2.027904 sec
執行時間竟然減少一半之多 (2.027904 sec < 4.266808 sec < 4.517215 sec < 5.026474 sec)
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
37.02 0.47 0.47 13861875 0.00 0.00 rayRectangularIntersection
15.75 0.67 0.20 13861875 0.00 0.00 raySphereIntersection
14.18 0.85 0.18 2110576 0.00 0.00 compute_specular_diffuse
11.81 1.00 0.15 2110576 0.00 0.00 localColor
7.88 1.10 0.10 1048576 0.00 0.00 ray_color
4.73 1.16 0.06 4620625 0.00 0.00 ray_hit_object
3.15 1.20 0.04 1241598 0.00 0.00 refraction
2.36 1.23 0.03 1 0.03 1.27 raytracing
1.58 1.25 0.02 1048576 0.00 0.00 rayConstruction
0.79 1.26 0.01 1241598 0.00 0.00 protect_color_overflow
0.79 1.27 0.01 1241598 0.00 0.00 reflection
0.00 1.27 0.00 2558386 0.00 0.00 idx_stack_empty
0.00 1.27 0.00 2520791 0.00 0.00 idx_stack_top
0.00 1.27 0.00 1204003 0.00 0.00 idx_stack_push
0.00 1.27 0.00 1048576 0.00 0.00 idx_stack_init
0.00 1.27 0.00 113297 0.00 0.00 fresnel
0.00 1.27 0.00 37595 0.00 0.00 idx_stack_pop
0.00 1.27 0.00 3 0.00 0.00 append_rectangular
0.00 1.27 0.00 3 0.00 0.00 append_sphere
0.00 1.27 0.00 2 0.00 0.00 append_light
0.00 1.27 0.00 1 0.00 0.00 calculateBasisVectors
0.00 1.27 0.00 1 0.00 0.00 delete_light_list
0.00 1.27 0.00 1 0.00 0.00 delete_rectangular_list
0.00 1.27 0.00 1 0.00 0.00 delete_sphere_list
0.00 1.27 0.00 1 0.00 0.00 diff_in_second
0.00 1.27 0.00 1 0.00 0.00 write_to_ppm
發現subtract_vector
,dot_product
等在上一個版本很花時間的函式都消失了, 因爲都變成 inline function 被展開了