"simd" 前缀在 SceneKit 中是什么意思?
What does the "simd" prefix mean in SceneKit?
有一个名为 SCNNode(SIMD)
的 SCNNode
类别,它声明了一些属性,例如 simdPosition
、simdRotation
等。这些似乎是 original/normal 属性 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
有什么区别?前缀 "simd" 到底是什么意思?
SIMD 是一个建立在 vector types 之上的小型库,您可以从 <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
的原因。
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
为了执行前面的 2 个 sums
,CPU 需要
- load x0 and x1 in memory and add them
- load y0 and y1 in memory and add them
所以经过2次运算得到结果
我创建了一些图形来更好地向您展示这个想法
Step 1
Step 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为了执行前面的操作做了什么
- load x and y in memory and add them
就是这样!
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
}
Here a total of childNodes.count * 3
operations is executed.
现在让我们看看如何将之前的代码转换成SIMD指令
let delta = simd_float3(10)
for node in scene.rootNode.childNodes {
node.simdPosition += delta
}
此代码比上一个代码快得多。我不确定是快了 2 倍还是 3 倍,但相信我,它好多了。
总结
如果您需要对不同的值执行多次相同的操作,只需使用 SIMD 属性:)
有一个名为 SCNNode(SIMD)
的 SCNNode
类别,它声明了一些属性,例如 simdPosition
、simdRotation
等。这些似乎是 original/normal 属性 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
有什么区别?前缀 "simd" 到底是什么意思?
SIMD 是一个建立在 vector types 之上的小型库,您可以从 <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
的原因。
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
为了执行前面的 2 个 sums
,CPU 需要
- load x0 and x1 in memory and add them
- load y0 and y1 in memory and add them
所以经过2次运算得到结果
我创建了一些图形来更好地向您展示这个想法
Step 1
Step 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为了执行前面的操作做了什么
- load x and y in memory and add them
就是这样!
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
}
Here a total of
childNodes.count * 3
operations is executed.
现在让我们看看如何将之前的代码转换成SIMD指令
let delta = simd_float3(10)
for node in scene.rootNode.childNodes {
node.simdPosition += delta
}
此代码比上一个代码快得多。我不确定是快了 2 倍还是 3 倍,但相信我,它好多了。
总结
如果您需要对不同的值执行多次相同的操作,只需使用 SIMD 属性:)