代码之家  ›  专栏  ›  技术社区  ›  kennyc

解释金属和SIMD中的不同类型

  •  3
  • kennyc  · 技术社区  · 6 年前

    在处理金属时,我发现有很多类型令人困惑,我并不总是清楚我应该在哪种情况下使用哪种类型。

    在苹果的金属着色语言规范中,有一个非常清晰的表,其中列出了金属着色文件中支持的类型。但是,有很多示例代码似乎使用了SIMD中的其他类型。在macOS(Objective-C)方面,金属类型是不可用的,但是SIMD类型是可用的,我不确定应该使用哪种类型。

    例如:

    在金属规格中,有 float2 它被描述为表示两个浮动组件的“向量”数据类型。

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

    • 浮动2 ,这是 typedef ::simd_float2 float2 在向量类型中。h

      注意:“在C或Objective-C中,此类型可用作simd_float2。”


    • vector_float2 ,这是 typedef simd_float2 vector_float2

      注意:“此类型已弃用;应改用simd_float2或simd::float2”


    • simd_float2 ,这是 typedef __attribute__((__ext_vector_type__(2))) float simd_float2

    • ::simd_float2 simd::float2 ?

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

    • matrix_float4x4 , simd_float4x4 , ::simd_float4x4 float4x4 ,

    有人能解释一下为什么会有这么多看起来功能重叠的typedef吗?如果您今天在ObjtoVC/ ObjuleC++中写了一个新的应用程序(2018),您应该使用哪种类型来表示两个浮动值(X/Y),以及哪种类型的矩阵转换可以在应用程序代码和金属之间共享?

    2 回复  |  直到 6 年前
        1
  •  12
  •   warrenm    5 年前

    类型 vector_ matrix_ 前缀已被弃用,取而代之的是 simd_ 前缀,所以一般指导(使用 float4 例如)将是:

    • 在C代码中,使用 simd_float4 键入。(除非您自己提供前缀,否则必须包含前缀) typedef ,因为C没有名称空间。)
    • 对于Objective-C也是如此。
    • 在C++代码中,使用 simd::float4 类型,可以缩短为 浮动4 通过 using namespace simd; .
    • 同样适用于ObjuleC++。
    • 在金属代码中,使用 浮动4 类型,因为 浮动4 是金属着色语言中的一种基本类型[1]。
    • 在Swift代码中,使用 浮动4 类型,因为 辛德_ 类型的类型别名为较短的名称。
    • 更新 :在Swift 5中, 浮动4 相关类型已经被弃用,取而代之的是 SIMD4<Float> 以及相关类型。

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

    既然你没问我,我就改天再谈包装好的。

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

        2
  •  2
  •   Peter Cordes    6 年前

    应该使用哪种类型来表示两个浮点值(x/y)

    如果你能避免的话, 不要 使用单个SIMD向量表示单个几何体 x,y 矢量如果你用的是CPU SIMD。

    当您有许多 相同的 每一个SIMD向量中的东西,因为它们实际上存储在16字节或32字节的向量寄存器中,其中两个向量之间的“垂直”操作很便宜(压缩加法或乘法),但“水平”操作大多只能通过洗牌+垂直操作来完成。

    例如4的向量 x 值和另一个4向量 y 值允许您并行地执行4个点积或4个交叉积,而不进行洗牌,因此每个时钟周期的总吞吐量比向量为 [x1, y1, x2, y2] .

    https://stackoverflow.com/tags/sse/info ,尤其是这些幻灯片: SIMD at Insomniac Games (GDC 2015) 有关规划数据布局和程序设计以并行执行许多类似操作而不是尝试加速单个操作的详细信息。


    这条规则的一个例外是 只有 加/减来转换坐标,因为即使使用结构数组,这仍然是一个纯粹的垂直操作。因此,对于基于16字节向量的CPU短向量SIMD来说是很好的。(例如,一个向量中的第二个元素只与另一个向量中的第二个元素交互,因此不需要洗牌。)


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

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