1

众所周知,至少有两种计算方法a * b + c

  1. ret := a*b; ret := ret + c;

  2. ret := fma(a, b, c);

但是在 OpenCL C 中,还有第三个函数称为“mad”,它以精度换取性能。

在 LunarG sdk 中,默认的 SPIR-V 编译器编译 GLSL 和 HLSL 着色语言,并且在 GLSL 规范 v4.60 中没有提到“mad”功能。

如何在 Vulkan 中使用“疯狂”功能?

4

1 回答 1

2

这里有点误会。

融合乘加并不意味着精度降低。这可能意味着与应用乘法然后加法与 fma 的数字略有不同,因为操作步骤之间存在内部硬件精度差异。出于这个原因,在某些 API/语言中,默认情况下不启用自动 FMA,并且仅在编译器中使用快速数学或特定标志时才会出现。可能有一些系统会导致精度降低,但这并不是它所暗示的。

然而,在 SPIR-V 中,虽然似乎没有针对 FMA 的特定指令,但该规范明确预测并允许它发布 SPIR-V -> gpu 汇编编译。它甚至有NoContraction语言的装饰。

NoContraction 应用于算术指令,表示该运算不能与另一条指令组合形成单个运算。例如,如果应用于 OpFMul,则该乘法不能与加法相结合以产生融合乘加运算。 此外,此类操作不允许重新关联;例如,add(a + add(b+c)) 不能转换为 add(add(a+b) + c)。

请注意,SPIR-V 并不是所有着色器的全部。它只是着色器的可移植中间表示,然后由供应商的 vulkan 驱动程序进一步编译。没有机器直接运行 SPIR-V。这些类型的优化留给驱动程序执行,而不是程序员。您通常可以假设这样的优化将在适当的条件下发生,这对于缺少显式 FMA 内置的其他编程语言也是如此。

于 2019-06-24T13:50:14.150 回答