2012-01-31 69 views
17

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 alguna instrucción SSE (o AVX) para hacer esto, aparte de cargar primero el escalar en cada posición en un vector (por ejemplo _mm_set_ps (2,2,2,2)) y luego multiplicar?SSE (SIMD): multiplicar el vector por escalar

Esto es lo que hago ahora:

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

Busco algo así como ...

__m128 _result = _mm_scale_ps(_vector, s); 

Respuesta

13

dependiendo de su compilador que puede ser capaz de mejorar la generación de código un poco mediante el uso de _mm_set1_ps:

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

constantes Sin embargo escalares como éste sólo deberían necesitar ser inicializado una vez, fuera de cualquier bucle, por lo que el rendimiento el costo debe ser irrelevante. (A menos que el valor escalar esté cambiando dentro del ciclo?)

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

0

No sé de cualquier instrucción única que hace lo que quiere. ¿Es la operación establecida realmente un cuello de botella? Si está multiplicando un vector grande por la misma constante, el tiempo que lleva completar 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, puede reemplazar la multiplicación por una instrucción add en su lugar, sin requerir ninguna constante.

4

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.

conjunto de instrucciones AVX ofrece _mm_broadcast_ss/_mm256_broadcast_ss/_mm256_broadcast_sd intrínsecos para poblar SSE y AVX se registra con el/doble valor mismo flotador.

En el conjunto de instrucciones SSE3 puede encontrar _mm_loaddup_pd intrínseco que completa el registro SSE con el mismo valor doble.

En otras versiones de SSE normalmente la mejor opción es cargar un valor escalar usando _mm_load_ss/_mm_load_sd y luego copiarlo en todos los elementos de un registro vector con _mm_shuffle_ps/_mm_unpacklo_pd.