2016-09-14 69 views
8

所有現代GPU都有標量體系結構,但着色語言提供各種矢量和矩陣類型。我想知道,GLSL源代碼的標量化或矢量化如何影響性能。例如,讓我們定義一些「標」要點:GLSL:標量vs矢量性能

float p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; 
p0x = 0.0f; p0y = 0.0f; 
p1x = 0.0f; p1y = 0.61f; 
p2x = 0.9f; p2y = 0.4f; 
p3x = 1.0f; p3y = 1.0f; 

及其矢量等效:

vec2 p0 = vec2(p0x, p0y); 
vec2 p1 = vec2(p1x, p1y); 
vec2 p2 = vec2(p2x, p2y); 
vec2 p3 = vec2(p3x, p3y); 

有了這點,這下面的代碼數學上等價塊將運行得更快?

標代碼:

position.x = -p0x*pow(t-1.0,3.0)+p3x*(t*t*t)+p1x*t*pow(t-1.0,2.0)*3.0-p2x*(t*t)*(t-1.0)*3.0; 
position.y = -p0y*pow(t-1.0,3.0)+p3y*(t*t*t)+p1y*t*pow(t-1.0,2.0)*3.0-p2y*(t*t)*(t-1.0)*3.0; 

或它的載體相當於:

position.xy = -p0*pow(t-1.0,3.0)+p3*(t*t*t)+p1*t*pow(t-1.0,2.0)*3.0-p2*(t*t)*(t-1.0)*3.0; 

或者他們會在現代GPU上等效地運行嗎?

上面的代碼只是一個例子。這種「可矢量化」代碼的實際例子可以執行更重的計算,其中來自全局ins,制服和頂點屬性的輸入變量更多。

+5

重要嗎?矢量形式比未經版本化的形式更可讀。做一些有意義的事情,讓編譯器完成它的工作。 –

+0

正如@NicolBolas所說的,glsl優化器在編譯之前做了很多優化。所以我猜想這兩個代碼將被優化到相同的形式。或者,做一個基準可以給你更多的信息。 – codetiger

+1

@NicolBolas:是的,這很重要,尤其是因爲你不知道用戶將擁有哪些驅動程序。當然,80%的時間我不在乎,但是當我需要表演時,20%的時間我問自己同樣的問題(並且找不到明確的答案)。 – ybungalobill

回答

2

最好的辦法是對你認爲可以與該代碼一起使用的所有系統(即GPU)品種進行基準測試,並計算出Vectorized代碼更快,以及Scalarized更快碼。然後你可以編寫這兩個版本的代碼(或者更可能是多個版本),並編寫運行時邏輯,根據正在使用的GPU /驅動程序來切換使用哪個版本。

這當然是一個巨大的麻煩。大多數程序員不會那樣做; GPGPU程序員通常只有一個服務器/ GPU節點類型,因此他們的代碼將專門針對單一架構進行量身定製。與此同時,在AAA遊戲工作室(這是另一個有足夠的預算和人力來處理這類任務的地方),他們通常會讓NVidia和AMD在他們的最終解決方案中找到這種魔力,NVidia/AMD將會寫得更好,這些遊戲使用的着色器的更優化版本,將它們添加到它們的驅動程序中,並告訴驅動程序在更好的着色器中替代任何Gearbox/Bethesda /誰試圖加載的替代。

重要的是,對於您的用例,最好的選擇是專注於使代碼更易於維護;這將爲您節省更多時間,並且會讓您的程序運行得更好,而不是任何「過早優化」(我們要說清楚,基本上就是您在做什麼)。