2016-04-20 8 views
6

Ich habe mit D'Inline-Assembler und SSE gespielt, aber etwas gefunden, das ich nicht verstehe. Wenn ich versuche, zwei Float4-Vektoren unmittelbar nach der Deklaration hinzuzufügen, ist die Berechnung korrekt. Wenn ich die Berechnung in eine separate Funktion setze, bekomme ich eine Reihe von nan s.SSE Fremdheit mit Funktionen

//function contents identical to code section in unittest 
float4 add(float4 lhs, float4 rhs) 
{ 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } 
    return res; 
} 

unittest 
{ 
    float4 lhs = {1, 2, 3, 4}; 
    float4 rhs = {4, 3, 2, 1}; 

    println(add(lhs, rhs)); //float4(nan, nan, nan, nan) 

    //identical code starts here 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } //end identical code 
    println(res); //float4(5, 5, 5, 5) 
} 

Die Baugruppe ist funktionell identisch (soweit ich beurteilen kann) zu this link.

Edit: Ich benutze eine benutzerdefinierte float4-Struktur (für jetzt, es ist nur ein Array), weil ich in der Lage sein, eine hinzufügen Funktion wie float4 add(float4 lhs, float rhs) haben. Im Moment führt, dass in einem Compiler-Fehler wie folgt aus:

Error: floating point constant expression expected instead of rhs

Hinweis: Ich bin mit DMD 2.071.0

+0

Ich hoffe, dass Sie nicht vorhaben, Code wie das für die Leistung tatsächlich zu verwenden. Sie zwingen den Compiler, die Vektoren im Speicher zu speichern und diese Adressen dann im Speicher zu speichern. Dann schreiben Sie Code, der die Adressen aus dem Speicher lädt und die Vektoren erneut lädt. (In dem Windows- "vectorcall" -ABI und in dem von allen anderen AMD64-Systemen verwendeten SysV-ABI werden Vektorargumente in Vektorregistern übergeben). In D, IDK, wenn 'lhs_addr' tatsächlich ein Register sein kann, ist es im besten Fall immer noch eine nutzlose Reg-reg-Bewegung. Idealerweise gibt es eine Syntax, nach der Vektoren in bestimmten Regs gefragt werden, wie GNU C inline asm. –

+0

Ich versuche, meinen eigenen float4-Typ zu schreiben, weil 'float4 rhs_vec = [rhs, rhs, rhs, rhs];' mit dem Fehler in der Frage nicht erlaubt ist. Im Moment habe ich den Code aus dem Link im Wesentlichen kopiert und einige kleinere Verbesserungen vorgenommen, um (hoffentlich) die Arbeit in D zu ermöglichen. Im Moment muss es einfach funktionieren. Was würden Sie stattdessen für die Sektion tun? Dies ist nur mein dritter Ausflug in die Montage, daher würde jede Korrektur geschätzt werden. – Straivers

+0

Ich weiß nicht, D, ich habe gerade diese Frage wegen der SSE und Inline-Asm-Tags gesehen. Hat D etwas wie die Intel C-Intrinsics? '__m128 my_vec = _mm_add_ps (vec1, vec2);'? Wenn dem so ist, werden Sie wahrscheinlich besser damit umgehen. Wenn die Inline-ASM-Syntax von D nur auf die Übergabe von Daten durch den Speicher beschränkt ist, dann nicht [es ist nur nützlich, wenn Sie eine ganze Schleife darin schreiben möchten, nicht als Wrapper für ein paar Anweisungen] (http://stackoverflow.com/ Fragen/3323445/was-ist-der-Unterschied zwischen-asm-und-asm/35959859 # 3595985). Wenn es GNU-C style asm-Anweisungen unterstützt, dann benutze das. –

Antwort

2

Ihr Code wierd ist, welche Version von DMD verwenden Sie? Das funktioniert wie erwartet:

import std.stdio; 
import core.simd; 

float4 add(float4 lhs, float4 rhs) 
{ 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } 
    return res; 
} 

void main() 
{ 
    float4 lhs = [1, 2, 3, 4]; 
    float4 rhs = [4, 3, 2, 1]; 

    auto r = add(lhs, rhs); 
    writeln(r.array); //float4(5, 5, 5, 5) 

    //identical code starts here 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } //end identical code 
    writeln(res.array); //float4(5, 5, 5, 5) 
} 
+0

Vielen Dank für Ihre Hilfe, aber ich habe gerade gemerkt, dass ich einige Dinge nicht in meine Frage aufgenommen habe. Sie wurden der Frage hinzugefügt. – Straivers

+0

@Stravers, hat Kozzi11 tatsächlich deine Frage beantwortet oder nicht? – DejanLekic

+0

Nein. Oder vielmehr, er antwortete auf die ursprüngliche Frage, die mir klar machte, dass ich die Frage falsch formuliert hatte. Ein Fehler, der seitdem behoben wurde. – Straivers