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

Posted

技术标签:

【中文标题】有没有办法在 Vulkan SPIR-V 中使用 OpenCL C mad 函数?【英文标题】:Is there a way to use OpenCL C mad function in Vulkan SPIR-V? 【发布时间】:2019-06-24 08:31:18 【问题描述】:

据我们所知,至少有两种方法可以计算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 中使用“疯狂”功能?

【问题讨论】:

我正在 Khronos 组的 GitHub 上尝试使用 SPIRV-LLVM 翻译器,如果我在 Vulkan 中成功运行 OpenCL C 内核,我将添加我自己的答案;如果内核类型不兼容,我也会指出。 【参考方案1】:

这里有点误会。

融合乘加并不意味着精度较低。这可能意味着与应用乘法然后加法与 fma 的数字略有不同,因为操作步骤之间存在内部硬件精度差异。出于这个原因,在某些 API/语言中,默认情况下不启用自动 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 内置的其他编程语言也是如此。

【讨论】:

我已经在 SPIR-V v1.4rev1 规范中确认,既没有 FMA 也没有 MAD。

以上是关于有没有办法在 Vulkan SPIR-V 中使用 OpenCL C mad 函数?的主要内容,如果未能解决你的问题,请参考以下文章

MLIR,LLVM SPIR-V Getting started初步探索

Vulkan 中子组可访问的本地内存的查询大小

没有任何秘密的 API:Vulkan* 简介

从 SPIR-V 到 ISPC:将 GPU 计算转化为 CPU 计算

由 SPIR-V 的 SPIRV-cross 生成的 GLSL 是不是违反了 std140 规则?

如何使用 OpenGL ARB_gl_spirv 扩展?