Erhalten Sie GCC eine SSE-Register während einer Funktion zu erhalten, die Inline-asm verwendet

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

Frage

Ich bin ein Programm in C schreiben, die einige schnelle mathematische Berechnungen tun muss. Ich bin mit Inline-SSE Montageanleitung eine SIMD-Aktion zu erhalten (gepackt mit doppelter Genauigkeit Gleitkommazahlen verwenden). Ich bin Kompilieren unter Linux mit GCC.

Ich bin in einer Situation, wo ich eine Schleife über einige Daten benötigen, und ich verwende einen konstanten Faktor in meinen Berechnungen. Ich mag diesen Faktor weg, während der Schleife in einem sicheren Register versteckt halten, so dass ich muß nicht jedes Mal neu geladen werden.

Um mit einigem Code zu verdeutlichen:

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, es sieht aus, als ob ich nur einen wahren Zeiger auf diese Struktur (in einem allgemeinen Register). Dies müßte jede Iteration deferenced wird, kostbare Zeit zu 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 zu nicht einfach 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 :-). Also ich hoffe es eine richtige Art und Weise, dies zu tun.

War es hilfreich?

Lösung

Ich denke, die Lösung ist hier 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ß, es ist ein Vektor-Typ):

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

I dies nur durch eine einfache Berechnung in der Schleife, und mit mindestens Optimierungsstufe 1 der Wert von invariant kompiliert up in einem XMM Register während der Schleife gehalten wird.

(Dies alles vorausgesetzt, dass Sie dies nicht tun Notwendigkeit Ihre Schleifeninvariante in einem expliziten XMM-Register, und dass Sie GCC normale Registerzuweisung verwenden).

Andere Tipps

Ich denke, es ist am besten an den Compiler verlassen registrieren Zuordnung. Es kann wohl eine bessere Übersicht über es, als Sie halten. GCC wird bereits die SSE-Erweiterungen verwenden, aber wenn Sie sicher sind, Sie wissen besser, verwenden Sie die GCC __builtin Funktionen. Um ehrlich zu sein, bezweifle ich ein wenig, dass Sie machen es auf diese Weise schneller.

Viel Glück!

Diese Seiten sind wahrscheinlich interessant, zu betrachten.

GCC X86 Integrierte Funktionen

Arbeiten mit SIMD mit GCC

Ich bin es gewohnt, mit Montage und C zu arbeiten und was ich hier tun, ist, dass ich die ganze Funktion in der Montage schreiben würde. Wenn Sie ein flexible Make-System haben, empfehle ich die ASM-Funktion separat zusammenbauen und die Verknüpfung in der Anwendung. Das einzige Problem dabei ist, dass die Funktion nicht vom Compiler inlined werden.

void Funktion (void); // C

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top