contributed by <shelly4132
>
HaoTse
git add
時可以避免上傳執行結果的圖片安裝一些必要的東西
先clone檔案下來執行看看
結果
將O0改成Ofast,真的很快啊
可使用eog開啟圖片
eog out.ppm
或是將檔案轉換成png的格式
convert out.ppm out.png
圖片
先執行 $ make clean
把剛剛產生的執行檔刪掉
接著執行 $ make PROFILE=1
-pg這個指令可以去追蹤程式執行的時間、幫助我們找到最耗時的function,以及每個function被呼叫的次數等等。
$ ./raytracing
再執行一次可以發現因為多了追蹤程式的時間所以總體執行時間變長了。
接下來就可以執行以下命令看結果
從以下可看出最耗時的為subtract_vector、dot_product和multiply_vector等function,因此優化應該從這前幾名開始著手。
在math-toolkit.h裡可以看到「static inline」這個關鍵字,拆開來看的話
一個static函式表示它定義的範圍是local的,只會在這個檔案被看到。
在呼叫函式時會需要分配記憶空間因而需要額外的資源負擔,所以有些小函式我們可以「建議」編譯器將他設定為「行內函式」(Inline function),如果建議被採納,則該函式會自動在呼叫點展現為程式碼,行內函式建議可以直接定義於表頭檔案中。
所以我們可以把「static inline」理解為一個static的函式被加上了inline的屬性。
另外,如果編譯器優化設定為-O0,必須加上__attribute__((always_inline))強制展開,inline才會有作用。
於是我便在所有inline後面加上__attribute__((always_inline))
然後執行!
非常驚人的效果,執行時間一下子就掉了3秒左右!
這個方法顧名思義就是把迴圈展開,降低branch miss,雖然此法可能會造成程式的可讀性降低,和程式碼變得很冗長,但在一定限度內的展開迴圈的確是優化的好辦法。
以add_vector這個function來看,原本是i從0到2的迴圈,我直接把迴圈拿掉,把全部的運算寫出來。
執行後可以發現時間又降低了大概1秒左右
現在我們再用gprof看一遍,可以發現subtract_vector、dot_product和multiply_vector那些function的排名都掉到很後面了,而rayRectangularIntersection、raySphereIntersection等等則變成比例較高的。
從上面的結果我們看到rayRectangularIntersection、raySphereIntersection所佔耗時間最多的2個,而他們剛好都是被raytracing.c裡的raytracing()所間接呼叫的,又正好raytracing()裡每個pixel是可以獨自運算的,所以我們可以對他做平行處理增加效能。
OpenMP(Open Multi-Processing)是一套支援跨平台共享記憶體方式的多執行緒並行的編程API,使用C,C++和Fortran語言,可以在大多數的處理器體系和作業系統中執行,包括Solaris, AIX, HP-UX, GNU/Linux, Mac OS X, 和Microsoft Windows。包括一套編譯器指令、庫和一些能夠影響執行行為的環境變數。
一開始自己在raytracing()的for迴圈上加了下面這一行
但執行出來的時間幾乎沒有減少
後來才發現原來我忘記去設定thread的數量
開了50個thread後時間就比之前又降了1秒左右
把gprof拿掉之後,距離Ofast最佳化的時間還有一段差距