我们知道,至少有两种方法来计算a * b + c
:
ret := a*b; ret := ret + c;
ret := fma(a, b, c);
但是在OpenCL C中,还有第三个函数“ mad”,它将精度与性能进行了权衡。
在LunarG sdk中,默认的SPIR-V编译器将编译GLSL和HLSL着色语言,并且GLSL规范v4.60中未提及“ mad”功能。
如何在Vulkan中使用“疯狂”功能?
答案 0 :(得分:2)
这里有些误会。
融合乘法加法并不意味着精度降低。由于在操作步骤之间保持内部硬件精度差异,因此与使用乘法然后加上与fma相比,该数字可能略有不同。因此,在某些API /语言中,默认情况下未启用自动FMA,只有在编译器中使用了快速运算符或特定标志时,才会启用FMA。可能在某些系统中精度会降低,但这并不是它的含义。
但是,在SPIR-V中,虽然似乎没有针对FMA的特定说明,但规范明确预测并允许在SPIR-V-> gpu汇编编译之后进行。它甚至在语言中带有NoContraction
装饰。
无约束 适用于算术指令以指示 操作不能与另一条指令结合形成一个指令 操作。 例如,如果将其应用于OpFMul,则该乘法不能 与加法结合使用以产生融合的乘法加法运算。 此外,不允许此类操作重新关联;例如。, add(a + add(b + c))无法转换为add(add(a + b)+ c)。
请注意,SPIR-V并不是着色器的全部。它只是着色器的可移植中间表示,然后由供应商vulkan驱动程序进一步编译。没有机器直接运行SPIR-V。这类优化留给驱动程序执行,而不是由程序员执行。您通常可以假设这样的优化将在适当的条件下发生,这对于缺少显式FMA内置功能的其他编程语言是相同的。