![]() |
1
32
不幸的是,我认为这里真正的答案是在你的目标硬件上用你的特定情况的性能分析器进行实际测试。特别是考虑到听起来你正处于项目优化阶段;这是唯一考虑到硬件频繁变化和特定材质球性质的方法。 在CPU上,如果出现预测失误的分支,则会导致管道刷新,而且由于CPU管道太深,实际上会丢失20个或更多周期的内容。在GPU上,情况有点不同;管道可能要浅得多,但没有分支预测,所有的着色器代码都将在快速内存中——但这并不是真正的区别。 很难知道每件事情的确切细节,因为nVidia和ATI都比较守口如瓶,但关键是gpu是为大规模并行执行而设计的。有许多异步着色器内核,但每个内核都被设计为运行多个线程。我的理解是,每个核心都希望在任何给定周期的所有线程上运行相同的指令(nVidia将此线程集合称为“warp”)。 在这种情况下,一个线程可能代表一个顶点、一个几何元素或一个像素/片段,而warp则是其中大约32个元素的集合。对于像素,它们很可能是屏幕上彼此靠近的像素。问题是,如果在一个warp中,不同的线程在条件跳转时做出不同的决定,那么warp已经发散,不再为每个线程运行相同的指令。硬件可以处理这个问题,但(至少对我来说)它是如何做到的还不完全清楚。对于每一代连续的卡片,处理方式也可能略有不同。最新的、最通用的CUDA/compute着色友好nvidia可能有最好的实现;较旧的卡可能有较差的实现。更糟糕的情况是,您可能会发现许多线程同时执行if/else语句的两边。 使用着色器的一个重要技巧是学习如何利用这种大规模并行范式。有时这意味着使用额外的过程、临时的屏幕外缓冲区和模板缓冲区将逻辑向上推离着色器并推到CPU上。有时,优化可能会消耗更多的周期,但实际上可能会减少一些隐藏的开销。 还要注意,可以显式地将DirectX着色器中的if语句标记为[branch]或[flatten]。扁平样式为您提供正确的结果,但始终执行指令中的所有内容。如果您没有显式地选择一个,编译器可以为您选择一个——并且可以选择[flatten],这对您的示例不好。 要记住的一点是,如果跳过第一个纹理查找,这将混淆硬件的纹理坐标导数数学。你会遇到编译器错误,最好不要这样做,否则你可能会错过一些更好的纹理支持。 |
![]() |
2
32
如果条件是一致的(即整个过程的常量),则分支基本上是自由的,因为框架将基本上编译着色器的两个版本(执行分支和不执行分支),并根据输入变量为整个过程选择其中一个。在这种情况下,一定要
如果每个顶点/像素的条件都不同,那么它确实会降低性能,而旧的着色器模型甚至不支持动态分支。 |
|
3
26
在许多情况下,这两个分支都可以通过条件作为内插器进行计算和混合。 这种方法比branch快得多。也可以在CPU上使用。 例如: ...
可替换为:
... |
![]() |
4
10
以下是kindle Fire的真实性能基准: 在片段着色器中。。。 它以每秒20帧的速度运行:
它以每秒60帧的速度运行:
|
![]() |
5
8
我不知道基于if的优化,但是如何创建您认为需要的所有纹理查找排列,每个都有自己的着色器,并在正确的情况下使用正确的着色器(取决于需要哪个纹理查找特定模型或模型的一部分)。我想我们在Xbox360的霸王游戏上做了类似的事情。 |
![]() |
Sweepy Dodo · JSON lite的格式化 6 月前 |
![]() |
giantjenga · 优化整数向量到二进制向量的转换 8 月前 |
![]() |
Zegarek · Postgresql递归查询未提供预期结果 8 月前 |
![]() |
Joe · 为什么这两个查询之间的性能存在如此大的差异? 11 月前 |
![]() |
tic-toc-choc · 在`dplyr中高效使用列表进行过滤` 11 月前 |