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 需要
- 在内存中加载 x0 和 x1 并添加它们
- 在内存中加载 y0 和 y1 并添加它们
所以结果是通过2次操作得到的。
我创建了一些图形来更好地向您展示这个想法
第一步
第 2 步
SIMD
现在让我们看看 SIMD 是如何工作的。
首先,我们需要以正确的 SIMD 格式存储输入值,所以
let x = simd_int2(10, 20)
let y = simd_int2(30, 40)
如您所见,前面的 x 和 y 是向量。事实上,x 和 y 都包含 2 个组件。
现在我们可以写了
let sum = x + y
让我们看看 CPU 做了什么来执行前面的操作
- 在内存中加载 x 和 y 并添加它们
就是这样!
x 的两个组件和y 的两个组件同时处理。
并行编程
我们不是谈论并发编程,而是真正的并行编程。
您可以想象,在某些操作中,SIMD 方法比串行方法快得多。
场景套件
现在让我们看看 SceneKit 中的一个示例
我们希望将10 添加到场景节点的所有直系后代的x、y 和z 组件中。
使用经典的串行方法我们可以编写
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 属性 :)