2016-09-14 37 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 /谁试图加载的替代。

重要的是,对于您的用例,最好的选择是专注于使代码更易于维护;这将为您节省更多时间,并且会让您的程序运行得更好,而不是任何“过早优化”(我们要说清楚,基本上就是您在做什么)。