Ich verstehe, dass es wichtig ist, VZEROUPPER
zu verwenden, wenn Sie SSE- und AVX-Code mischen, aber was ist, wenn ich AVX (und gewöhnlichen x86-64-Code) ohne irgendwelche Legacy-SSE-Anweisungen verwende?
Wenn ich niemals einen einzelnen SSE-Befehl in meinem Code verwende, gibt es einen Leistungsgrund, warum ich jemals VZEROUPPER
verwenden müsste?
Dies setzt voraus, dass ich keine externen Bibliotheken anrufe (die möglicherweise SSE verwenden).
Sie haben Recht, wenn Ihr ganzes Programm keine any Nicht-VEX-Anweisungen verwendet, die xmm
-Register schreiben, brauchen Sie nicht vzeroupper
, um Strafen für Zustandsübergänge zu vermeiden.
Achten Sie darauf, dass Nicht-VEX-Anweisungen in CRT-Startcode und / oder dem dynamischen Linker oder anderen stark nicht offensichtlichen Orten verborgen bleiben können.
Das heißt, eine Nicht-VEX-Anweisung kann nur eine einmalige Strafe verursachen, wenn sie ausgeführt wird. Das Umgekehrte ist nicht wahr: eine VEX-256-Anweisung kann im Allgemeinen (oder nur mit diesem Register) Nicht-VEX-Anweisungen machen langsam für den Rest des Programms .
VZEROUPPER
kann Kontextschalter etwas billiger machen , weil die CPU immer noch weiß, ob der ymm-obere Zustand sauber oder schmutzig ist.
Wenn es sauber ist, kann xsaveopt
den FPU-Zustand kompakter schreiben, ohne das zu speichern alle oberen Nullhälften überhaupt (nur Einstellung ein Bit, das sagt, dass sie sauber sind). Beachten Sie im Bundesstaat -Übergangsdiagramm für SSE / AVX , dass xsave
/ xrstor
Teil des Bildes ist.
Ein extra vzeroupper
nur dafür ist nur dann eine Überlegung wert, wenn Ihr Code keine 256b Anweisungen für eine lange Zeit danach verwenden wird, weil Sie im Idealfall keine Kontextwechsel haben / CPU-Migrationen.
Verschmutzte obere Hälften nehmen möglicherweise physische Register auf , wodurch die Fenstergröße außerhalb der Reihenfolge begrenzt wird, damit die CPU Parallelität auf Befehlsebene findet. (ROB-Größe ist der andere wichtige limitierende Faktor, aber die PRF-Größe kann der Flaschenhals sein .)
Dies ist definitiv auf AMD CPUs , wo 256b Ops in zwei 128b Ops aufgeteilt sind. YMM-Register werden intern als zwei 128-Bit-Register behandelt, und z.B. vmovaps ymm0, ymm1
benennt die low 128 mit einer Latenz von null um, benötigt aber einen Uop für die obere Hälfte. (Siehe Agner Fogs microarch pdf )
Es gibt Hinweise darauf, dass Skylake-AVX512 2x 256-Bit-Registerdateieinträge für ZMM-Register verwendet, wenn die oberen 256 Bit verschmutzt sind. @Mysticial Berichte unerwartete Verlangsamungen im Code mit langen FP-Abhängigkeitsketten mit YMM vs. ZMM, aber ansonsten identischem Code.
Experimente im ROB-Size- / PRF-Size-Blogpost, den ich im ersten Abschnitt verlinkt habe, zeigen, dass die Einträge der physischen FP-Registerdatei in Sandybridge 256-Bit sind. vzeroupper
sollte nicht mehr Register auf Mainstream-Intel-CPUs mit AVX / AVX2 freigeben, nur AVX512 mit schmutzigen ZMM-Oberteilen 256.
Silvermont unterstützt AVX nicht. Und es verwendet eine separate Ruhestandregisterdatei für den Architekturstatus, so dass die Out-of-Order-PRF nur spekulativ ausgeführt wird Ergebnisse. Selbst wenn AVX mit 128-Bit-Hälften unterstützt würde, würde ein veraltetes YMM-Register mit einer fehlerhaften oberen Hälfte keinen zusätzlichen Platz in der Umbenennungsregisterdatei belegen.
KNL wurde speziell für die Ausführung von AVX512 entwickelt, vermutlich hat seine FP-Registerdatei 512-Bit-Einträge. Es basiert auf Silvermont, aber die SIMD-Teile des Kerns sind unterschiedlich (z. B. können FP / Vektor-Befehle neu angeordnet werden, während Silvermont sie nur spekulativ ausführen kann, sie jedoch nicht innerhalb der FP / Vektor-Pipeline nach Agner Fog neu anordnen). Dennoch kann KNL auch eine separate Datei für das Ruhestandsregister verwenden, so dass schmutzige ZMM-Upper keinen zusätzlichen Speicherplatz beanspruchen würden, selbst wenn es in der Lage wäre, einen 512-Bit-Eintrag zu teilen, um zwei 256-Bit-Vektoren zu speichern. Was unwahrscheinlich ist, weil ein größeres Out-of-Order-Fenster für AVX1 / AVX2 auf KNL es nicht wert wäre, Transistoren zu verwenden. vzeroupper
ist auf KNL viel langsamer als Mainstream-CPUs von Intel (eine pro 36 Zyklen im 64-Bit-Modus), also würden Sie wahrscheinlich nicht verwenden wollen, vor allem nur für den kleinen Context-Switch-Vorteil.
Wenn Sie die oberen Hälften von Ausführungseinheiten, die längere Zeit nicht benutzt wurden, abschalten (und manchmal höhere Turbo-Taktraten zulassen), hängt es davon ab, ob YMM (oder ZMM) -Befehle in letzter Zeit verwendet wurden und nicht ob der obere Hälften sind schmutzig oder nicht. So hilft AFAIK, vzeroupper
nicht der CPU, die Taktgeschwindigkeit nach der Verwendung von AVX / AVX512-Anweisungen schneller zu drosseln, für CPUs, bei denen max turbo für 256-Bit- oder 512-Bit-Befehle niedriger ist / p>
Es gibt auch keine Strafe beim Mischen von VEX und EVEX , also brauchst du vzeroupper
nicht zu benutzen.
Tags und Links assembly x86 performance avx micro-optimization