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

有一个名为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什么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

  1. 在内存中加载x0和x1并添加它们
  2. 在内存中加载y0和y1并添加它们

所以结果是通过2个操作获得的。

SIMD

现在让我们看看SIMD如何工作。 首先,我们需要以正确的SIMD格式存储input值

 let x = simd_int2(10, 20) let y = simd_int2(30, 40) 

正如你所看到的,前面的xy是向量。 Infact xy都包含2个组件。

现在我们可以写

 let sum = x + y 

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

  1. 在内存中加载x和y并添加它们

而已!

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

并行编程

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

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

场景工具包

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

我们想把10添加到场景节点的所有直接后代的xyz分量中。

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

 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