Objective c 解释Metal和SIMD中的不同类型

Objective c 解释Metal和SIMD中的不同类型,objective-c,macos,cocoa,simd,metal,Objective C,Macos,Cocoa,Simd,Metal,当我使用金属时,我发现有许多令人困惑的类型,我并不总是清楚我应该在哪种情况下使用哪种类型 在苹果的金属着色语言规范中,有一个非常清楚的表格,其中列出了金属着色器文件中支持的类型。但是,有很多示例代码似乎使用了SIMD中的其他类型。在macOS(Objective-C)方面,金属类型不可用,但SIMD类型可用,我不确定应该使用哪些类型 例如: 在Metal规范中,有一个float2,它被描述为代表两个浮动组件的“向量”数据类型 在应用程序方面,以下所有内容似乎都以某种方式使用或表示: float

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

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

例如:

在Metal规范中,有一个
float2
,它被描述为代表两个浮动组件的“向量”数据类型

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

  • float2
    ,它是向量类型中的
    typedef::simd\u float2 float2

    注意:“在C或Objective-C中,此类型作为simd_float2提供。”


  • vector\u float2
    ,即
    typedef simd\u float2 vector\u float2

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


  • simd\u float2
    ,它是
    typedef\uuuuu属性\uuuu((\uuuu ext\u vector\u type\uuuu2)))浮点simd\u float2

  • ::simd\u float2
    simd::float2

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

  • 矩阵浮点数4x4
    单指令多数据浮点数4x4
    ::单指令多数据浮点数4x4
    浮点数4x4


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

前缀为
vector\uu
matrix\u
的类型已被弃用,取而代之的是前缀为
simd\u
的类型,因此一般指南(以
float4
为例)是:

  • 在C代码中,使用
    simd_float4
    类型。(除非您提供自己的
    typedef
    ,否则必须包含前缀,因为C没有名称空间。)
  • 目标C也是如此
  • < LI>在C++代码中,使用<代码> SIMD::FLUAT4/Cux>类型,您可以使用<命名空间SIMD >代码< >代码> FLUAT4/COD>;代码>
  • Objective-C++也一样
  • 在金属代码中,使用
    float4
    类型,因为
    float4
    是金属着色语言[1]中的基本类型
  • 在Swift代码中,使用
    float4
    类型,因为
    simd\uz
    类型的别名较短
  • 更新:在Swift 5中,
    float4
    和相关类型已被弃用,取而代之的是
    SIMD4
    和相关类型
这些类型基本上都是等效的,并且都具有相同的大小和对齐特征,因此您可以跨语言使用它们。这实际上是simd框架的设计目标之一

既然你没问,我就把关于打包类型的讨论留到另一天再说

[1] Metal是一种不常见的情况,因为它在全局命名空间中定义
float4
,然后将其导入
Metal
命名空间,该命名空间也作为
simd
命名空间导出。它还将
float4
别名为
vector\u float4
。因此,您可以将上述任何名称用于此向量类型(除了
simd\u float4
)。首选
float4

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

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

当每个SIMD向量中有许多相同的内容时,CPU SIMD工作得最好,因为它们实际上存储在16字节或32字节的向量寄存器中,其中两个向量之间的“垂直”操作(压缩加法或乘法)很便宜,但“水平”操作大多只能通过无序+垂直操作来完成

例如,一个值为4
x
的向量和另一个值为4
y
的向量允许您并行执行4个点积或4个交叉积,而无需混洗,因此与向量为
[x1,y1,x2,y2]
相比,每个时钟周期的总吞吐量显著增加点积

请参阅,尤其是这些幻灯片:了解更多有关规划数据布局和程序设计的信息,以便并行执行许多类似操作,而不是试图加速单个操作


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


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


(我不使用Objective C或Metal,因此我无法帮助您了解其类型名称的详细信息,这正是底层CPU硬件所擅长的。x86 SSE/AVX、ARM NEON/AArch64 SIMD或PowerPC Altivec基本相同。水平操作速度较慢。)

感谢您的输入和更多见解。很高兴了解到,无论数据是由CPU还是GPU处理,都需要考虑不同的因素。苹果公司通常在金属样品中使用float2或float3