vectores todas tipos programacion las imprimir funciones ejemplos con c optimization vectorization sse simd

todas - Cómo calcular el producto vector punto utilizando las funciones intrínsecas de SSE en C



todas las funciones de c++ (4)

Aquí hay un artículo de Intel que aborda las implementaciones de productos dot.

Estoy tratando de multiplicar dos vectores juntos donde cada elemento de un vector se multiplica por el elemento en el mismo índice en el otro vector. Luego quiero sumar todos los elementos del vector resultante para obtener un número. Por ejemplo, el cálculo se vería así para los vectores {1,2,3,4} y {5,6,7,8}:

1 * 5 + 2 * 6 + 3 * 7 + 4 * 8

Esencialmente, estoy tomando el producto punto de los dos vectores. Sé que hay un comando SSE para hacer esto, pero el comando no tiene una función intrínseca asociada. En este punto, no quiero escribir ensambles en línea en mi código C, por lo que quiero usar solo funciones intrínsecas. Esto parece un cálculo común, así que estoy sorprendido de que no haya encontrado la respuesta en Google.

Nota: Estoy optimizando para una micro arquitectura específica que admite hasta SSE 4.2.

Gracias por tu ayuda.


Escribí esto y lo compilé con gcc -O3 -S -ftree-vectorize -ftree-vectorizer-verbose=2 sse.c

void f(int * __restrict__ a, int * __restrict__ b, int * __restrict__ c, int * __restrict__ d, int * __restrict__ e, int * __restrict__ f, int * __restrict__ g, int * __restrict__ h, int * __restrict__ o) { int i; for (i = 0; i < 8; ++i) o[i] = a[i]*e[i] + b[i]*f[i] + c[i]*g[i] + d[i]*h[i]; }

Y GCC 4.3.0 auto-vectorizado:

sse.c:5: note: LOOP VECTORIZED. sse.c:2: note: vectorized 1 loops in function.

Sin embargo, solo lo haría si utilizara un ciclo con suficientes iteraciones; de lo contrario, la salida detallada aclararía que la vectorización no era rentable o que el ciclo era demasiado pequeño. Sin las palabras clave __restrict__ , tiene que generar versiones separadas, no vectorizadas, para tratar los casos en que la salida o puede apuntar a una de las entradas.

Pegaría las instrucciones como ejemplo, pero como parte de la vectorización desenrolló el bucle, no es muy legible.


GCC (al menos la versión 4.3) incluye <smmintrin.h> con intrínsecos de nivel SSE4.1, incluidos los productos de puntos de precisión simple y doble:

_mm_dp_ps (__m128 __X, __m128 __Y, const int __M); _mm_dp_pd (__m128d __X, __m128d __Y, const int __M);

Como alternativa para procesadores antiguos, puede usar este algoritmo para crear el producto de puntos de los vectores a y b :

r1 = _mm_mul_ps(a, b); r2 = _mm_hadd_ps(r1, r1); r3 = _mm_hadd_ps(r2, r2); _mm_store_ss(&result, r3);


Yo diría que el método SSE más rápido sería:

static inline float CalcDotProductSse(__m128 x, __m128 y) { __m128 mulRes, shufReg, sumsReg; mulRes = _mm_mul_ps(x, y); // Calculates the sum of SSE Register - https://.com/a/35270026/195787 shufReg = _mm_movehdup_ps(mulRes); // Broadcast elements 3,1 to 2,0 sumsReg = _mm_add_ps(mulRes, shufReg); shufReg = _mm_movehl_ps(shufReg, sumsReg); // High Half -> Low Half sumsReg = _mm_add_ss(sumsReg, shufReg); return _mm_cvtss_f32(sumsReg); // Result in the lower part of the SSE Register }

Seguí la forma más rápida de hacer la suma del vector flotante horizontal en x86 .