Wenn ich SSE3 oder AVX verwenden kann, sind dann ältere SSE-Versionen als SSE2 oder MMX verfügbar -
oder muss ich noch separat nach ihnen suchen?
Im Allgemeinen waren dies additive, aber bedenken Sie, dass es im Laufe der Jahre Unterschiede zwischen der Unterstützung von Intel und AMD gibt.
Wenn Sie AVX haben, können Sie auch SSE, SSE2, SSE3, SSSE3, SSE4.1 und SSE 4.2 annehmen. Denken Sie daran, dass zur Verwendung von AVX das OSXSAVE-CPUID-Bit auch gesetzt sein muss, um sicherzustellen, dass das von Ihnen verwendete Betriebssystem auch das Speichern der AVX-Register unterstützt.
Sie sollten immer noch explizit nach der CPUID-Unterstützung suchen, die Sie in Ihrem Code für Robustheit verwenden (sagen Sie gleichzeitig nach AVX, OSXSAVE, SSE4, SSE3, SSSE3, um Ihre AVX-Codepfade zu schützen).
%Vor%SSE und SSE2 sind für alle Prozessoren erforderlich, die x64-nativ sein können. Daher sind sie gute Grundannahmen für den gesamten Code. Windows 8.0, Windows 8.1 und Windows 10 erfordern ausdrücklich SSE- und SSE2-Unterstützung, selbst für x86-Architekturen, so dass diese Befehlssätze ziemlich allgegenwärtig sind. Mit anderen Worten, wenn Sie eine Prüfung auf SSE oder SSE2 nicht bestehen, beenden Sie die App einfach mit einem schwerwiegenden Fehler.
%Vor%-oder -
%Vor% Denken Sie auch daran, dass MMX, x87 FPU und AMD 3DNow! * veraltete Befehlssätze für sind x64 nativ, also sollten Sie sie im neueren Code nicht mehr aktiv verwenden. Eine gute Faustregel ist, dass keine intrinsische Methode verwendet wird, die ein __m64
zurückgibt oder einen __m64
-Datentyp verwendet.
Vielleicht möchten Sie diese DirectXMath-Blogserie mit Hinweisen zu vielen dieser Befehlssätze und den entsprechenden Anforderungen an die Prozessorunterstützung.
Hinweis (*) - Alle AMD 3DNow! Anweisungen sind veraltet, außer für PREFETCH
und PREFETCHW
, die übertragen wurden. Intel64-Prozessoren der ersten Generation fehlten die Unterstützung für diese Anweisungen, aber sie wurden später hinzugefügt, da sie als Teil des Kern-X64-Befehlssatzes betrachtet werden. Windows 8.1 und Windows 10 x64 benötigen insbesondere PREFETCHW
, obwohl der Test etwas merkwürdig ist. Die meisten Intel-CPUs vor Broadwell melden tatsächlich keine Unterstützung für PREFETCHW
durch CPUID, aber sie behandeln den Opcode als Nicht-Op, anstatt eine Ausnahme wegen "illegaler Instruktionen" auszulösen. Daher ist der Test hier (a) wird es von CPUID unterstützt, und (b) wenn nicht, wirft PREFETCHW
zumindest keine Ausnahme.
Hier ist ein Testcode für Visual Studio, der den PREFETCHW
-Test sowie viele andere CPUID-Bits für die x86- und x64-Plattformen demonstriert.
UPDATE: Die grundlegende Herausforderung besteht natürlich darin, wie Sie mit Systemen umgehen, die keine Unterstützung für AVX bieten. Obwohl der Befehlssatz nützlich ist, besteht der größte Vorteil eines AVX-fähigen Prozessors in der Möglichkeit, den Schalter /arch:AVX
build zu verwenden, der die globale Verwendung der VEX Präfix für bessere SSE / SSE2 Code-Gen. Das einzige Problem ist der resultierende Code DLL / EXE ist nicht kompatibel mit Systemen, die AVX Unterstützung haben.
Für Windows sollten Sie idealerweise eine EXE für Nicht-AVX-Systeme erstellen (unter der Annahme, dass SSE / SSE2 nur /arch:SSE2
anstelle von x86-Code verwendet; diese Einstellung ist implizit für x64-Code), also eine andere EXE optimiert für AVX (mit /arch:AVX
) und dann mithilfe der CPU-Erkennung ermitteln, welche EXE für ein bestimmtes System verwendet werden soll.
Zum Glück mit Xbox One können wir immer nur mit /arch::AVX
bauen, da es eine feste Plattform ist ...
Als allgemeine Regel - mischen Sie nicht verschiedene Generationen von SSE / AVX, außer Sie müssen. Wenn Sie dies tun, vergewissern Sie sich, dass Sie vzeroupper oder ähnliche Anweisungen zum Löschen des Status verwenden. Andernfalls können Sie Teilwerte ziehen und unwissentlich falsche Abhängigkeiten erstellen, da die meisten Register von den Modi gemeinsam genutzt werden Selbst beim Löschen kann das Umschalten zwischen den Modi, abhängig von der genauen Mikroarchitektur, zu Strafen führen.
Weiterführende Literatur - Ссылка
Siehe Chucks Antwort für gute Ratschläge, was Sie tun sollten. Siehe diese Antwort für eine wörtliche Antwort auf die gestellte Frage, falls Sie neugierig sind.
Die AVX-Unterstützung garantiert die Unterstützung aller Intel SSE * -Befehlssätze, da sie VEX-codierte Versionen von allen enthält. Wie Chuck darauf hinweist, kannst du gleichzeitig mit einer Bitmaske nach vorherigen suchen, ohne deinen Code aufzublähen, aber verschwinde nicht.
Beachten Sie, dass POPCNT, TZCNT und solche Sachen nicht Teil von SSE-irgendetwas sind. POPCNT hat ein eigenes Feature-Bit. LZCNT hat auch ein eigenes Feature-Bit, da AMD es separat von BMI1 eingeführt hat. TZCNT ist jedoch nur ein Teil von BMI1. Da einige BMI1-Befehle VEX-Codierungen verwenden, haben auch Pentium / Celeron-CPUs der neuesten Generation (wie Skylake Pentium) keinen BMI1. :( Ich denke, Intel wollte nur AVX / AVX2 weglassen, wahrscheinlich damit sie CPUs mit fehlerhaften oberen Spuren von Ausführungseinheiten als Pentium verkaufen können, und dies tun sie, indem sie die VEX-Unterstützung in den Decodern deaktivieren.
Die Intel SSE-Unterstützung wurde in allen bisher veröffentlichten CPUs inkrementell erhöht. SSE4.1 beinhaltet SSSE3, SSE3, SSE2 und SSE. Und SSE4.2 beinhaltet alles Vorhergehende. Ich bin mir nicht sicher, ob eine offizielle x86-Dokumentation die Möglichkeit einer CPU mit SSE4.1-Unterstützung, aber nicht SSSE3 ausschließt. (d. h. PSHUFB weglassen, was möglicherweise teuer zu implementieren ist.) In der Praxis ist dies jedoch äußerst unwahrscheinlich, da dies die Annahmen vieler Leute verletzen würde. Wie gesagt, es wäre sogar offiziell verboten, aber ich habe es nicht sorgfältig geprüft.
AVX enthält keine AMD SSE4a oder AMD XOP. AMD-Erweiterungen müssen extra geprüft werden. Beachten Sie auch, dass die neuesten AMD-CPUs XOP-Unterstützung verlieren. (Intel hat es nie übernommen, also schreiben die meisten Leute keinen Code, um es auszunutzen, also sind diese Transistoren für AMD meistens vergeudet. Es hat einige nette Sachen, wie eine 2-Quellen-Byte-Permutation, die eine Byte-LUT zweimal erlaubt breit wie PSHUFB, ohne die In-Lane-Begrenzung von AVX2's VPSHUFB ymm).
SSE2 ist die Basis für die x86-64-Architektur . Sie müssen nicht nach SSE- oder SSE2-Unterstützung in 64-Bit-Builds suchen. Ich vergesse, wenn MMX auch Baseline ist. Fast sicher.
Der SSE-Befehlssatz enthält einige Befehle, die auf MMX-Registern arbeiten. (zB PMAXSW mm1, mm2/m64
war neu mit SSE. Die XMM-Version ist Teil von SSE2.) Sogar ein 32-Bit CPU, die SSE unterstützt, muss MMX-Register haben. Es wäre Wahnsinn, MMX-Register zu haben, aber nur die SSE-Anweisungen zu unterstützen, die sie verwenden, nicht die ursprünglichen MMX-Anweisungen (zB movq mm0, [mem]
). Allerdings habe ich nichts definitives gefunden, das die Möglichkeit einer x86-basierten Deathrestation 9000 mit SSE aber ausschließt nicht MMX CPUID-Feature-Bits, aber ich habe nicht in Intels offizielle x86-Handbücher waten. (Siehe x86 Tag-Wiki für Links).
Verwenden Sie MMX sowieso nicht, es ist im Allgemeinen langsamer, auch wenn Sie nur 64 Bits gleichzeitig bearbeiten müssen, in der unteren Hälfte eines XMM-Registers. Die neuesten CPUs (wie Intel Skylake) haben einen geringeren Durchsatz für die MMX-Versionen einiger Befehle als für die XMM-Version. In manchen Fällen sogar noch schlechtere Latenzzeiten. Laut Agner Fog Tests beträgt PACKSSWB mm0, mm1
beispielsweise 3 Ups mit 2c Latenz auf Skylake. Die 128-Bit- und 256-Bit-Version von XMM / YMM ist 1 Up mit 1c Latenz.