可变长度循环对GPU着色器的影响


9

它很流行在GPU内渲染程序内容,例如在演示场景中(绘制单个四边形以填充屏幕并让GPU计算像素)。

雷行军很受欢迎:

在此处输入图片说明

这意味着GPU正在每个像素执行一些未知数量的循环迭代(尽管您可以将上限设为maxIterations)。

具有可变长度的循环如何影响着色器性能?

想象一下简单的光线行进伪代码:

t = 0.f;
while(t < maxDist) {
    p = rayStart + rayDir * t;
    d = DistanceFunc(p);
    t += d;
    if(d < epsilon) {
       ... emit p
       return;
    }
}

各种主流GPU系列(Nvidia,ATI,PowerVR,Mali,Intel等)如何受到影响?顶点着色器,尤其是片段着色器?

如何进行优化?


不幸的是,这个问题很难在这里正确回答。尽管已经给出了一个答案,但指向这样一个值得阅读的资源(涉及动态分支)。为“主题” +1 ..
teodron

1
@teodron不要成为失败主义者!我希望有人会说,在NVidia卡上,8x8像素的屏幕像素将全部迭代到最深的深度,并且8x8像素的像素可以按任何顺序完成,或类似的操作。那是不对的,那只是我希望人们能够分享的那种智慧。嗯,Larrabee上的链接是非常间接的。
2012年

似乎他没有在讨论Larrabee,但在两年后的2010年,这名斯坦福大学的家伙做了同样的演讲(您可以在此处看到)。从他的图来看,考虑一个while循环,我不明白早日“结束”其计算的像素是否可以弥补任何性能。在CUDA中,线程会遇到障碍。以此类推,着色器线程会发生什么?
teodron

@teodron是的,我了解了CUDA并应用于GPU;我确定他们已经步入正轨,但我希望有人博学。总之,这里的一些相关williamedwardscoder.tumblr.com/post/26628848007/rod-marching
威尔

Answers:


8

在GDC 2012上有一个关于GPU距离场射线行进(以及其他主题)的精彩演讲:http : //directtovideo.wordpress.com/2012/03/15/get-my-slides-from-gdc2012/

就性能而言,最新的(DX11级)图形卡在SIMD单元上执行着色器,这些单元以同步方式运行32(NVIDIA)或64(AMD)“线程”。这些组被称为扭曲或波阵面。对于像素着色器,每个线程等于一个像素,因此我希望SIMD单元可以一起处理8x4(NVIDIA)或8x8(AMD)像素块。分支和流控制是在每个波前完成的,因此波前中的所有线程必须循环与该波前中最深的单个像素一样多的次数。SIMD通道遮罩将关闭已完成像素的执行,但是它们仍然必须与整个波前的流控制一起静默运行。当然,这意味着当分支连贯一致时,该系统的效率会大大提高,

以我的经验,即使波前中的所有线程都以相同的方式分支,分支开销仍然很高。通过展开循环以分摊一些分支开销,我已经看到了某些情况下的性能提升。但是,这当然取决于您在每次循环迭代中要完成多少工作。如果循环主体中有足够的“填充物”,则展开将不会成功。



0

关于动态分支,还有一点需要注意(也许是显而易见的,但对某些人来说仍是值得注意的):它会严重影响展开循环的性能(显然,如果迭代次数不是恒定的,则无法展开循环) 。


-4

int s = 0;

现在for(int k = 1; k <= n; k ++){s + = k;}就像s = n *(n + 1)/ 2

所以多数民众赞成在不是真的:D


1
您可能会感到沮丧,因为没人能完全确定您要在此处传达的内容或与问题有什么关系。
doppelgreener 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.