23

有一个SCNNode名为 的类别SCNNode(SIMD),它声明了一些属性,例如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));

position和有什么区别simdPosition?前缀“simd”到底是什么意思?

4

2 回答 2

63

SIMD:单指令多数据

SIMD 指令允许您同时对多个值执行相同的操作

让我们看一个例子

串行方法(无 SIMD)

我们有这 4 个 Int32 值

let x0: Int32 = 10
let y0: Int32 = 20

let x1: Int32 = 30
let y1: Int32 = 40

现在我们要将 2x和 2 的y值相加,所以我们写

let sumX = x0 + x1 // 40
let sumY = y0 + y1 // 60

为了执行前面sums的 2 个 CPU 需要

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

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

我创建了一些图形来更好地向您展示这个想法

步骤1

在此处输入图像描述

第2步

在此处输入图像描述

SIMD

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

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

如您所见,xy是向量。事实上两者都x包含y 2 个组件。

现在我们可以写

let sum = x + y

让我们看看 CPU 做了什么来执行前面的操作

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

在此处输入图像描述

而已!

的两个组件x和两个组件y同时处理

并行编程

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

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

场景套件

现在让我们看看 SceneKit 中的一个示例

我们要添加10到场景节点的所有直系后代的xy和组件中。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 属性 :)

于 2017-06-27T19:14:33.983 回答
9

SIMD 是一个基于向量类型的小型库,您可以从中导入<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.

于 2017-06-27T18:48:19.653 回答