Capítulo perteneciente al math engine LordPakus
Hola a todos
No se si recordareis que Thathi me pidió en el capitulo 2 que implementara la distancia entre dos vectores. y que tal y como os dije en el capitulo 5 cuanto más compleja es la operación más mejora de rendimiento se puede llegar a conseguir.
Pues bien, concretamente para la optimización SSE, para el caso de la distancia entre dos vectores se ha conseguido unos valores de tiempo de :
Version sin optimizar Tiempo gastado: 680milisegundos
Version optimizada con SSE Tiempo gastado: 68milisegundos
Es decir se ha CONSEGUIDO MULTIPLICAR POR 10 EL RENDIMIENTO!!!. (os lo dije :D)
Aqui os dejo el código para que veais como lo he hecho:
float LPVector::distanceOld(LPVector vector)
{
float a = 0.0;
float temp = 0.0;
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return (-1.0);
}
for(int i = 0 ; i < n ; ++i)
{
temp = (v[i] - vector.v[i]);
a += ( temp * temp ) ;
}
return sqrt(a);
}
float LPVector::distanceSSE(LPVector vector)
{
//Fast SSE code when float specified
float b[4];
float* const row0 = (float*) &v[0];
float* const row1 = (float*) &(vector.v[0]);
float* const a = (float*) &b[0];
float temp = 0.0;
int i = 0;
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return (-1.0);
}
__asm
{
// Carga trozos de los vectores de 4 en 4
// La carga se hace "desordenada para que siempre haya una instrucción como mínimo entre uso y uso de registros."
mov edx, row0
mov esi, row1
mov edi, a
//Al hacer una XOR ponemos el registro a 0 más rapidamente que hacciendo un mov de 0
//El registro xmm7 (el último) lo ponemos de variable acumuladora de resultado
xorps xmm7, xmm7
}
i = n;
while( i >= 12 )
{
__asm
{
//Cargamos la info en los registros SSE
movups xmm0, [edx]
movups xmm1, [esi]
//Aumentamos los contadores en 16 = 4 elementos * 4 bytes por elemento (float)
add edx,16
add esi,16
//Cargamos la info en los registros SSE(tenemos 8 registros donde guardar info)
movups xmm2, [edx]
movups xmm3, [esi]
//Aumentamos los contadores en 16 = 4 elementos * 4 bytes por elemento (float)
add edx,16
add esi,16
//Cargamos la info en los registros SSE(tenemos 8 registros donde guardar info)
movups xmm4, [edx]
movups xmm5, [esi]
//Aumentamos los contadores en 16 = 4 elementos * 4 bytes por elemento (float)
add edx,16
add esi,16
//Hacemos la operación que toca, en nuestro caso, restar , elevar el resultado al cuadrado y acumular el resultado
subps xmm0 , xmm1 //Restamos de 4 en 4
subps xmm2 , xmm3 //Restamos de 4 en 4
subps xmm4 , xmm5 //Restamos de 4 en 4
//Elevamos al cuadrado la diferencia
mulps xmm0,xmm0
mulps xmm2,xmm2
mulps xmm4,xmm4
//Sumamos resultados parciales al total (xmm7)
addps xmm7,xmm0
addps xmm7,xmm2
addps xmm7,xmm4
}
i -= 12;
}
__asm
{
movups [edi], xmm7
}
b[0] += (b[1] + b[2] + b[3]);
//Los flecos los rematamos de la manera tradicional
for(int j = n-i ; j < n ; ++j)
{
temp = (v[i] - vector.v[i]);
b[0] += temp*temp;
}
return sqrt(b[0]);
}
int main (int argc, char* argv[])
{
LPVector v1,v2;
float d1,d2;
clock_t timer;
float delay;
//Creamos los vectores aleatorios
v1.random(DIM,0.0f,100.0f);
v2.random(DIM,0.0f,100.0f);
//Sumamos los vectores
cout << "Version sin optimizar\n";
timer = clock();
for(int i=0 ; i < 100000 ; i++ )
d1 = v1.distanceOld ( v2 );
delay = ( clock() - timer ) ;
cout << "Tiempo gastado: " << delay << "milisegundos\n";
cout << "Version optimizada con SSE\n";
timer = clock();
for(int i=0 ; i < 100000 ; i++ )
d2 = v1.distanceSSE ( v2 );
delay = ( clock() - timer ) ;
cout << "Tiempo gastado: " << delay << "milisegundos\n";
if ( d1 != d2)
cout << "Error: La operacion da diferente resultado!!!\n";
if ( d1 == d2)
cout << "Calculo correcto\n";
//Eliminamos los vectores
v1.Delete();
v2.Delete();
system("PAUSE");
}
Si hay algo que no entendais o quereis que implemente en SSE alguna función en especial no dudeis en hacerme llegar vuestras sugerencias o preocupaciones...
Espero que os haya gustado y que hayais aprendido...
Nos vemos
Blog de programación enfocado a estudiantes principiantes de C/C++ en español. Dispone de cursos de todos los niveles y para multitud de usos.
Mostrando entradas con la etiqueta vector distance. Mostrar todas las entradas
Mostrando entradas con la etiqueta vector distance. Mostrar todas las entradas
lunes, 5 de septiembre de 2011
Entradas populares
-
Una pregunta que me hacen en muchas ocasiones es ¿¿qué significa %2?? La respuesta tiene dos acepciones en función de si lo estamos u...
-
<< Ejemplo anterior Artículos Relacionados Ejemplo siguiente >> Hola a todos, ASCII Art es el hecho de hacer di...
-
Hola a todos... En muchas ocasiones un programador ve frustrado un proyecto al faltarle un artista de audio y/o imagen que le complemente ...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
-
<< Gurú anterior Gurús de la programación John Carmack Robert C. Martin (Uncle Bob) Kent Beck Martín Fowler Ward C...
-
Articulo perteneciente a : Referencias de programación Hola a todos Os pongo una aportación que a más de uno le irá bien, un resumen de ...