Il existe une catégorie SCNNode
nommée SCNNode(SIMD)
, qui déclare certaines propriétés comme simdPosition
, simdRotation
et ainsi de suite. Il semble que ce soient des propriétés dupliquées des propriétés originales/normales position
et 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));
Quelle est la différence entre position
et simdPosition
? Que signifie exactement le préfixe "simd"?
Les instructions SIMD vous permettent d'effectuer la même opération sur plusieurs valeurs en même temps .
Voyons un exemple
Nous avons ces 4 valeurs Int32
let x0: Int32 = 10
let y0: Int32 = 20
let x1: Int32 = 30
let y1: Int32 = 40
Maintenant, nous voulons additionner les valeurs 2 x
et 2 y
, donc nous écrivons
let sumX = x0 + x1 // 40
let sumY = y0 + y1 // 60
Pour effectuer les 2 sums
précédentes, le CPU doit
- charger x0 et x1 en mémoire et les ajouter
- charger y0 et y1 en mémoire et les ajouter
Le résultat est donc obtenu en 2 opérations.
J'ai créé des graphiques pour mieux vous montrer l'idée
Étape 1
Étape 2
Voyons maintenant comment fonctionne SIMD. Tout d'abord, nous avons besoin des valeurs d'entrée stockées dans le format SIMD approprié afin
let x = simd_int2(10, 20)
let y = simd_int2(30, 40)
Comme vous pouvez le voir, les x
et y
précédents sont des vecteurs. En fait, x
et y
contiennent 2 composants.
Maintenant on peut écrire
let sum = x + y
Voyons ce que fait le CPU pour effectuer les opérations précédentes
- charger x et y en mémoire et les ajouter
C'est tout!
Les deux composants de x
et les deux composants de y
sont traités en même temps .
Nous ne parlons [~ # ~] pas [~ # ~] de la programmation concurrente, mais plutôt réel parallèle programmation .
Comme vous pouvez l'imaginer dans certaines opérations, l'approche SIMD est beaucoup plus rapide que celle en série.
Voyons maintenant un exemple dans SceneKit
Nous voulons ajouter 10
aux composants x
, y
et z
de tous les descendants directs du nœud de scène.
En utilisant l'approche sérielle classique nous pouvons écrire
for node in scene.rootNode.childNodes {
node.position.x += 10
node.position.y += 10
node.position.z += 10
}
Voici un total de
childNodes.count * 3
les opérations sont exécutées.
Voyons maintenant comment convertir le code précédent dans les instructions SIMD
let delta = simd_float3(10)
for node in scene.rootNode.childNodes {
node.simdPosition += delta
}
Ce code est beaucoup plus rapide que le précédent. Je ne sais pas si 2x ou 3x plus vite mais, croyez-moi, c'est bien mieux.
Si vous devez effectuer plusieurs fois la même opération sur une valeur différente, utilisez simplement les propriétés SIMD :)
SIMD est une petite bibliothèque construite sur types de vecteurs que vous pouvez importer depuis <simd/simd.h>
. Il permet un code plus expressif et plus performant.
Par exemple, en utilisant SIMD, vous pouvez écrire
simd_float3 result = a + 2.0 * b;
au lieu de
SCNVector3 result = SCNVector3Make(a.x + 2.0 * b.x, a.y + 2.0 * b.y, a.z + 2.0 * b.z);
Dans Objective-C, vous ne pouvez pas surcharger les méthodes. Autrement dit, vous ne pouvez pas avoir les deux
@property(nonatomic) SCNVector3 position;
@property(nonatomic) simd_float3 position API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
La nouvelle API basée sur SIMD avait besoin d'un nom différent, et c'est pourquoi SceneKit expose simdPosition
.