Domanda

Sto scrivendo un programma in C che ha bisogno di fare alcuni calcoli matematici veloci. Sto usando in linea le istruzioni di montaggio SSE per ottenere qualche azione SIMD (usando imballato doppia precisione numeri in virgola mobile). Sto compilando utilizzando GCC su Linux.

Sono in una situazione in cui ho bisogno di un ciclo su alcuni dati, e io uso un fattore costante nei miei calcoli. Mi piacerebbe mantenere quel fattore nascosto in un registro sicuro durante il ciclo, in modo da non dover ricaricare ogni volta.

Per chiarire con un po 'di codice:

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;"
        );
    }
}

Ho provato a fare qualcosa con la parola chiave "registrare". Ma se non sbaglio, sembra che posso conservare solo puntatore per quella struttura (in un registro generale). Questo dovrebbe essere deferenced ogni iterazione, perdere tempo prezioso.

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 */

Non mi piace solo supporre che GCC non cambierà il XMM1 registro, è troppo di un "demoni volanti fuori il naso" genere di cose :-). Così sto sperando che ci sia un modo corretto di fare questo.

È stato utile?

Soluzione

Credo che la soluzione qui è di fare gcc consapevoli del fatto che il tipo di vec2_t è in realtà un vettore; allora si può solo calcolare il valore loop-invariante e trattarlo come una variabile normale (tranne il compilatore sa che è un tipo di vettore):

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
       );
   }
}

Ho appena compilato questo con un semplice calcolo all'interno del ciclo, e con almeno livello di ottimizzazione 1 il valore di invariant è conservato in un registro XMM durante il ciclo.

(Tutto questo implica che non esistano necessità il tuo invariante di ciclo in un registro esplicito XMM, e che è possibile utilizzare il normale allocazione dei registri di GCC).

Altri suggerimenti

Credo che sia meglio lasciare registrare assegnazione al compilatore. Probabilmente può mantenere traccia di esso di te. GCC sarà già utilizzare le estensioni SSE ma se siete sicuri di sapere meglio, utilizzare il GCC __builtin funzioni. Per essere onesti, dubito un po 'che ti rendono più veloce in questo modo.

Buona fortuna!

Questi siti sono probabilmente interessante da guardare.

GCC X86 Built-in funzioni

Lavorare con SIMD con GCC

Sono abituato a lavorare con il gruppo e C e quello che vorrei fare qui è che avrei scritto l'intera funzione in assemblea. Se si dispone di un sistema di marca flessibile, vi consiglio di assemblare la funzione ASM separatamente e che lo collega nella vostra applicazione. L'unico problema è che la funzione non può essere inline dal compilatore.

void function (void); // C

extern funzione "C" (vuoto); // C ++

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top