在SceneKit中,“simd”前缀是什么意思?
有一个名为SCNNode(SIMD)
的SCNNode
类别,它声明了一些属性,如simdPosition
, simdRotation
等等。 看来这些是原来的/正常的属性position
和rotation
重复属性。
@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));
position
和simdPosition
什么simdPosition
? 前缀“simd”是什么意思?
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
为了执行CPU需要的前两个sums
- 在内存中加载x0和x1并添加它们
- 在内存中加载y0和y1并添加它们
所以结果是通过2个操作获得的。
SIMD
现在让我们看看SIMD如何工作。 首先,我们需要以正确的SIMD格式存储input值
let x = simd_int2(10, 20) let y = simd_int2(30, 40)
正如你所看到的,前面的x
和y
是向量。 Infact 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属性:)
SIMD是一个build立在vectortypes之上的小型库,可以从<simd/simd.h>
导入。 它允许更具performance力和更高性能的代码。
例如使用SIMD你可以写
simd_float3 result = a + 2.0 * b;
代替
SCNVector3 result = SCNVector3Make(ax + 2.0 * bx, ay + 2.0 * by, az + 2.0 * bz);
在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
。