vectores producto por multiplicacion escalar c x86 sse simd

producto - multiplicacion de vectores en r2



SSE(SIMD): multiplicar el vector por escalar (3)

Una operación común que hago en mi programa es escalar los vectores por un escalar (V * s, por ejemplo [1,2,3,4] * 2 == [2,4,6,8]). ¿Hay una instrucción SSE (o AVX) para hacer esto, aparte de cargar primero el escalar en cada posición en un vector (por ej. _mm_set_ps (2,2,2,2)) y luego multiplicar?

Esto es lo que hago ahora:

__m128 _scalar = _mm_set_ps(s,s,s,s); __m128 _result = _mm_mul_ps(_vector, _scalar);

Estoy buscando algo como ...

__m128 _result = _mm_scale_ps(_vector, s);


Dependiendo de su compilador, puede mejorar un poco la generación de código usando _mm_set1_ps :

const __m128 scalar = _mm_set1_ps(s); __m128 result = _mm_mul_ps(vector, scalar);

Sin embargo, las constantes escalares como esta solo deberían inicializarse una vez, fuera de cualquier bucle, por lo que el costo de rendimiento debería ser irrelevante. (A menos que el valor escalar esté cambiando dentro del ciclo?)

Como siempre, deberías mirar el código que genera tu compilador y también intentar ejecutar tu código bajo un perfil decente para ver dónde están realmente los puntos de acceso.


No sé de ninguna instrucción que haga lo que quieres. ¿Es la operación establecida realmente un cuello de botella? Si está multiplicando un vector grande por la misma constante, el tiempo que lleva llenar un registro XMM / YMM con cuatro copias de la constante debe ser una fracción muy pequeña del tiempo total empleado.

Como una optimización simple, si la constante es 2 como lo fue en su ejemplo, podría reemplazar la multiplicación por una instrucción de agregar, sin requerir ninguna constante.


No hay instrucciones para la multiplicación de un vector por un escalar. Sin embargo, hay algunas instrucciones para cargar los mismos valores escalares en todas las posiciones en un registro vectorial.

El conjunto de instrucciones AVX proporciona _mm_broadcast_ss / _mm256_broadcast_ss / _mm256_broadcast_sd para _mm256_broadcast_sd registros SSE y AVX con el mismo valor flotante / doble.

En el conjunto de instrucciones SSE3, puede encontrar _mm_loaddup_pd intrinsic que completa el registro SSE con el mismo doble valor.

En otras versiones de SSE, la mejor opción es cargar un valor escalar utilizando _mm_load_ss / _mm_load_sd y luego copiarlo a todos los elementos de un registro vectorial con _mm_shuffle_ps / _mm_unpacklo_pd .