ios - ¿Qué significa el prefijo "simd" en SceneKit?
arkit (2)
SIMD: datos múltiples de una sola instrucción
Las instrucciones SIMD le permiten realizar la misma operación en varios valores al mismo tiempo .
Veamos un ejemplo
Enfoque en serie (NO SIMD)
Tenemos estos 4 valores de Int32
let x0: Int32 = 10
let y0: Int32 = 20
let x1: Int32 = 30
let y1: Int32 = 40
Ahora queremos sumar los valores 2 x
y 2 y
, entonces escribimos
let sumX = x0 + x1 // 40
let sumY = y0 + y1 // 60
Para realizar las 2 sums
anteriores, la CPU necesita
- carga x0 y x1 en la memoria y agrégalos
- carga y0 y y1 en la memoria y agrégalos
Así se obtiene el resultado con 2 operaciones.
He creado algunos gráficos para mostrarte mejor la idea.
Paso 1
Paso 2
SIMD
Veamos ahora cómo funciona SIMD. En primer lugar, necesitamos los valores de entrada almacenados en el formato adecuado de SIMD para
let x = simd_int2(10, 20)
let y = simd_int2(30, 40)
Como se puede ver, los x
y y
son vectores. De hecho, tanto x
como y
contienen 2 componentes.
Ahora podemos escribir
let sum = x + y
Veamos qué hace la CPU para realizar las operaciones anteriores.
- carga xey en la memoria y agrégalos
¡Eso es!
Ambos componentes de x
y ambos componentes de y
se procesan al mismo tiempo .
Programación paralela
NO estamos hablando de programación concurrente, en lugar de eso, es una programación paralela real.
Como se puede imaginar en ciertas operaciones, el enfoque SIMD es mucho más rápido que el de serie.
Kit de escena
Veamos ahora un ejemplo en SceneKit.
Queremos agregar 10
a los componentes x
, y
, z
de todos los descendientes directos del nodo de escena.
Usando el enfoque serial clásico podemos escribir
for node in scene.rootNode.childNodes {
node.position.x += 10
node.position.y += 10
node.position.z += 10
}
Aquí se ejecuta un total de operaciones
childNodes.count * 3
.
Veamos ahora cómo podemos convertir el código anterior en instrucciones SIMD.
let delta = simd_float3(10)
for node in scene.rootNode.childNodes {
node.simdPosition += delta
}
Este código es mucho más rápido que el anterior. No estoy seguro de si es 2x o 3x más rápido pero, créeme, es mucho mejor.
Envolver
Si necesita realizar varias veces la misma operación en un valor diferente, solo use las propiedades SIMD :)
Existe una categoría de SCNNode
llamada SCNNode(SIMD)
, que declara algunas propiedades como simdPosition
, simdRotation
, etc. Parece que estas son propiedades duplicadas de la position
y rotation
propiedades originales / normales.
@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));
¿Cuál es la diferencia entre la position
y simdPosition
? ¿Qué significa exactamente el prefijo "simd"?
SIMD es una pequeña biblioteca construida sobre tipos de vectores que puede importar desde <simd/simd.h>
. Permite un código más expresivo y de mayor rendimiento.
Por ejemplo usando SIMD puedes escribir
simd_float3 result = a + 2.0 * b;
en lugar de
SCNVector3 result = SCNVector3Make(a.x + 2.0 * b.x, a.y + 2.0 * b.y, a.z + 2.0 * b.z);
En Objective-C no puedes sobrecargar los métodos. Eso es que no puedes tener los dos.
@property(nonatomic) SCNVector3 position;
@property(nonatomic) simd_float3 position API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
La nueva API basada en SIMD necesitaba un nombre diferente, y es por eso que SceneKit expone simdPosition
.