本篇文章給大家分享的是有關(guān)Shader中if和for的效率問題以及使用策略是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
在成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設(shè)中從網(wǎng)站色彩、結(jié)構(gòu)布局、欄目設(shè)置、關(guān)鍵詞群組等細(xì)微處著手,突出企業(yè)的產(chǎn)品/服務(wù)/品牌,幫助企業(yè)鎖定精準(zhǔn)用戶,提高在線咨詢和轉(zhuǎn)化,使成都網(wǎng)站營銷成為有效果、有回報(bào)的無錫營銷推廣。創(chuàng)新互聯(lián)建站專業(yè)成都網(wǎng)站建設(shè)十余年了,客戶滿意度97.8%,歡迎成都創(chuàng)新互聯(lián)客戶聯(lián)系。
if和for確實(shí)有效率問題(相比CPU下的情況),但是通常情況無法回避,也就無需處理。
用step代替if,大部分情況是無優(yōu)化或者負(fù)優(yōu)化,只在一些個(gè)別情況下有少量的提升。
可以用Shader變體來取代一些只和固定參數(shù)有關(guān)的if,但這只是為了減少if自身的成本(if和里面執(zhí)行的表達(dá)式畢竟也是指令)
if和for之所以比預(yù)想的要慢,是因?yàn)镚PU的“進(jìn)行計(jì)算的運(yùn)算單元”和“執(zhí)行指令的邏輯單元”并不是一對一對應(yīng)的,而是一對多的關(guān)系。
當(dāng)你執(zhí)行一條指令的時(shí)候,并不是操作一個(gè)像素,而是同時(shí)操作一組像素,并一條一條指令向下執(zhí)行。
如果你的代碼里出現(xiàn)了if,在這組像素中,可能有條件表達(dá)式返回true的,也可能有返回false的。但只要有一個(gè)返回true,下面那條代碼就必須執(zhí)行。而那些不需要執(zhí)行的像素點(diǎn),雖然這次并不需要計(jì)算,但也沒有其他的邏輯單元可以與它們配對工作,所以也只能干等。
后面的else部分也是同理,即使只有一個(gè)像素需要計(jì)算,也需要占用全部資源。
所以,if的效率問題是會導(dǎo)致多個(gè)分支重復(fù)執(zhí)行。
而for的問題也和if類似,會導(dǎo)致循環(huán)邏輯必須以這組像素里最大循環(huán)次數(shù)的那一個(gè)為準(zhǔn)來執(zhí)行。
if的效率低,是因?yàn)樗鼤?dǎo)致多分支重復(fù)執(zhí)行,而不是它自身有多慢。如果你去掉了if,但是執(zhí)行的邏輯還是原本全部分支的總和,并不會有多少改善。step代替if的做法就是如此。
假如考慮是的是if本身這條指令的耗費(fèi)的話。雖然if本身并不算一個(gè)簡單指令,但如果要使用step來代替if,直譯則是這樣:fixed4 c = lerp(c * Color,Color,step(c.a,0.5));
這畢竟是兩條指令,未見得就比if本身要好多少。但如果在某些特定情況能省略掉那條lerp,確實(shí)有可能獲得一些優(yōu)勢(比如:if (x >= 1) x +=1 --> x += step(1,x))
當(dāng)那組像素內(nèi),如果所有c.a > 0.5的判斷都返回false的話,就意味著下面那條指令計(jì)算的結(jié)果全部都會拋棄。這種時(shí)候,GPU還是會正常的跳過這條語句。
所有分支都執(zhí)行只是無奈之舉。只要能夠避免,自然就會避免。
在實(shí)際運(yùn)行環(huán)境中,一批像素內(nèi)全部c.a <= 0.5的情況可能并不那么常見,但只要出現(xiàn)一次,就會導(dǎo)致計(jì)算被跳過,這樣就可能比step的代替方案效率更高。所以,只有在我們基本確信這種情況99%都不會出現(xiàn)的情況,用step代替if才可能是一種“優(yōu)化”,而優(yōu)化幅度也未見得會高到能夠被結(jié)果體現(xiàn)出來。
但假如這種情況很常見,你將if替換成step,反而可能產(chǎn)生明顯的負(fù)優(yōu)化。
這里就有一個(gè)問題:我們應(yīng)該如何判斷,同一批像素全部c.a <= 0.5的概率呢?這就需要知道,什么才叫“同一批像素”。
事實(shí)上,“同一批像素”的分配方式,每種硬件的每一代都是不同的。有豎著掃的,也有和掃描線一樣橫著排的。移動平臺由于都是TBR,還會以一個(gè)方塊作為基礎(chǔ)分布。但不管怎么樣,至少是連續(xù)的。至于這一批像素到底有多少個(gè)……一般的說法是32,但這同樣也是不確定的。
我們能確定的是,假如是這樣一張透明圖片
它有這么大的體積,中間的部分還是實(shí)心的,那么它的像素被分配到同一批次的可能性就很高,也就邊緣會出現(xiàn)兩條分支都執(zhí)行的情況。
但是,像文本這樣的,鏤空較多,概率就比較低,也就可以考慮用step代替if。但是并不保險(xiǎn),你看,其實(shí)連續(xù)不透明部分還是滿多的樣子的嘛,搞不好在某些單個(gè)批次像素?cái)?shù)量較少的機(jī)器上……
適合step代替if的情況,其實(shí)非常有限,大概只有網(wǎng)點(diǎn)圖能算一個(gè)了。
而我在下圖的情景下使用step,與其說是了為避免if,不如說是為了減少指令。
說白了,就是正確使用step代替if收益太少,錯誤使用step代替if代價(jià)太大。如果你沒有絕對的信心,不要用step代替if,尤其是取代分支下有大量復(fù)雜計(jì)算的if。
如果一定要這樣用的話,根據(jù)情況,最好做測試驗(yàn)證下是否會導(dǎo)致性能的下降。
如果和if有關(guān)的參數(shù)是一個(gè)外部變量(Uniform)的話,由于在一個(gè)Pass里它的值是一定不變的,所以同一批次下,也一定會走同一條分支,走多條分支的情況100%不會出現(xiàn)。這時(shí)候還使用step,就是愚蠢至極的做法。
但是,假如是這種情況,則更傾向于用Shader變體的做法,用條件編譯來直接切換不同分支。
這樣可以將那條if語句本身的成本(據(jù)說算上else是4個(gè)時(shí)鐘周期),還有表達(dá)式的成本給消除掉。雖然優(yōu)化幅度不大,但是在frag單元任何一條指令的節(jié)省都是值得的。
但是不做……
其實(shí)也沒什么大礙,Shader變體太多也可能存在內(nèi)存和加載時(shí)間的問題,變體切換也有成本,要根據(jù)實(shí)際情況進(jìn)行選擇了。
以上就是Shader中if和for的效率問題以及使用策略是什么,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。