2009-08-08 4 views
7

Ich schreibe ein Programm in C, das einige schnelle mathematische Berechnungen durchführen muss. Ich verwende Inline-SSE-Assembler-Anweisungen, um eine SIMD-Aktion zu erhalten (mit gepackten Gleitkommazahlen mit doppelter Genauigkeit). Ich kompiliere mit GCC unter Linux.Erhalten Sie GCC, um ein SSE-Register in einer Funktion zu erhalten, die Inline-Asm verwendet

Ich bin in einer Situation, in der ich einige Daten durchlaufen muss, und ich verwende einen konstanten Faktor in meinen Berechnungen. Ich möchte diesen Faktor während der Schleife in einem sicheren Register versteckt halten, so dass ich ihn nicht jedes Mal neu laden muss.

mit einigem Code Zur Klarstellung:

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

Ich habe etwas mit dem "Register" Stichwort versucht zu tun. Aber wenn ich mich nicht irre, sieht es so aus, als könnte ich nur einen Zeiger auf diese Struktur (in einem allgemeinen Register) bewahren. Dies müsste bei jeder Wiederholung deferenziert werden und wertvolle Zeit verschwenden.

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

Ich mag nicht nur davon ausgehen, dass GCC wird die Änderung nicht XMM1 zu registrieren, ist es zu viel von einem „Dämonen aus der Nase fliegt“ Art der Sache :-). Ich hoffe, es gibt einen richtigen Weg, dies zu tun.

Antwort

8

Ich denke, die Lösung hier ist, gcc bewusst zu machen, dass Ihr vec2_t Typ tatsächlich ein Vektor ist; dann können Sie nur den Loop-invariant Wert berechnen und behandeln es als eine normale Variable (mit Ausnahme der Compiler weiß, ist es ein Vektortyp):

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

ich dies nur mit einer einfachen Berechnung innerhalb der Schleife kompiliert auf und Bei mindestens der Optimierungsebene 1 wird der Wert invariant während der Schleife in einem XMM-Register gehalten.

(Dies alles setzt voraus, dass Sie brauchen Ihre Schleife Invariante in einem expliziten XMM-Register, und dass Sie GCC normalen Registerzuweisung verwenden können).

3

Ich denke, es ist am besten, Registerzuweisung zum Compiler zu verlassen. Es kann wahrscheinlich besser darüber nachdenken als Sie. GCC wird bereits die SSE-Erweiterungen verwenden, aber wenn Sie sicher sind, dass Sie es besser wissen, verwenden Sie die GCC __builtin-Funktionen. Um ehrlich zu sein, ich bezweifle ein bisschen, dass du es so schneller machen wirst.

Viel Glück!

Diese Seiten sind wahrscheinlich interessant zu betrachten.

GCC X86 Built-in functions

Working with SIMD with GCC

3

Ich bin es gewohnt, mit Montage und C zu arbeiten und was ich hier tun würde, ist, dass ich die ganze Funktion in der Montage schreiben würde. Wenn Sie ein flexibles System haben, empfehle ich, die ASM-Funktion separat zu montieren und in Ihre Anwendung zu integrieren. Das einzige Problem dabei ist, dass die Funktion vom Compiler nicht eingebunden werden kann.

Void-Funktion (void); // C

externe "C" -Funktion (void); // C++