Es wurde bereits darauf hingewiesen, dass Agner Fog's optimization manuals eine ausgezeichnete Ressource sind, und insbesondere seine Instruction Tables, die fast für alle x86-Mikroarchitekturen von Interesse sind.
Aber Sie haben eine andere Option: Intel's Architecture Code Analyzer (IACA). Es gibt eine Beschreibung, wie man es benutzt here on Stack Overflow, aber es ist ziemlich einfach zu gehen (obwohl ein bisschen langweilig für einmalige Analyse). Sie laden einfach die ausführbare Datei herunter, geben einen Prolog- und Epilog-Code um den zu analysierenden Anweisungsblock herum (zu diesem Zweck enthält sie einen C-Header (iacaMarks.h
), der mit verschiedenen Compilern zusammenarbeitet, oder Sie weisen Ihren Assembler an, den geeignete Bytes), und führen Sie dann Ihre Binärdatei durch iaca.exe
. Die aktuelle Version (v2.2) unterstützt nur 64-Bit-Binärdateien, aber das ist keine große Einschränkung, da die Analyse auf Befehlsebene für 32-Bit- und 64-Bit-Modi nicht wesentlich unterschiedlich ist. Die aktuelle Version unterstützt auch alle modernen Intel-Mikroarchitekturen, die für einen professionellen Softwareentwickler von Nehalem bis Broadwell interessant sein könnten.
Die Ausgabe, die Sie von diesem Tool erhalten, zeigt Ihnen an, auf welchen Ports eine bestimmte Anweisung ausgeführt werden kann und wie viele μops diese Anweisung in der angegebenen Mikroarchitektur zerlegt wird.
Das ist so nah wie Sie zu einer direkten Antwort auf Ihre Frage erhalten, da als , die genauen μops, dass jeder Befehl zerlegt wird, von Intel absichtlich geheim gehalten werden. Sie sind nicht nur ein proprietäres Geschäftsgeheimnis, sondern Intel will frei sein, wie es von einer Mikroarchitektur zur anderen funktioniert. In der Tat jedoch wie viele μops eine Anweisung zerlegt, ist alles, was Sie jemals wissen möchten, wenn Sie Code optimieren. Es spielt keine Rolle welche μops die Anweisung zerlegt zu.
Aber ich würde noch einmal einen Teil von Peter Cordes's answer wiederholen: "Es ist leicht zu erraten in einigen Fällen, obwohl". Wenn Sie diese Art von detaillierten Informationen für jede Anweisung, die Sie in Betracht ziehen, nachschlagen müssen, werden Sie eine Menge Zeit verschwenden. Sie werden sich auch wahnsinnig machen, denn wie Sie bereits wissen, variiert es von Mikroarchitektur zu Mikroarchitektur. Der eigentliche Trick besteht darin, ein intuitives Gefühl dafür zu bekommen, welche Anweisungen in der x86-ISA "einfach" und welche "komplex" sind. Es sollte ziemlich offensichtlich sein, wenn Sie die Dokumentation lesen, und dieses intuitive Gefühl ist wirklich alles, was die Optimierungsempfehlungen von Intel Ihnen aufzeigen. Vermeiden Sie "komplexe" (alte CISC-artige) Anweisungen wie LOOP
, ENTER
, LEAVE
und so weiter. Zum Beispiel bevorzugen Sie DEC
+ JNZ
über LOOP
. Relativ gesehen gibt es nur eine kleine Minderheit von "klassischen" x86-Anweisungen, die zu mehr als ein oder zwei μops dekodieren. * Das Studieren der Ausgabe eines guten optimierenden Compilers wird Sie auch in die richtige Richtung führen, da Sie nie sehen werden, dass Compiler diese "komplexen" Anweisungen verwenden.
Etwas contra Peters Antwort, bin ich jedoch ziemlich sicher, dass der zitierte Abschnitt der Optimierung Handbücher Intel nicht Bezug auf die SIMD-Befehle sind. Sie sprechen über die CISC-Anweisungen der alten Schule, die in Mikrocode implementiert sind und die sie bereits gelöscht hätten, wenn sie sie nicht aus Gründen der Abwärtskompatibilität unterstützen müssten. Wenn Sie das Verhalten von SSE3's HADDPS
benötigen, dann sind Sie wahrscheinlich besser dran mit HADDPS
anstatt zu versuchen, es in "einfachere" Komponenten zu zerlegen. (Es sei denn natürlich können Sie Zeitplan diese Vorgänge besser, indem sie in keinem Zusammenhang Code Verschachtelung. Aber das ist furchtbar schwer in der Praxis zu tun.)
* Um ganz genau zu sein, da sie sicher sind, scheinbar einfache Anweisungen, die tatsächlich unter Verwendung von Mikrocode implementiert werden und zu mehreren μops zerlegen. Eine 64-Bit-Division (DIV
) ist ein Beispiel. Wenn ich mich richtig erinnere, ist dies mikrocodiert mit etwa 30-40 μops (variabel). Dies ist jedoch keine Anweisung, die Sie vermeiden sollten. Dies zeigt, dass die Handbücher von Intel hier sehr allgemein gehalten sind. Wenn Sie eine Division durchführen müssen, verwenden Sie DIV
. Natürlich bevorzugen nicht Divisionen bei der Optimierung für die Geschwindigkeit zu tun, aber versuchen Sie nicht, Ihre eigenen Division Algorithmus zu schreiben, nur um die mikrocodierte DIV
zu vermeiden, entweder!
Die andere große Ausnahme sind hier die string instructions. Der Performance-Kalkül für diese ist etwas komplizierter als "vermeiden, weil sie zu mehreren μops dekodieren".
, Glück eine Sache ist einfach: nie die Zeichenfolge Anweisungen ohne ein REP
Präfix verwenden. Das ist einfach nicht sinnvoll, und Sie erhalten eine wesentlich bessere Leistung, wenn Sie die Anweisung selbst in die einfacheren Komponentenanweisungen zerlegen - zum Beispiel MOVSB
+ INC/DEC ESI
+ INC/DEC EDI
.
Wo es etwas schwieriger zu entscheiden ist, wenn Sie beginnen, die Vorteile des REP
Präfix zu nutzen. Obwohl dies dazu führt, dass die Anweisung in viele μops dekodiert, ist es manchmal noch effizienter, die wiederholten String-Anweisungen zu verwenden, als die Schleife manuell selbst zu codieren. Aber nicht immer. Es gab viele Diskussionen zu diesem Thema bereits auf Stack Overflow und anderswo; siehe zum Beispiel this question.
Eine detaillierte Analyse geht über den Rahmen dieser Antwort wirklich, aber meine schnelle Faustregel ist, dass Sie über REP LOADS
vergessen, REP SCAS
und REP CMPS
vollständig. Auf der anderen Seite sind REP MOVS
und REP STOS
nützlich when you need to repeat a reasonably large number of times. Verwenden Sie immer die größte mögliche Wortgröße: DWORD auf 32-Bit, QWORD auf 64-Bit (aber beachten Sie, dass on modern processors, you may be better off using MOVSB
/STOSB
, since they can move larger quantities internally. Und auch wenn alle diese Bedingungen erfüllt sind, wenn Ihr Ziel Vector Anweisungen zur Verfügung hat, möchten Sie wahrscheinlich überprüfen, dass es würde nicht schneller sein, den Zug/Speicher mit Vektor bewegt. ein Geschäftsgeheimnis zu implementieren und für jede Mikroarchitektur
Siehe auch Agner Fog's general advice on page 150.
Sie können nicht, sie sind ändern. Aktuelle Tendenz um sie wieder CISC-like zu machen durch * fusion * Agner Fogs [Anweisungstabellen Dokument] (http://www.agner.org/optimize/) ist eine sehr anständige Ressource. –
@HansPassant, sieht aus wie die Instr Tabellen, mit denen Sie verbunden sind, sind die beste verfügbare Referenz. Willst du das beantworten, damit ich es annehmen kann? –
mögliches Duplikat von [Warum versteckt Intel den internen RISC-Kern in seinen Prozessoren?] (Http://stackoverflow.com/questions/5806589/why-does-intel-hide-internal-risc-core-in-the-processors) –