Что означает префикс "simd" в SceneKit?

Существует категория SCNNode с именем SCNNode(SIMD), которая объявляет некоторые свойства, такие как 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? Что означает префикс "simd"?

Ответ 1

SIMD: несколько инструкций с несколькими инструкциями

Инструкции SIMD позволяют выполнять одну и ту же операцию с несколькими значениями в одновременно.

Посмотрим пример

Последовательный подход (NO 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 должен

  • загрузите x0 и x1 в память и добавьте их
  • загрузите y0 и y1 в память и добавьте их

Таким образом, результат получается с помощью двух операций.

SIMD

Теперь посмотрим, как работает SIMD. Прежде всего нам нужны входные значения, сохраненные в правильном формате SIMD, поэтому

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

Как вы можете видеть, предыдущие x и y являются векторами. Infact и x и y содержат 2 компонента.

Теперь мы можем написать

let sum = x + y

Посмотрите, что делает процессор для выполнения предыдущих операций.

  • загрузите x и y в память и добавьте их

Что это!

Оба компонента x и оба компонента y обрабатываются одновременно.

Параллельное программирование

Мы НЕ говорим о параллельном программировании, а это реальное параллельное программирование.

Как вы можете себе представить в определенной операции, SIMD-подход быстрее, чем серийный.

Набор сцен

Теперь посмотрим пример в SceneKit

Мы хотим добавить 10 в компоненты x, y и z всех прямых потомков сцены node.

Используя классический последовательный подход, мы можем написать

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:)

Ответ 2

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 нуждался в другом имени и почему SceneKit предоставляет simdPosition.