Warum versteckt Intel den internen RISC-Kern in seinen Prozessoren?

89

Beginnend mit Pentium Pro (P6-Mikroarchitektur) hat Intel seine Mikroprozessoren neu gestaltet und den internen RISC-Kern gemäß den alten CISC-Anweisungen verwendet. Seit Pentium Pro werden alle CISC-Anweisungen in kleinere Teile (uops) unterteilt und dann vom RISC-Kern ausgeführt.

Am Anfang war mir klar, dass Intel beschlossen hat, neue interne Architekturen zu verbergen und Programmierer zur Verwendung der "CISC-Shell" zu zwingen. Dank dieser Entscheidung konnte Intel die Mikroprozessorarchitektur vollständig neu gestalten, ohne die Kompatibilität zu beeinträchtigen. Dies ist vernünftig.

Eines verstehe ich jedoch nicht, warum Intel einen internen RISC-Befehlssatz immer noch so viele Jahre lang versteckt hält. Warum ließen sie Programmierer keine RISC-Anweisungen wie die alten x86-CISC-Anweisungen verwenden?

Wenn Intel die Abwärtskompatibilität so lange beibehält (wir haben immer noch den virtuellen 8086-Modus neben dem 64-Bit-Modus), warum erlauben sie uns nicht, Programme zu kompilieren, damit sie CISC-Anweisungen umgehen und den RISC-Kern direkt verwenden? Dies eröffnet eine natürliche Möglichkeit, den x86-Befehlssatz, der heutzutage veraltet ist, langsam aufzugeben (dies ist der Hauptgrund, warum Intel sich für die Verwendung des RISC-Kerns im Inneren entschieden hat, oder?).

Wenn ich mir die neue Intel Core i-Serie anschaue, sehe ich, dass sie nur den CISC-Befehlssatz um AVX, SSE4 und andere erweitert.

Doof
quelle
1
Beachten Sie, dass es bestimmte x86-CPUs gibt, auf denen der interne RISC-Befehlssatz
verfügbar

Antworten:

90

Nein, der x86-Befehlssatz ist sicherlich nicht veraltet. Es ist so beliebt wie immer. Der Grund, warum Intel intern eine Reihe von RISC-ähnlichen Mikrobefehlen verwendet, liegt darin, dass sie effizienter verarbeitet werden können.

Eine x86-CPU verfügt also über einen ziemlich leistungsstarken Decoder im Frontend, der x86-Anweisungen akzeptiert und in ein optimiertes internes Format konvertiert, das das Backend verarbeiten kann.

Es gibt zwei Punkte, um dieses Format "externen" Programmen auszusetzen:

  • Es ist kein stabiles Format. Intel kann es zwischen CPU-Modellen ändern, um es an die spezifische Architektur anzupassen. Dies ermöglicht es ihnen, die Effizienz zu maximieren, und dieser Vorteil würde verloren gehen, wenn sie sich auf ein festes, stabiles Anweisungsformat für den internen und externen Gebrauch festlegen müssten.
  • Es gibt einfach nichts zu gewinnen, wenn man es tut. Bei den heutigen großen, komplexen CPUs ist der Decoder ein relativ kleiner Teil der CPU. Das Dekodieren von x86-Befehlen macht dies komplexer, aber der Rest der CPU bleibt davon unberührt. Insgesamt ist also nur sehr wenig zu gewinnen, insbesondere weil das x86-Frontend noch vorhanden sein müsste, um "Legacy" -Code auszuführen . Sie würden also nicht einmal die derzeit im x86-Frontend verwendeten Transistoren speichern.

Dies ist keine perfekte Anordnung, aber die Kosten sind relativ gering, und es ist eine viel bessere Wahl, als die CPU so zu gestalten, dass sie zwei völlig unterschiedliche Befehlssätze unterstützt. (In diesem Fall würden sie wahrscheinlich einen dritten Satz von Micro-Ops für den internen Gebrauch erfinden , nur weil diese frei angepasst werden können, um der internen Architektur der CPU am besten zu entsprechen.)

jalf
quelle
1
Gute Argumente. RISC ist eine gute Kernarchitektur, bei der GUT bedeutet, dass es schnell läuft und korrekt implementiert werden kann. X86 ISA mit einer CISC-Architekturhistorie ist erst jetzt ein Befehlssatzlayout mit einer riesigen Historie und einer fabelhaften Fülle an Binärsoftware sowie effizient für die Lagerung und Verarbeitung. Es ist keine CISC-Shell, sondern der branchenübliche Standard-ISA.
Warren P
2
@ Warren: Im letzten Teil glaube ich das eigentlich nicht. Ein gut gestalteter CISC-Befehlssatz ist in Bezug auf die Speicherung effizienter, ja, aber nach den wenigen Tests, die ich gesehen habe, ist der "durchschnittliche" x86-Befehl ungefähr 4,3 Byte breit, was mehr ist, als er normalerweise ist eine RISC-Architektur. x86 verliert viel Speichereffizienz, weil es im Laufe der Jahre so willkürlich entworfen und erweitert wurde. Aber wie Sie sagen, ist seine Hauptstärke die Geschichte und die große Menge an vorhandenem Binärcode.
Jalf
1
Ich habe nicht gesagt, dass es "gut gestaltete CISC" ist, nur "große Geschichte". Die GUTEN Teile sind die RISC-Chip-Designteile.
Warren P
2
@jalf - Nach der Überprüfung der tatsächlichen Binärdateien beträgt die Befehlsgröße in x86 durchschnittlich jeweils 3 Byte. Es gibt natürlich viel längere Anweisungen, aber die kleineren dominieren im tatsächlichen Gebrauch.
srking
1
Die durchschnittliche Befehlslänge ist kein gutes Maß für die Codedichte: Der häufigste Typ von x86-Befehl in typischem Code ist das Laden und Speichern (nur das Verschieben von Daten an den Ort, an dem sie verarbeitet werden können, und zurück in den Speicher, den RISC-Prozessoren und etwa die Hälfte des CISC haben Viele Register müssen also nicht so viel tun. Auch wie viel kann eine Anweisung tun (
Armanweisungen
20

Die wirkliche Antwort ist einfach.

Der Hauptfaktor für die Implementierung von RISC-Prozessoren war die Reduzierung der Komplexität und die Steigerung der Geschwindigkeit. Der Nachteil von RISC ist die reduzierte Befehlsdichte. Dies bedeutet, dass derselbe Code, der im RISC-ähnlichen Format ausgedrückt wird, mehr Befehle benötigt als der entsprechende CISC-Code.

Dieser Nebeneffekt bedeutet nicht viel, wenn Ihre CPU mit der gleichen Geschwindigkeit wie der Speicher läuft oder zumindest wenn beide mit einigermaßen ähnlichen Geschwindigkeiten laufen.

Derzeit zeigt die Speichergeschwindigkeit im Vergleich zur CPU-Geschwindigkeit einen großen Unterschied bei den Takten. Aktuelle CPUs sind manchmal fünfmal oder schneller als der Hauptspeicher.

Dieser Stand der Technik begünstigt einen dichteren Code, den CISC bereitstellt.

Sie können argumentieren, dass Caches RISC-CPUs beschleunigen könnten. Gleiches gilt für CISC cpus.

Durch die Verwendung von CISC und Caches wird eine größere Geschwindigkeitsverbesserung erzielt als mit RISC und Caches, da der Cache derselben Größe mehr Einfluss auf den von CISC bereitgestellten Code mit hoher Dichte hat.

Ein weiterer Nebeneffekt ist, dass RISC die Compiler-Implementierung erschwert. Es ist einfacher, Compiler für CISC-CPUs zu optimieren. etc.

Intel weiß, was sie tun.

Dies ist so wahr, dass ARM einen Modus mit höherer Codedichte namens Thumb hat.

Jorge Aldo
quelle
1
Auch ein interner RISC-Kern reduziert die Transistoranzahl auf einer CISC-CPU. Anstatt jeden CISC-Befehl fest zu verdrahten, können Sie ihn mit Mikrocode ausführen. Dies führt dazu, dass RISC-Mikrocode-Anweisungen für verschiedene CISC-Anweisungen wiederverwendet werden, wodurch weniger Chipfläche verwendet wird.
Sil
16

Wenn Intel die Abwärtskompatibilität so lange beibehält (wir haben immer noch den virtuellen 8086-Modus neben dem 64-Bit-Modus), warum erlauben sie uns nicht, Programme zu kompilieren, damit sie CISC-Anweisungen umgehen und den RISC-Kern direkt verwenden? Dies eröffnet eine natürliche Möglichkeit, den x86-Befehlssatz, der heutzutage veraltet ist, langsam aufzugeben (dies ist der Hauptgrund, warum Intel sich für die Verwendung des RISC-Kerns im Inneren entschieden hat, oder?).

Sie müssen den geschäftlichen Aspekt betrachten. Intel hat tatsächlich versucht, sich von x86 zu entfernen, aber es ist die Gans, die goldene Eier für das Unternehmen legt. XScale und Itanium haben noch nie den Erfolg ihres x86-Kerngeschäfts erreicht.

Was Sie im Grunde verlangen, ist, dass Intel seine Handgelenke aufschlitzt, um die warmen Unschärfen der Entwickler zu erhalten. X86 zu untergraben ist nicht in ihrem Interesse. Alles, was mehr Entwickler dazu bringt, sich nicht für x86 zu entscheiden, untergräbt x86. Das wiederum untergräbt sie.

Mike Thomsen
quelle
6
Ja, als Intel dies versuchte (Itanium), reagierte der Markt nur mit einem Achselzucken.
Warren P
Es sollte beachtet werden, dass es eine Vielzahl von Faktoren gab, während Itanium versagte, und nicht nur, weil es eine neue Architektur war. Zum Beispiel das Auslagern der CPU-Planung auf einen Compiler, der sein Ziel nie erreicht hat. Wenn das Itanium 10x oder 100x schneller als x86-CPUs wäre, hätte es sich wie heiße Kuchen verkauft. Aber es war nicht schneller.
Katastic Voyage
5

Die Antwort ist einfach. Intel entwickelt keine CPUs für Entwickler ! Sie entwickeln sie für die Menschen, die die Kaufentscheidungen treffen, was übrigens jedes Unternehmen auf der Welt tut!

Intel hat vor langer Zeit die Zusage gemacht, dass (natürlich im Rahmen des Zumutbaren) die CPUs abwärtskompatibel bleiben. Die Leute möchten wissen, dass beim Kauf eines neuen Intel-basierten Computers die gesamte aktuelle Software genauso ausgeführt wird wie auf ihrem alten Computer. (Obwohl hoffentlich schneller!)

Darüber hinaus weiß Intel genau, wie wichtig dieses Engagement ist, weil sie einmal versucht haben, einen anderen Weg zu gehen. Wie viele Leute kennen Sie genau mit einer Itanium-CPU?!?

Sie mögen es vielleicht nicht mögen, aber diese eine Entscheidung, beim x86 zu bleiben, hat Intel zu einem der bekanntesten Firmennamen der Welt gemacht!

geo
quelle
2
Ich bin nicht einverstanden mit der Andeutung, dass Intel-Prozessoren nicht entwicklerfreundlich sind. Nachdem ich PowerPC und x86 viele Jahre lang programmiert habe, bin ich zu der Überzeugung gelangt, dass CISC viel programmiererfreundlicher ist. (Ich arbeite jetzt für Intel, aber ich habe mich vor meiner Einstellung für dieses Thema entschieden.)
Jeff
1
@ Jeff Das war überhaupt nicht meine Absicht! Die Frage war, warum Intel den RISC-Befehlssatz nicht geöffnet hat, damit Entwickler ihn verwenden können. Ich habe nichts darüber gesagt , dass x86 nicht entwicklerfreundlich ist. Was ich sagte, war, dass Entscheidungen wie diese nicht mit Blick auf Entwickler getroffen wurden , sondern ausschließlich geschäftliche Entscheidungen waren.
Geo
5

Die Antwort von @ jalf deckt die meisten Gründe ab, aber es gibt ein interessantes Detail, das nicht erwähnt wird: Der interne RISC-ähnliche Kern ist nicht dafür ausgelegt, einen Befehlssatz wie ARM / PPC / MIPS auszuführen. Die x86-Steuer wird nicht nur in den stromhungrigen Decodern gezahlt, sondern bis zu einem gewissen Grad im gesamten Kern. dh es ist nicht nur die x86-Befehlskodierung; Es ist jede Anweisung mit seltsamer Semantik.

Stellen wir uns vor, Intel hätte einen Betriebsmodus erstellt, in dem der Anweisungsstrom etwas anderes als x86 war, mit Anweisungen, die direkter auf uops abgebildet wurden. Stellen wir uns auch vor, dass jedes CPU-Modell für diesen Modus eine eigene ISA hat, sodass sie die Interna jederzeit ändern können, wenn sie möchten, und sie mit einer minimalen Anzahl von Transistoren für die Befehlsdecodierung dieses alternativen Formats belichten können.

Vermutlich haben Sie immer noch nur die gleiche Anzahl von Registern, die dem x86-Architekturstatus zugeordnet sind, sodass x86-Betriebssysteme diese auf Kontextschaltern speichern / wiederherstellen können, ohne den CPU-spezifischen Befehlssatz zu verwenden. Aber wenn wir diese praktische Einschränkung aufheben, könnten wir ja noch ein paar Register haben, weil wir die versteckten temporären Register verwenden können, die normalerweise für Mikrocode 1 reserviert sind .


Wenn wir nur alternative Decoder ohne Änderungen an späteren Pipeline-Stufen (Ausführungseinheiten) haben, hätte diese ISA immer noch viele x86-Exzentrizitäten. Es wäre keine sehr schöne RISC-Architektur. Keine einzelne Anweisung wäre sehr komplex, aber ein Teil der anderen Verrücktheit von x86 wäre immer noch da.

Beispiel: Links- / Rechtsverschiebungen lassen das Überlauf-Flag undefiniert, es sei denn, die Verschiebungszahl ist eins. In diesem Fall ist OF = die übliche Vorzeichenüberlauferkennung. Ähnliche Verrücktheit für Rotationen. Die exponierten RISC-Anweisungen können jedoch Flag-freie Verschiebungen usw. bereitstellen (sodass nur ein oder zwei der mehreren Uops verwendet werden können, die normalerweise in einigen komplexen x86-Anweisungen enthalten sind). Dies ist also nicht das Hauptgegenargument.

Wenn Sie einen völlig neuen Decoder für eine RISC-ISA erstellen möchten, können Sie Teile von x86-Anweisungen auswählen, die als RISC-Anweisungen verfügbar gemacht werden sollen. Dies verringert die x86-Spezialisierung des Kerns etwas.


Die Befehlskodierung hätte wahrscheinlich keine feste Größe, da einzelne Uops viele Daten enthalten können. Viel mehr Daten als sinnvoll, wenn alle Insns gleich groß sind. Ein einzelnes mikrofusioniertes UOP kann einen 32-Bit-Sofort- und einen Speicheroperanden hinzufügen, der einen Adressierungsmodus mit 2 Registern und einer 32-Bit-Verschiebung verwendet. (In SnB und höher können nur Einzelregister-Adressierungsmodi mit ALU-Operationen mikrosicher werden.)

Uops sind sehr groß und ARM-Anweisungen mit fester Breite nicht sehr ähnlich. Ein 32-Bit-Befehlssatz mit fester Breite kann jeweils nur 16-Bit-Befehle sofort laden. Das Laden einer 32-Bit-Adresse erfordert daher ein Paar mit sofortiger Last, niedriger Hälfte und hoher Höhe. x86 muss das nicht tun, was dazu beiträgt, dass es nicht schrecklich ist, wenn nur 15 GP-Register die Fähigkeit einschränken, Konstanten in Registern zu halten. (15 ist eine große Hilfe gegenüber 7 Registern, aber ein erneutes Verdoppeln auf 31 hilft viel weniger, ich denke, einige Simulationen wurden gefunden. RSP ist normalerweise kein allgemeiner Zweck, daher ähnelt es eher 15 GP-Registern und einem Stapel.)


TL; DR Zusammenfassung:

Wie auch immer, diese Antwort läuft darauf hinaus, "der x86-Befehlssatz ist wahrscheinlich der beste Weg, um eine CPU zu programmieren, die in der Lage sein muss, x86-Befehle schnell auszuführen", wirft aber hoffentlich etwas Licht auf die Gründe.


Interne UOP-Formate im Front-End vs. Back-End

Siehe auch Mikrofusions- und Adressierungsmodi für einen Fall von Unterschieden in den Front-End- und Back-End-UOP-Formaten auf Intel-CPUs.

Fußnote 1 : Es gibt einige "versteckte" Register, die als temporäre Register per Mikrocode verwendet werden können. Diese Register werden genau wie die x86-Architekturregister umbenannt, sodass Multi-UOP-Anweisungen nicht in der richtigen Reihenfolge ausgeführt werden können.

Beispiel: xchg eax, ecxAuf Intel-CPUs werden 3 Uops dekodiert ( warum? ), und wir vermuten, dass dies MOV-ähnliche Uops sind, die dies tun tmp = eax; ecx=eax ; eax=tmp;. In dieser Reihenfolge, weil ich die Latenz der dst-> src-Richtung bei ~ 1 Zyklus messe, gegenüber 2 für die andere Richtung. Und diese Bewegungen sind keine normalen movAnweisungen. Sie scheinen keine Kandidaten für die Eliminierung von Bewegungen ohne Latenz zu sein.

Unter http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ wird auch erwähnt, dass versucht wird, die PRF-Größe experimentell zu messen, und dass physische Register berücksichtigt werden müssen, die zum Halten des Architekturstatus verwendet werden, einschließlich versteckter Register.

Im Front-End nach den Decodern, jedoch vor der Ausgabe- / Umbenennungsphase, in der Register in die physische Registerdatei umbenannt werden, verwendet das interne UOP-Format Registernummern, die den x86-Registrierungsnummern ähneln, jedoch Platz zum Adressieren dieser versteckten Register bieten.

Das UOP-Format ist innerhalb des nicht in Ordnung befindlichen Kerns (ROB und RS), auch bekannt als Back-End (nach der Ausgabe- / Umbenennungsphase), etwas anders. Die physischen int / FP-Registerdateien haben jeweils 168 Einträge in Haswell , daher muss jedes Registerfeld in einem UOP breit genug sein, um so viele zu adressieren.

Da der Renamer in der HW vorhanden ist, ist es wahrscheinlich besser, ihn zu verwenden, als statisch geplante Anweisungen direkt an das Back-End zu senden. Wir würden also mit einer Reihe von Registern arbeiten, die so groß sind wie die x86-Architekturregister + Mikrocode-Provisorien, nicht mehr.

Das Back-End ist so konzipiert, dass es mit einem Front-End-Renamer arbeitet, der WAW / WAR-Gefahren vermeidet. Daher könnten wir es nicht wie eine in Ordnung befindliche CPU verwenden, selbst wenn wir dies wollten. Es gibt keine Verriegelungen, um diese Abhängigkeiten zu erkennen. Dies wird durch Ausgabe / Umbenennung behandelt.

Es könnte ordentlich sein, wenn wir Uops in das Back-End einspeisen könnten, ohne den Engpass der Problem- / Umbenennungsphase (der engste Punkt in modernen Intel-Pipelines, z. B. 4-breit bei Skylake vs. 4 ALU + 2 Lade- + 1 Speicherports in) das Backend). Aber wenn Sie das getan haben, können Sie Code nicht statisch planen, um die Wiederverwendung von Registern zu vermeiden und auf ein Ergebnis zuzugreifen, das noch benötigt wird, wenn ein Cache-Miss eine Last für längere Zeit blockiert.

Wir müssen also so ziemlich Uops in die Issue / Rename-Phase einspeisen und wahrscheinlich nur die Dekodierung umgehen, nicht den UOP-Cache oder die IDQ. Dann erhalten wir normale OoO-Execs mit vernünftiger Gefahrenerkennung. Die Registerzuordnungstabelle dient nur zum Umbenennen von 16 + einigen Ganzzahlregistern in die Ganzzahl-PRF mit 168 Einträgen. Wir konnten nicht erwarten, dass die HW einen größeren Satz logischer Register in dieselbe Anzahl physischer Register umbenennt. das würde eine größere RAT erfordern.

Peter Cordes
quelle
-3

Warum erlauben sie uns nicht, Programme zu kompilieren, damit sie CISC-Anweisungen umgehen und den RISC-Kern direkt verwenden?

Neben den vorherigen Antworten ist ein weiterer Grund die Marktsegmentierung. Es wird angenommen, dass einige Anweisungen eher in Mikrocode als in Hardware implementiert sind. Wenn also jeder willkürliche Mikrooperationen ausführen kann, kann dies den Verkauf neuer CPUs mit "neuen" leistungsfähigeren CISC-Anweisungen untergraben.

KOLANICH
quelle
1
Ich denke nicht, dass das Sinn macht. Ein RISC kann Mikrocode verwenden, insbesondere wenn es darum geht, einem x86-Frontend nur RISC-Decoder hinzuzufügen.
Peter Cordes
2
Das ist immer noch falsch. Die neuen AES-Anweisungen (und die kommenden SHA-Anweisungen) und andere Dinge wie PCLMULQDQ verfügen über dedizierte Hardware. Auf Haswell dekodiert AESENC zu einem einzigen UOP ( agner.org/optimize ), sodass es definitiv überhaupt nicht mikrocodiert ist. (Die Decoder müssen nur den Mikrocode-ROM-Sequenzer für Anweisungen aktivieren, die auf mehr als 4 Uops decodieren .)
Peter Cordes
1
Sie haben Recht, dass einige neue Anweisungen vorhandene Funktionen nur auf eine Weise verwenden, die mit x86-Anweisungen nicht verfügbar ist. Ein gutes Beispiel wäre BMI2 SHLX , mit dem Sie Verschiebungen mit variabler Anzahl durchführen können, ohne die Zählung in CL zu setzen und ohne die zusätzlichen Uops zu verursachen, die für die Behandlung der beschissenen x86-Flag-Semantik erforderlich sind (Flags werden nicht geändert, wenn die Anzahl der Verschiebungen Null SHL r/m32, clist eine Eingabeabhängigkeit von FLAGS und dekodiert auf 3 Uops auf Skylake. Es war jedoch nur 1 UOP auf Core2 / Nehalem, laut Agner Fogs Tests.)
Peter Cordes
Vielen Dank für Ihre Kommentare.
KOLANICH