Streaming SIMD Extensions: Vectorización al alcance de todos Germán Ros Sánchez Universidad de Murcia Octubre 2009
SSE*: Streaming SIMD Extensions Es un conjunto de instrucciones SIMD que incorporan los procesadores modernos de Intel y AMD. Son muy útiles para conseguir pequeños speedup de entre 2x~4x. Tiene un ancho de 4 operaciones (128bits). El bajo nivel de abstracción que proponen (ASM/C) ha provocado que muchos programadores no las usen. Tienen una utilidad limitada: VECTORIZACIÓN.
Arquitectura oculta
Modelo de programación C/C++ Si bien es cierto que a nivel de ensamblador el modelo es austero, usando la abstracción ofrecida por xmmintrin.h podemos obtener un modelo de programación similar a otros de vectorización, tales como CUDA. El proceso es fácilmente resumible en tres fases: Agrupamiento de los datos a operar Realizar las operaciones pertinentes Compilar: gcc/g++ -o prog prog.c -msse
1. Tipos de datos y agrupamiento En SSE usamos aritmética de coma flotante A la hora de definir las matrices las cosas cambian un poco. Ahora hay que utilizar declspec(align(16)) float en lugar de Float. Ej: declspec(align(16)) float M[SIZE]; Cuando queremos usar matrices dinámicas debemos sustituir la función malloc por _mm_malloc. Ej: M = (float*) _mm_malloc(n*sizeof(float), 16);
1. Tipos de datos y agrupamiento (II) Estos cambios obedecen a la necesidad de que los datos estén correctamente alineados a 16Bytes. Una vez que nuestros datos estén definidos y alineados tenemos que agruparlos para que puedan ser usados por las funciones de SSE. El agrupamiento se hace a través del tipo de datos m128. Ej: m128* pm = ( m128*) M;
1. Tipos de datos y agrupamiento (III) Muchas veces puede resultar de utilidad hacer que nuestros tipos de datos sean conscientes de SSE para obtener el mejor de los rendimientos. Hay que tener cuidado con esto. Se debería hacer de forma transparente al resto del código del programa (encapsulado en alguna función). Ej: Estructura para un pixel en SSE typedef struct { float red[4]; float green[4]; float blue[4]; float alpha[4]; } CData32T4;
2. Realizando Operaciones Gestión de la memoria _aligned_malloc _aligned_free Operaciones aritméticas _mm_add_ps _mm_sub_ps _mm_mul_ps _mm_div_ps _mm_sqrt_ps...
2. Realizando Operaciones (II) Operaciones lógicas _mm_and_ps _mm_or_ps _mm_xor_ps _mm_andnot_ps Operaciones de conversión _mm_cvtss_si32 _mm_cvtps_pi32 _mm_cvttss_si64 _mm_cvtpi16_ps Y MUCHAS MÁS OPERACIONES EN xmmintrin.h!
Un ejemplo práctico
Suma de vectores secuencial float* m1; float* m2; float* m3; srand(time(null)); m1 = new float[m]; m2 = new float[m]; m3 = new float[m]; //Inicializacion for(int i=0;i<m;i++) { m1[i] = (rand()/(float)rand_max); m2[i] = (rand()/(float)rand_max); } //T veces for(int k=0;k<t;k++) { //suma for(int i=0;i<m;i++) m3[i] = m1[i] + m2[i]; } Declaración Inicialización Cálculo
Suma de vectores vectorizada (I) float* m1; float* m2; float* m3; Inicialización SSE srand(time(null)); m1 = (float*) _mm_malloc(m * sizeof(float), 16); m2 = (float*) _mm_malloc(m * sizeof(float), 16); m3 = (float*) _mm_malloc(m * sizeof(float), 16); //Inicializacion for(int i=0;i<m;i++) { m1[i] = (rand()/(float)rand_max); m2[i] = (rand()/(float)rand_max); }
Suma de vectores vectorizada (II) int m = M/4; //T veces for(int k=0;k<t;k++) { m128* psrc1 = ( m128*) m1; m128* psrc2 = ( m128*) m2; m128* pdest = ( m128*) m3; } //suma for(int i=0;i<m;i++) { *pdest = _mm_add_ps(*psrc1, *psrc2); psrc1++; psrc2++; pdest++; } Asignación a los tipos SSE Cálculo con SSE
Conclusiones
Ejemplos de rendimiento
Ventajas Ofrece la posibilidad de tener paralelismo de datos de manera sencilla y sin necesidad de adquirir un hardware caro. Es posible su combinación con otras técnicas como OpenMP, MPI, CUDA, etc. Inconvenientes El nivel de abstracción ofrecido no es tan alto como en OpenMP. No hay posibilidad de seguir escalando más allá de 4x o 5x. Estamos haciendo programas dependientes de la arquitectura. No contamos con primitivas de sincronización.
Úiltimamente... Se está ampliando su uso en el ámbito científico/académico, en áreas como la Visión por Computador, o el modelado 3D. Aunque no ofrecen grandes SpeedUps, su uso puede suponer la diferencia entre una ejecución en Tiempo Real o no. De ahí que últimamente se use en combinación de otras tecnologías como CUDA Pronto quedarán obsoletas con la salida de AVX: Advanced Vector Extensions (prevista para 2010)
Referencias http://www.codeproject.com/kb/recipes/sseintro.aspx http://www.cvl.isy.liu.se/scout/publications/paperinfo/sf05.html http://www.usqcd.org/fnal/sse/sse.html http://www.gamedev.net/reference/articles/article1987.asp http://msdn.microsoft.com/en-us/library/t467de55(vs.71).aspx http://en.wikipedia.org/wiki/streaming_simd_extensions http://softwarecommunity.intel.com/isn/downloads/ Intel%20SSE4%20Programming%20Reference.pdf
Preguntas?