2016-05-12 15 views
1

Frage ist heute ziemlich kurz. Betrachten Sie das folgende Spielzeug C-Programm shuffle.c zum Umkehren zwei gepackte Doppel im Register xmm0:Irgendwelche Präferenz für SHUFPD oder PSHUFD zum Umkehren von zwei gepackten Doppel in einem XMM?

#include <stdio.h> 

void main() { 
    double x[2] = {0.0, 1.0}; 
    asm volatile (
    "movupd (%[x]), %%xmm0\n\t" 
    "shufpd $1, %%xmm0, %%xmm0\n\t" /* method 1 */ 
    //"pshufd $78, %%xmm0, %%xmm0\n\t" /* method 2 */ 
    "movupd %%xmm0, (%[x])\n\t" 
    : 
    : [x] "r" (x) 
    : "xmm0", "memory"); 
    printf("x[0] = %.2f, x[1] = %.2f\n", x[0], x[1]); 
    } 

Nach einem Testlauf: gcc -msse3 -o shuffle shuffle.c | ./test, beide Methoden/Anleitungen kehren das richtige Ergebnis x[0] = 1.00, x[1] = 0.00. This page besagt, dass shufpd eine Latenzzeit von 6 Zyklen hat, während die besagt, dass pshufd nur eine Latenz von 1 Zyklen hat. Das klingt nach großer Vorliebe für pshufd. Diese Anweisung ist jedoch wirklich für gepackte Ganzzahlen gedacht. Wenn es für gepackte Doubles verwendet wird, gibt es eine Strafe, die mit "falschem Typ" verbunden ist?

Als eine ähnliche Frage habe ich auch gehört, dass die Anweisung movaps ist 1 Byte kleiner als movapd, und sie tun das gleiche durch Lesen von 128 Bit aus einer 16-Bit-Adresse ausgerichtet. Können wir also immer erstere für die Verschiebung (zwischen XMMs)/Laden (aus dem Speicher)/Speichern (in den Speicher) verwenden? Das scheint verrückt. Ich denke, dass es einen Grund geben muss, dies abzulehnen. Kann mir jemand eine Erklärung geben? Vielen Dank.

+0

Siehe auch http://stackoverflow.com/questions/2804902/whats-the-difference-between-logical-sse-intrinsics. Ich konnte mich nicht entscheiden, ob ich dies als Duplikat abstimmen oder beantworten sollte. Ich glaube mich zu erinnern, dass ich vor kurzem auch auf eine andere Frage die gleiche Antwort gegeben habe. –

Antwort

3

Sie erhalten immer korrekte Ergebnisse, aber es kann für die Leistung wichtig sein.

Bevorzugen Sie FP-Shuffles für FP-Daten, die eine Eingabe in FP-Math-Anweisungen (wie addps oder vfma..., im Gegensatz zu insns wie xorps) sein wird.

Dadurch wird bei einigen Mikroarchitekturen, einschließlich potenziell aktueller Intel-Chips, eine zusätzliche Verzögerung der Umgehungsverzögerung vermieden. Siehe Agner Fog's microarchitecture guide. Die AMD Bulldozer-Familie führt alle Shuffle-Operationen in der Vektor-Integer-Domain aus, so dass es eine Bypass-Verzögerung gibt, egal welche Shuffle Sie verwenden.

Wenn es Anweisungen speichert, kann es sich lohnen, einen Integer Shuffle trotzdem zu verwenden. (Aber in der Regel ist es anders herum, wo Sie wollen shufps verwenden, um Daten aus zwei Integer-Vektoren zu kombinieren. Das ist in noch mehr Fällen in Ordnung, und vor allem ein Problem nur auf Nehalem, IIRC.)


http://x86.renejeschke.de/html/file_module_x86_id_293.html Listen die Latenz für CPUID 0F3n/0F2n CPUs, also Pentium4 (Familie 0xF Modell 2 (Northwood)/Modell 3 (Prescott)). Diese Zahlen sind offensichtlich völlig irrelevant und passen nicht einmal zu Agner Fogs P4-Tabelle für shufpd.

Intels Intrinsic-Handbuch enthält manchmal auch Zahlen, die nicht mit experimentellen Tests übereinstimmen. Siehe Agner Fog's instruction tables für gute Latenz/Durchsatzzahlen und Microarch Guides, um die Details zu verstehen.


movaps vs. movapd: Keine vorhandenen Mikroarchitekturen Pflege, die Sie verwenden. Es wäre für jemanden in der Zukunft möglich, eine x86-CPU zu entwerfen, die double Vektoren intern von float Vektoren getrennt hält, aber für den Moment ist die einzige Unterscheidung int vs. FP gewesen.

bevorzugen immer die ps Anweisung, wenn das Verhalten identisch ist (xorps über xorpd, movhps über movhpd).


Einige Compiler (vielleicht beide gcc und Klirren, ich vergesse) einen _mm_store_si128 integer Vektorspeicher zu movaps, kompilieren, weil es auf jede vorhandene Hardware keine Leistung Nachteil ist, und es ist ein Byte kürzer.

IIRC, es gibt auch keine Perf Nachteile zum Laden von ganzzahligen Vektordaten mit movaps/movups, aber ich bin mir weniger sicher darüber.

Dort ist eine Perf Nachteil gegenüber der Verwendung der falschen mov Anweisung für eine reg-reg Bewegung, obwohl. movdqa xmm1, xmm2 zwischen zwei FP-Anweisungen ist schlecht auf Nehalem.


re: Ihr Inline-asm:

Es braucht nicht volatile zu sein, und man kann die "memory" clobber fallen, wenn Sie eine 16-Byte-Struktur oder etwas, das als Eingang "+m" verwendet/Ausgangsoperand. Oder ein "+ x" Vektorregister-Operand für eine __m128d Variable.

Sie erhalten wahrscheinlich bessere Ergebnisse aus Intrinsics als aus Inline-Asm, es sei denn, Sie schreiben ganze Schleifen in Inline-Asm oder Standalone-Funktionen.

Siehe das Tag Wiki für einen Link zu meinem Inline-Asm-Guide.