我正在制作一個分形發生器,它需要非常快。目前正在根據用戶公式生成一行OpenCL C:
// User inputs z^2 c z^2 for example, generating this line of code:
z = cpow(z, 2) c cpow(z, 2);
我的問題是,當這條線被編譯成匯編時,它會執行cpow(z, 2)兩次計算來計算運算式,還是 OpenCL C 優化為只進行一次計算,并在遇到第二次時重用該結果cpow(z, 2)?
uj5u.com熱心網友回復:
任何編程語言的一般規則:永遠不要相信編譯器會為你做任何優化。
對于某些簡單的事情,您可以確定 OpenCL 編譯器會進行優化。例子:
float x = y (2.0f/3.0f 4.0f);// 編譯器將使用文字預先計算算術,只要它不改變操作的順序,并且在匯編中你只會得到一個加法。所以使用括號!if(x<y) x = 4; else x = 5;// 編譯器將在此處消除分支并使用與三元運算子相同的程式集float y = a*x c;// 編譯器將把它壓縮在一個單一的融合乘加 (FMA) 指令中,該指令在一個時鐘周期內執行乘法和加法for(int i=0; i<8; i ) x = x%y;// 編譯器將展開回圈,因此不會浪費時鐘周期來增加 ifloat x = some complicated arithmetic; but then x is never used;// 編譯器將洗掉 x 和所有用于計算其值的算術
但是仍然有很多陷阱——第一個例子中的小細節沒有寫括號——導致編譯器沒有優化到最大程度。您可以使用https://godbolt.org/進行試驗,看看哪些有效,哪些無效。在帶有 Nvidia GPU 的 OpenCL 中,您可以生成 PTX 程式集并對其進行研究。
此外,編譯器不太聰明,并不總是生成完美優化的程式集。在您的示例中,無論編譯器設定如何,實作理想性能的安全方法是以優化的方式撰寫它:
z = 2*z*z c; // The pow function is way slower than just a multiplication. In OpenCL, the compiler here will see a*b c and compress that into a FMA instruction. So 1 multiplication and 1 FMA for this line.
一個典型的技巧是對方程中的冗余項使用臨時變數,然后在出現該項的任何地方插入變數。
如果編譯器沒有正確優化,除了次優性能之外,使用浮點運算,您還可能通過較大的舍入誤差獲得次優精度,因為這取決于您添加的數字和順序。您應該在代碼中手動控制和優化它;通常編譯器不會改變操作的順序。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/495920.html
