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次操作得出。
我创建了一些图形来更好地展示这个想法。
步骤1
步骤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
现在让我们看一个在SceneKit中的例子
我们想要将所有场景节点的直接子节点的x
、y
和z
分量加上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属性:)