在寫shader的時候,其實一些寫法對於其執行影響非常大,而且由於gpu和cpu在架構上的不同,**的優化思想也不一樣,最近一直在寫幾個shader,為了效能問題,查閱了很多資料,把一些tips總結下來。
首先要樹立幾個思想:
1.gpu是simd的架構,即單指令多資料流架構,即在gpu上同時執行n個資料和執行1個資料的效率是一樣的,我們要
盡量的把並行的計算搬到gpu上
2.gpu是以向量計算為基礎設計的,也就是說在gpu上執行乙個向量乘法和執行乙個float的乘法的效率是一樣的,
並不向cpu那樣要多執行幾次
所以1.盡量把一些計算合併成向量計算,記住乙個向量計算和乙個float計算那樣快!
比如 float x,y;
x = x * a;
y = y * b;
不如寫成 float2 v = float2(x,y);
v = v*float2(a,b);
因為前一種寫法是兩次乘法計算,而後一種只要1次
2.不要在gpu裡面用分支或者條件判斷這種語句,儘管大多數gpu 的shader支援這種語法,但是多數gpu裡面的
這種控制語句涉及到一些同步等消耗的操作,
其實大多數這種語句都可以用數值的方式替代。
比如 你想寫
float4 a;
if(b > 1)
else
可以改寫成
float4 a;
float tmp = step(b,1);
a = tmp * 0.5 + (1-tmp);
if else可以被step出來的0 或1的乘法代替又比如
float4 a;
if(b && c || d && e)
else
可以寫成
float4 a;
float tmp = step(1, (float)b*(float)c + float(d)*float(e));
a = tmp + (1-tmp) * 0.5;
&& 我們用轉換到float後的乘法代替,||可以被判斷加法step 1代替
而這種操作,尤其是shader內建的函式比條件判斷和分支的效率要高很多,別忘了,gpu純粹是為了計算的,而不是
做判斷3.盡量使用shader為我們提供的內建函式,這些內建的函式比我們想象的要快很多,往往應用了某些gpu的特殊
特性。比如要比較a和b誰大用max(a,b),還有例如上面反覆用的step,雖然你可以寫用(float)(a>=1)來替換step(1,a),
但是這還是沒有內建函式更快的,包括常用的saturate()把乙個數歸到0-1,總之一句話,如果能用乙個內建函式替換
你的某些**,就盡量替換。而且這些內建函式基本上都是支援對向量操作的,所以如果用step(a,fixed3(1,2,3))其
實只是一條指令,但是卻可以同時返回用a同1 2 3分別比較的結果。
4.使用swizzle是非常快的,例float4 a = float4(1,1,1,1),用a.wz = float2(2,3)要比 a.w=3; a.z=2要高效很多
5.使用合適的資料型別,大部分gpu支援f的數值型別基本上分為fixed half float,分別是12位的定點數,16位的浮
點數以及32位的浮點數,盡可能的選擇位數更少的資料型別來加快操作
摘錄一些有關Shader優化的問題
1。減少代數運算.如果可以自己展開的先展開利於編譯器優化 例如 普通的球面帖圖投射常常表示為 p sqrt rx2 ry2 rz 1 2 這可以展開為 p sqrt rx2 ry2 rz2 2rz 1 2.不要把向量值放入含有多個內插值的標量部件中 tangent float4 tangentvec...
rake db migrate學會的一些tips
在對著書本學習ror的時候,執行rake db migrate出現了一堆問題 1.首先rake版本衝突,本地是10,然後需要是0.8.7,解決辦法 先解除安裝最新版本rake gem unistall rake v 10.0.3,然後安裝rake0.8.7 gem install rake 0.8....
rake db migrate學會的一些tips
在對著書本學習ror的時候,執行rake db migrate出現了一堆問題 1.首先rake版本衝突,本地是10,然後需要是0.8.7,解決辦法 先解除安裝最新版本rake gem unistall rake v 10.0.3,然後安裝rake0.8.7 gem install rake 0.8....