contributed by <linachiu
>
shelly4132
$ sudo apt-get update
$ sudo apt-get install graphviz
$ sudo apt-get install imagemagick
$ make
$ ./raytracing
結果
# Rendering scene
Done!
Execution time of raytracing() : 3.209233 sec
和跑出一張光影圖
使用以下指令將他轉為png檔
$ convert out.ppm out.png
GNU的工具
使用方式
-pg
的參數,編譯器會在各函數中加入mcount函數$ ./raytracing gprof -b raytracing gmon.out | less
執行gmon.out$ gprof ./raytracing | less
可以看每個函式所佔時間比率gprof v.s perf
perf top 的原理是每隔一段時間採樣一次,最後根據這些資料輸出,因此採樣的頻率可能會造成結果的不同。
先做$ make clean
$ make PROFILE=1
重新編譯 (使用gprof)
./raytracing gprof -b raytracing gmon.out | less
我們得到
# Rendering scene
Done!
Execution time of raytracing() : 7.402606 sec
時間上比剛才多出了很多,為什麼呢?
因為編譯器會在每個函數中加入 mcount 函數,在執行的時候記錄相關資訊。這些資訊會儲存至 gmon.out 中,最後呼叫 gprof 來繪製相關表格。
$ gprof ./raytracing | less
因為很多所以只列出前幾個
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
20.83 0.61 0.61 69646433 0.00 0.00 dot_product
19.12 1.17 0.56 56956357 0.00 0.00 subtract_vector
8.54 1.42 0.25 10598450 0.00 0.00 normalize
8.37 1.67 0.25 31410180 0.00 0.00 multiply_vector
8.03 1.90 0.24 13861875 0.00 0.00 rayRectangularIntersection
8.03 2.14 0.24 13861875 0.00 0.00 raySphereIntersection
6.83 2.34 0.20 4620625 0.00 0.00 ray_hit_object
3.42 2.44 0.10 17821809 0.00 0.00 cross_product
3.24 2.53 0.10 4221152 0.00 0.00 multiply_vectors
2.90 2.62 0.09 17836094 0.00 0.00 add_vector
2.05 2.68 0.06 1048576 0.00 0.00 ray_color
1.71 2.73 0.05 2110576 0.00 0.00 compute_specular_diffuse
1.71 2.78 0.05 2110576 0.00 0.00 localColor
1.54 2.82 0.05 3838091 0.00 0.00 length
我們可以發現 dot_product 函數執行時間佔了最多,就讓我們來看看 dot_product 長怎麼樣
避免用圖片呈現原始程式碼,請改正 jserv
看起來很正常的for loop ,但是其實其中牽扯到了branch 分支,我們可以使用減少MIPS的方式來優化他
像是 dot_product 這樣可以簡單展開又不會影響閱讀的loop,其實就可以使用Loop unrolling 的方式優化
# Rendering scene
Done!
Execution time of raytracing() : 6.884073 sec
可以發現 Loop unrolling 後,執行時間從原本的 7.402606 sec 降至 6.884073 sec
看看各函式的執行時間
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
20.53 0.55 0.55 56956357 0.00 0.00 subtract_vector
13.44 0.91 0.36 13861875 0.00 0.00 rayRectangularIntersection
11.57 1.22 0.31 69646433 0.00 0.00 dot_product
10.83 1.51 0.29 10598450 0.00 0.00 normalize
8.96 1.75 0.24 31410180 0.00 0.00 multiply_vector
8.03 1.97 0.22 17836094 0.00 0.00 add_vector
7.09 2.16 0.19 13861875 0.00 0.00 raySphereIntersection
6.35 2.33 0.17 17821809 0.00 0.00 cross_product
2.99 2.41 0.08 1048576 0.00 0.00 ray_color
2.61 2.48 0.07 4620625 0.00 0.00 ray_hit_object
1.87 2.53 0.05 2110576 0.00 0.00 compute_specular_diffuse
1.49 2.57 0.04 4221152 0.00 0.00 multiply_vectors
1.12 2.60 0.03 1048576 0.00 0.00 rayConstruction
1.12 2.63 0.03 1 0.03 2.68 raytracing
我們可以在位優化前的表格中發現 math-toolkit.h 中的函示幾乎都排在前幾名, 這裡使用force inline 的方式將static inline 改成 attribute((always_inline))強制開啟inline。
因為我們不使用編譯器的最佳化,所以在編譯時會產生許多warming
# Rendering scene
Done!
Execution time of raytracing() : 5.294769 sec
執行後發現從 6.884073 sec 又少了 1.6秒
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
35.19 0.99 0.99 13861875 0.00 0.00 rayRectangularIntersection
12.68 1.34 0.36 13861875 0.00 0.00 raySphereIntersection
9.29 1.60 0.26 31410180 0.00 0.00 multiply_vector
8.22 1.83 0.23 2110576 0.00 0.00 compute_specular_diffuse
7.15 2.03 0.20 17821809 0.00 0.00 cross_product
6.61 2.22 0.19 17836094 0.00 0.00 add_vector
6.43 2.40 0.18 4620625 0.00 0.00 ray_hit_object
3.57 2.50 0.10 1048576 0.00 0.00 ray_color
2.14 2.56 0.06 1 0.06 2.78 raytracing
1.79 2.61 0.05 4221152 0.00 0.00 multiply_vectors
1.43 2.65 0.04 2110576 0.00 0.00 localColor
1.07 2.68 0.03 1241598 0.00 0.00 refraction
0.71 2.70 0.02 1241598 0.00 0.00 protect_color_overflow
0.71 2.72 0.02 1048576 0.00 0.00 idx_stack_init
0.71 2.74 0.02 1048576 0.00 0.00 rayConstruction
0.71 2.76 0.02 subtract_vector
原本的前三名也都到後面去了