有没有办法在 Vulkan SPIR-V 中使用 OpenCL C mad 函数?

Is there a way to use OpenCL C mad function in Vulkan SPIR-V?

我们知道,至少有两种方法可以计算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 着色语言,"mad" 函数在 GLSL 规范 v4.60 中未提及。

如何在 Vulkan 中使用 "mad" 功能?

这里有点误会

融合乘加并不意味着精度较低。它可能意味着一个数字与先乘后加 vs fma 略有不同,因为内部硬件精度在操作步骤之间存在差异。出于这个原因,在某些 API's/languages 中,默认情况下不启用自动 FMA,只有在编译器中使用 fast-math 或特定标志时才会启用。可能存在导致精度较差的系统,但这并不是它所暗示的。

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

NoContraction Apply to an arithmetic instruction to indicate the operation cannot be combined with another instruction to form a single operation. For example, if applied to an OpFMul, that multiply can’t be combined with an addition to yield a fused multiply-add operation. Furthermore, such operations are not allowed to reassociate; e.g., add(a + add(b+c)) cannot be transformed to add(add(a+b) + c).

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