2009-08-08 9 views
7

Estoy escribiendo un programa en C que necesita hacer algunos cálculos rápidos de matemáticas. Estoy usando instrucciones de ensamblaje de SSE en línea para obtener alguna acción SIMD (usando números de coma flotante de doble precisión). Estoy compilando usando GCC en Linux.Obtenga GCC para conservar un registro SSE a través de una función que utiliza asm en línea

Estoy en una situación en la que necesito revisar algunos datos, y uso un factor constante en mis cálculos. Me gustaría mantener ese factor escondido en un registro seguro durante el ciclo, por lo que no tengo que volver a cargarlo cada vez.

Aclarar con algo de código:

struct vect2 { 
    fltpt x; 
    fltpt y; 
}__attribute__((aligned(16))); /* Align on 16B boundary for SSE2 instructions */ 
typedef struct vect2 vect2_t; 


void function() 
{ 
    /* get a specific value set up in xmm1, and keep it there for the 
    * rest of the loop. */ 
    for(int i = 0, i<N; i++){ 
     asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
     ); 
    } 
} 

He intentado hacer algo con la palabra clave "registro". Pero si no me equivoco, parece que solo puedo conservar un puntero en esa estructura (en un registro general). Esto necesitaría ser referenciado en cada iteración, perdiendo un tiempo precioso.

register vect2_t hVect asm("xmm1") = {h, h}; 
/* Gives error: data type of 'hVect' isn't suitable for a register */ 

register vect2_t *hVect2 asm("rax"); 
*hVect2 = (vect2_t){h,h}; 
/* Seems to work, but not what I'm looking for */ 

que no sólo me gusta asumir que GCC no cambiará el XMM1 registro, es demasiado de un "demonios que vuelan de la nariz" tipo de cosas :-). Así que espero que haya una forma adecuada de hacer esto.

Respuesta

8

Creo que la solución aquí es hacer que gcc sepa que su tipo vec2_t es realmente un vector; a continuación, puedes calcular el valor de lazo invariante y tratarlo como una variable normal (excepto el compilador sabe que es un tipo vectorial):

typedef double vec2_t __attribute__ ((vector_size (16))); 

void function() 
{ 
    /* get a specific value set up, e.g. */ 
    vec2_t invariant; 
    asm("some calculations, soring result in invariant." 
     : "=x" (invariant)); 

    for(int i = 0; i<N; i++){ 
    asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
      : "x" (invariant) // and other SSE arguments 
     ); 
    } 
} 

acabo compilado esto con un simple cálculo dentro del bucle, y con al menos nivel de optimización 1, el valor de invariant se mantiene en un registro XMM durante el ciclo.

(Todo esto supone que no necesita su bucle invariante en un registro XMM explícito, y que puede usar la asignación de registro normal de GCC).

3

Creo que es mejor dejar la asignación de registro en el compilador. Probablemente pueda mantener un mejor seguimiento que tú. GCC ya usará las extensiones de SSE, pero si está seguro de que lo sabe, use las funciones de compilación de GCC. Para ser sincero, dudo un poco que lo hagas más rápido de esa manera.

¡Mucha suerte!

Estos sitios son probablemente interesantes de ver.

GCC X86 Built-in functions

Working with SIMD with GCC

3

Estoy acostumbrado a trabajar con el montaje y C, y lo que haría aquí es que me gustaría escribir toda la función en el ensamblaje. Si tiene un sistema de fabricación flexible, le recomiendo ensamblar la función ASM por separado y vincularla a su aplicación. El único problema con esto es que el compilador no puede insertar la función.

función de vacío (vacío); // C

función "C" externa (vacío); // C++

Cuestiones relacionadas