Obtener GCC para conservar un registro SSE a lo largo de una función que utiliza asm en línea

StackOverflow https://stackoverflow.com/questions/1250083

Pregunta

Estoy escribiendo un programa en C que tiene que hacer algunos cálculos matemáticos rápidos. Estoy usando las instrucciones en línea de montaje de la ESS para obtener algún tipo de acción SIMD (usando lleno de doble precisión números de punto flotante). Estoy compilando usando GCC en Linux.

Estoy en una situación en la que necesito para recorrer algunos datos, y utilizo un factor constante en mis cálculos. Me gustaría mantener ese factor escondido en un registro seguro durante el bucle, por lo que no tenga que volver a cargar cada vez.

Para 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 sólo puedo conservar un puntero a la estructura (en un registro general). Esto tendría que ser deferenced 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 */

No sólo me gusta asumir que GCC no cambiará el XMM1 registrarse, es demasiado de un "demonios que vuelan de la nariz" tipo de cosas :-). Así que estoy esperando que hay una forma correcta de hacer esto.

¿Fue útil?

Solución

Creo que la solución a este problema es hacer gcc en cuenta que el tipo de vec2_t es en realidad 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
       );
   }
}

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

(Todo esto supone que no necesidad su invariantes de bucle en un registro XMM explícita, y que se puede utilizar la asignación de registros normales de GCC).

Otros consejos

Creo que es mejor dejar registro de asignación al compilador. Es probable que pueda hacer un mejor seguimiento de la misma que tú. GCC ya utilizará las extensiones SSE pero si está seguro de que sabe mejor, utilizar el CCG __builtin funciones. Para ser honesto, no creo que un poco de que usted va a hacer que sea más rápido de esa manera.

Mucha suerte!

Estos sitios son probablemente interesante de ver.

GCC X86 incorporado funciones

Trabajar con SIMD con GCC

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 usted tiene un sistema flexible de maquillaje, recomiendo el montaje de la función ASM por separado y se une en su aplicación. El único problema con esto es que la función no puede ser inline por el compilador.

función void (void); // C

extern "C" función (void); // C ++

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top