主要观点:
- 纠正计算机图形学爱好者圈子中关于 GPU 中选择两个结果时条件语句的流行误解。
- 指出用“step()”函数替代三元运算符或 if 语句进行所谓“优化”的两种错误,一是对 GPU 工作原理理解错误,原代码无条件分支,只是条件移动;二是这种优化版本运行比原版本慢,因为“step()”函数可能通过条件移动等实现。
- 通过展示原始代码生成的机器代码,证实 GPU 未进行分支,而是进行比较和条件掩码操作。
关键信息:
- 给出包含三元运算符的原始代码
vec2 snap45( in vec2 v ) { vec2 s = sign(v); float x = abs(v.x); return x>0.923880?vec2(s.x,0.0): x>0.382683?s*sqrt(0.5): vec2(0.0,s.y); }
及其优化版本vec2 snap45( in vec2 v ) { vec2 s = sign(v); float x = abs(v.x); float w0 = step(0.92387953,x); float w1 = step(0.38268343,x)*(1.0-w0); float w2 = 1.0-w0-w1; vec2 res0 = vec2(s.x,0.0); vec2 res1 = vec2(s.x,s.y)*sqrt(0.5); vec2 res2 = vec2(0.0,s.y); return w0*res0 + w1*res1 + w2*res2; }
。 - 说明 GPU 能进行真正的分支且快速有效,但对于简单值或计算无分支,且“step()”函数优化浪费。
- 展示 AMD 编译器和 Microsoft 编译器生成的原始代码的机器代码,证实 GPU 未分支而是进行比较和条件掩码操作。
重要细节:
- “step()”函数定义为
float step( float x, float y ) { return x < y? 1.0 : 0.0; }
。 - 提到一些在三元运算符前的“abs()”GLSL 调用在机器代码中是指令修饰符,即“abs()”调用可视为免费的。
- 提醒若看到用“float a = mix( b, c, step( y, x ) );”替代“float a = x < y? b : c;”的优化提议,应予以纠正。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。