着色器中的循环性能


11

我想知道在着色器中集成动态循环功能的最佳方法是什么?

首先,似乎动态数组是不可能的。因此,创建最大大小的数组并仅填充其中一部分或使用预定义的大小定义数组会更好吗?

那么,迭代此数组的最佳方法是什么?

使用展开循环或动态循环进行4到128次迭代比较好吗?我还看到有可能将其展开到最大的预定义迭代次数,然后使用诸如的条件将其停止if (i == myCurrentMaximumIterationNumber)


2
您想对数组和循环做什么?我问是因为这听起来有点像XY问题。由于在GPU上使用条件和循环的最佳方法是避免使用它们,因此在您的情况下,也许还有更好的方法来代替使用数组和循环。
Nero

我正在实现当前有效的屏幕空间次表面散射效果。但是我对根据性能使用内核的方式有些怀疑。我选择最大数组大小并只填充一部分,并使用具有动态迭代次数的动态循环,该循环与当前使用的数组内容有关。我认为例如根据性能对着色器进行编程时,有些事情要做或知道。在我看来,循环是一个常见的性能主题,可能遵循一些规则,甚至遵循“良好实践”,但我没有找到任何好的答案。
2013年

Answers:


6

Shader编译器对于展开非常激进,因为早期的硬件通常没有流控制,而较新的硬件的成本可能会有所不同。如果您有正在积极测试的基准测试以及一系列相关的硬件,请尝试尝试一下以了解会发生什么。动态循环比静态循环更适合开发人员干预-但是除非有基准可用,否则将其留给编译器仍然是一个好建议。有了基准,探索是值得的(而且很有趣)。

顺便说一句,在GPU上进行动态循环的最大损失是波前/翘曲中的各个“线程”将在不同的时间结束。稍后停止的线程将强制所有提前完成的线程执行NOP。

应当仔细考虑嵌套循环:我实现了一个基于块的熵解码器,该编码器对零的游程进行编码(用于JPEG之类的压缩)。自然的实现是在一个紧密的内部循环中对运行进行解码-这意味着通常只有一个线程在进步。通过展平循环并在每个线程中显式测试当前是否正在解码运行,我通过固定长度循环(解码块的大小都相同)使所有线程保持活动状态。如果线程像CPU线程一样,更改将是非常糟糕的,但是在我运行的GPU上,我的性能提高了6倍(这仍然很糟糕-没有足够的块来保持GPU繁忙-但这是概念的证明)。

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.