解释 Metal 和 SIMD 中的不同类型

Explaining the different types in Metal and SIMD

在使用 Metal 时,我发现类型的数量多得令人眼花缭乱,而且我并不总是很清楚应该在哪种上下文中使用哪种类型。

在 Apple 的 Metal Shading Language Specification 中,有一个非常明确的 table Metal 着色器文件支持哪些类型。但是,有大量示例代码似乎使用了属于 SIMD 一部分的其他类型。在 macOS (Objective-C) 方面,Metal 类型不可用,但 SIMD 类型可用,我不确定应该使用哪些。

例如:

在 Metal Spec 中,float2 被描述为代表两个浮动组件的 "vector" 数据类型。

在应用程序方面,以下所有内容似乎都以某种身份使用或表示:





矩阵类型也存在类似情况:


有人能解释一下为什么有这么多看起来功能重叠的 typedef 吗?如果您今天(2018 年)在 Objective-C / Objective-C++ 中编写一个新应用程序,您应该使用哪种类型来表示两个浮点值 (x/y) 以及哪种类型用于矩阵转换可以在应用程序代码和 Metal 之间共享吗?

具有 vector_matrix_ 前缀的类型已被弃用,取而代之的是具有 simd_ 前缀的类型,因此一般指南(以 float4 为例) 将是:

  • 在 C 代码中,使用 simd_float4 类型。 (除非您提供自己的 typedef,否则您必须包含前缀,因为 C 没有名称空间。)
  • 与 Objective-C 相同。
  • 在 C++ 代码中,使用 simd::float4 类型,您可以通过 using namespace simd; 将其缩短为 float4
  • 与 Objective-C++ 相同。
  • 在 Metal 代码中,使用 float4 类型,因为 float4 是 Metal Shading Language [1] 中的基本类型。
  • 在 Swift 代码中,使用 float4 类型,因为 simd_ 类型被别名化为较短的名称。
  • 更新:在Swift 5 中,float4 和相关类型已被弃用,取而代之的是SIMD4<Float> 和相关类型。

这些类型在根本上都是等价的,并且都具有相同的大小和对齐特征,因此您可以跨语言使用它们。也就是说,事实上,simd框架的设计目标之一。

关于打包类型的讨论改天再说,因为你没有问。

[1] Metal 是一种不寻常的情况,因为它在全局命名空间中定义了 float4,然后将其导入到 metal 命名空间中,该命名空间也作为 simd 命名空间导出.它还将 float4 别名为 vector_float4。因此,您可以为该向量类型使用上述任何名称(simd_float4 除外)。更喜欢 float4.

which type should you use to represent two floating values (x/y)

如果可以避免,不要使用单个 SIMD 向量来表示单个几何图形 x,y 如果您使用 CPU 向量SIMD.

CPU 当每个 SIMD 向量中有许多 same 东西时,SIMD 效果最好,因为它们实际上存储在 16 字节或 32 字节中向量寄存器,其中两个向量之间的 "vertical" 操作很便宜(打包加法或乘法),但 "horizontal" 操作大多只能通过洗牌 + 垂直操作来完成。

例如,一个包含 4 个 x 值的向量和另一个包含 4 个 y 值的向量可以让您并行执行 4 个点积或 4 个叉积而无需改组,因此总吞吐量与 [x1, y1, x2, y2].

向量相比,每个时钟周期的点积要多得多

有关规划数据布局和程序设计以并行执行许多类似操作而不是尝试加速单个操作的更多信息,请参阅 https://whosebug.com/tags/sse/info, and especially these slides: SIMD at Insomniac Games (GDC 2015)


此规则的一个例外是,如果您加/减以转换坐标,因为即使使用结构数组,这仍然是纯粹的垂直操作。因此适用于 CPU 基于 16 字节向量的短向量 SIMD。 (例如,一个向量中的第二个元素仅与另一个向量中的第二个元素相互作用,因此不需要改组。)


GPU SIMD 不同,我认为交错数据没有问题。我不是 GPU 专家。

(我不使用 Objective C 或 Metal,所以我无法帮助您了解它们的类型名称的详细信息,只是底层 CPU 硬件所擅长的。基本上就是这样对于 x86 SSE/AVX、ARM NEON / AArch64 SIMD 或 PowerPC Altivec 也是如此。水平操作速度较慢。)