在SceneKit中,“simd”前缀是什么意思?

23

有一个名为SCNNode(SIMD)SCNNode类别,它声明了一些属性,如simdPositionsimdRotation等。看起来这些是原始/正常属性positionrotation的重复属性。

@property(nonatomic) simd_float3 simdPosition API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
@property(nonatomic) simd_float4 simdRotation API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));

positionsimdPosition有什么区别?前缀"simd"具体是什么意思?


1
https://en.wikipedia.org/wiki/SIMD - luk2302
我一直在想同样的问题:https://dev59.com/EVcP5IYBdhLWcg3wNnjW - Guig
1
虽然不完全相同,但请参考此答案 - rickster
2个回答

65

SIMD:单指令多数据

SIMD 指令允许您同时对多个值执行相同的操作。

让我们看一个例子

串行方法(无 SIMD)

我们有这4个 Int32 值

let x0: Int32 = 10
let y0: Int32 = 20

let x1: Int32 = 30
let y1: Int32 = 40

现在我们想要对2个x值和2个y值进行求和,所以我们写下:

let sumX = x0 + x1 // 40
let sumY = y0 + y1 // 60
为了执行上述两个sums,CPU需要进行以下操作:
  1. 将x0和x1加载到内存中并将它们相加
  2. 将y0和y1加载到内存中并将它们相加
因此,结果可以通过2次操作得出。
我创建了一些图形来更好地展示这个想法。

步骤1

enter image description here

步骤2

enter image description here

SIMD

现在让我们看看SIMD如何工作。 首先,我们需要将输入值存储在适当的SIMD格式中。
let x = simd_int2(10, 20)
let y = simd_int2(30, 40)

正如您所看到的,之前的xy都是向量。实际上,xy都包含2个分量。

现在我们可以写成:

let sum = x + y

让我们看看CPU执行前面操作的过程:

  1. 将x和y加载到内存中并将它们相加

enter image description here

就是这样!

x的两个分量和y的两个分量同时被处理

并行编程

我们不是在谈论并发编程,而是真正的并行编程

可以想象,在某些操作中,SIMD方法比串行方法快得多。

SceneKit

现在让我们看一个在SceneKit中的例子

我们想要将所有场景节点的直接子节点的xyz分量加上10

使用经典的串行方法,我们可以编写

for node in scene.rootNode.childNodes {
    node.position.x += 10
    node.position.y += 10
    node.position.z += 10
}

这里执行了总共childNodes.count * 3次操作。

现在让我们看看如何将先前的代码转换为SIMD指令。

let delta = simd_float3(10)
for node in scene.rootNode.childNodes {
    node.simdPosition += delta
}

这段代码比以前的快得多。我不确定是2倍还是3倍的速度更快,但相信我,它要好得多。

总结

如果您需要对不同的值执行多次相同的操作,只需使用SIMD属性:)


7
非常出色的解释!非常感谢。 - ooOlly
2
这基本上是正确的,但并没有完全涉及到问题的核心。 SIMD 库中的类型不仅仅为像向量加法这样的操作提供了方便的语法(毕竟,在 Swift 中至少通过扩展 SCNVector3 可以很容易地实现相同的功能)。该库还构建为使用 CPU 特定的向量指令(在 ARM 和 x86 上)提供这些操作的快速实现。它还为多个框架使用提供了向量和矩阵的共享“词汇表”,包括 ARKit、GameplayKit、Model I/O 和 Metal 着色器语言。 - rickster
嘿@Luca,非常感谢你的详细回答!我和我的团队遇到了一个问题,已经卡了好几天了 :/ 我发了一个有趣的问题:https://stackoverflow.com/questions/63662318/arkit-apply-filter-cifilter-to-a-specific-part-vertex-of-an-arfaceanchor 希望能听到你的建议! - Roi Mulia

9

SIMD是建立在向量类型之上的一个小型库,您可以从<simd/simd.h>导入它。它允许编写更具表现力和更高效的代码。

例如,使用SIMD,您可以编写以下代码:

simd_float3 result = a + 2.0 * b;

替代

SCNVector3 result = SCNVector3Make(a.x + 2.0 * b.x, a.y + 2.0 * b.y, a.z + 2.0 * b.z);

在Objective-C中,您不能重载方法。也就是说,不能同时存在以下两种情况:
@property(nonatomic) SCNVector3 position;
@property(nonatomic) simd_float3 position API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));

新的基于SIMD的API需要一个不同的名称,这就是为什么SceneKit暴露了"simdPosition"的原因。

有意义的好答案。 - ooOlly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接