In der Rechnerarchitektur ist die Registerumbenennung eine Technik, die logische von physischen Registern abstrahiert . Jedem logischen Register ist eine Menge physischer Register zugeordnet. Wenn ein Maschinenbefehl auf ein bestimmtes logisches Register verweist, transponiert der Prozessor diesen Namen dynamisch in ein spezifisches physisches Register. Die physischen Register sind undurchsichtig und können nicht direkt, sondern nur über ihre kanonischen Namen angesprochen werden.

Diese Technik dient dazu, falsche Datenabhängigkeiten zu eliminieren , die durch die Wiederverwendung von Registern durch aufeinanderfolgende Befehle entstehen , unter denen keine tatsächlichen Datenabhängigkeiten bestehen. Die Beseitigung dieser falschen Datenabhängigkeiten legt eine höhere Parallelität auf Befehlsebene in einem Befehlsstrom offen, die durch verschiedene und komplementäre Techniken wie superskalare und Out-of-Order-Ausführung für eine bessere Performance genutzt werden kann .

Problemansatz

Programme bestehen aus Anweisungen, die Werte verarbeiten. Die Anweisungen müssen diese Werte benennen, um sie voneinander zu unterscheiden. Eine typische Anweisung könnte lauten: „Addiere x und y und speichere das Ergebnis in x “. In dieser Anweisung sind x, y und y die Namen von Speicheradressen.

Es kommt häufig vor, dass die verarbeiteten Werte mehrmals hintereinander verwendet werden. Registermaschinen nutzen dies aus, indem sie eine Reihe von Prozessorregistern einführen . Diese Register sind Hochgeschwindigkeitsspeicher, die diese Werte speichern. Da der Zugriff auf Register in der Regel viel schneller ist als der Zugriff auf den Arbeitsspeicher , versuchen Hochleistungscode und -prozessoren, wenn möglich, mit Registern zu arbeiten. Die Gesamtheit der Register eines bestimmten Designs wird als Registerdatei bezeichnet .

Individual registers in the file are referred to by number in the machine code. Encoding a number in the machine code requires several bits. For instance, in the Zilog Z80 there were eight general-purpose registers in the file. To select one of eight values requires three bits, as 23 = 8. More architectural (logical) registers of the same width and type can result in better performance, as more temporary values can be held in registers and thus avoid the expensive operations of saving or loading from memory. Similarly, wider registers that can hold more data can also improve performance, if the workload can make use of that. Generally, more modern processors and those with larger instruction words will use more registers when possible. For example, the IA-32 instruction set architecture has 8 general purpose registers, x86-64 has 16, many RISCs have 32, and IA-64 has 128.

The advantages of a larger register file are offset by the need to use more bits to encode the register number. For instance, in a system using 32-bit instructions, you might wish to have three registers, such that you can perform operations of the type = . If the register file contains 32 entries, each one of the references will require 5 bits, and the set of three registers thus takes up 15 bits, leaving 17 to encode the operation and other information. Expanding the register file to 64 entries would require 6 bits, a total of 18 bits. While this may result in faster performance, it also means there are fewer bits left over for encoding the instruction. This leads to an effort to balance the size of the file with the number of possible instructions.

Out-of-order

Prozessoren früher Computer arbeiteten oft synchron mit dem Hauptspeicher, was die Vorteile großer Registerdateien schmälerte. Ein gängiger Designansatz im Minicomputer -Markt der 1960er-Jahre war die physische Implementierung der Register im Hauptspeicher. Der Leistungsvorteil bestand darin, dass der Befehl direkt auf die Speicheradresse zugreifen konnte, anstatt ein oder zwei zusätzliche Bytes für die vollständige Adresse zu benötigen. Dadurch wurden die Befehle kleiner und somit schneller lesbar. Diese Art von Design, die die Leistung durch eine sorgfältige Optimierung des Befehlssatzes auf minimale Größe maximierte, war bis in die 1980er-Jahre üblich. Ein Beispiel hierfür ist der MOS 6502 , der nur ein einziges Register besaß – in diesem Fall als Akkumulator bezeichnet – und einen speziellen „Nullseiten“-Adressierungsmodus für die ersten 256 Bytes des Speichers. Durch die Platzierung von Code und Daten auf der Nullseite war der Befehl nur zwei statt drei Bytes lang, was die Leistung durch vermiedene Lesezugriffe erheblich verbesserte und ähnliche Vorteile wie zusätzliche Register bot.

Die weitverbreitete Einführung von dynamischem RAM in den 1970er Jahren veränderte diesen Ansatz. Da die Leistung der Zentralprozessoren (CPUs) im Verhältnis zum angeschlossenen Speicher stetig zunahm, war es nicht mehr sinnvoll, den Hauptspeicher als Register zu verwenden. Dies führte zu immer größeren, internen Registerdateien der CPU, um Speicherzugriffe nach Möglichkeit zu vermeiden. In der Praxis lässt sich der Speicherzugriff jedoch nicht vollständig vermeiden, und mit zunehmendem Geschwindigkeitsunterschied wurde jeder Zugriff immer aufwändiger, da die Anzahl der Befehle, die durch die Speicherung des Wertes in einem Register hätten ausgeführt werden können, deutlich höher war.

Unterschiedliche Befehle können unterschiedlich lange dauern; beispielsweise kann ein Prozessor Hunderte von Registerzugriffsbefehlen ausführen, während gleichzeitig ein einzelner Ladevorgang aus dem Hauptspeicher läuft. Ein wichtiger Fortschritt zur Leistungssteigerung besteht darin, diese schnellen Befehle auszuführen, während die anderen auf Daten warten. Das bedeutet, dass die Befehle nicht mehr in der Reihenfolge ihres Maschinencodes, sondern in beliebiger Reihenfolge abgearbeitet werden .

Betrachten Sie folgenden Codeabschnitt, der auf einer CPU mit Out-of-Order-Verarbeitung ausgeführt wird:

r1 ≔ m [ 1024 ] ;lies den Wert an Speicheradresse 1024r1 ≔ r1 + 2 ; addiere zwei zum Wertm [ 1032 ] ≔ r1 ;Speichere das Ergebnis an Adresse 1032r1 ≔ m [ 2048 ] ; Wert in 2048 lesenr1 ≔ r1 + 4 ;add 4m [ 2056 ] ≔ r1 ;speichere es in 2056

Die Anweisungen in den letzten drei Zeilen sind unabhängig von den ersten drei Anweisungen, aber der Prozessor kann nicht fertig werden , bis die vorhergehenden abgeschlossen sind, da sonst vier zum Wert von 1024 addiert würden, nicht zu 2048. r1 ≔ m[2048]m[1032] ≔ r1

Falls ein anderes Register verfügbar ist, kann diese Einschränkung aufgehoben werden, indem für die ersten drei und die zweiten drei Befehle unterschiedliche Register gewählt werden:

r1 ≔ m [ 1024 ]r1 ≔ r1 + 2m [ 1032 ] ≔ r1r2 ≔ m [ 2048 ]r² ≔ r² + 4m [ 2056 ] ≔ r2

Die letzten drei Anweisungen können nun parallel zu den ersten drei ausgeführt werden. Das Programm läuft schneller als zuvor, da die Datenabhängigkeit durch die unnötige Verwendung desselben Registers in beiden Sequenzen beseitigt wird. Ein Compiler kann unabhängige Anweisungssequenzen erkennen und, falls Register verfügbar sind, bei der Registerzuweisung während der Codegenerierung unterschiedliche Register auswählen .

Um jedoch Code zu beschleunigen, der von Compilern generiert wird, die diese Optimierung nicht durchführen, oder Code, für den nicht genügend Register zur Durchführung dieser Optimierung vorhanden waren, stellen viele Hochleistungs-CPUs eine Registerdatei mit mehr Registern bereit, als im Befehlssatz angegeben sind, und benennen in Hardware Referenzen in den im Befehlssatz definierten Registern so um, dass sie auf Register in der Registerdatei verweisen, sodass sich die ursprüngliche Befehlssequenz, die nur r1 verwendet, so verhält, als ob sie:

rA ≔ m [ 1024 ]rA ≔ rA + 2m [ 1032 ] ≔ rArB ≔ m [ 2048 ]rB ≔ rB + 4m [ 2056 ] ≔ rB

Das Register r1 wird für die ersten drei Befehle in internes Register rA und für die zweiten drei Befehle in internes Register rB umbenannt. Dadurch wird die falsche Datenabhängigkeit beseitigt, sodass die ersten drei Befehle parallel zu den zweiten drei ausgeführt werden können.

Datengefahren

Wenn mehrere Befehle auf einen bestimmten Speicherort als Operanden verweisen, entweder durch Lesen (als Eingabe) oder durch Schreiben (als Ausgabe), kann die Ausführung dieser Befehle in einer anderen Reihenfolge als der ursprünglichen Programmreihenfolge zu drei Arten von Datenkonflikten führen:

Lesen nach Schreiben (RAW)
Ein Lesevorgang aus einem Register oder einer Speicherzelle muss den Wert zurückgeben, der dort durch den letzten Schreibvorgang in Programmreihenfolge gespeichert wurde, und nicht einen anderen Schreibvorgang. Dies wird als echte Abhängigkeit oder Ablaufabhängigkeit bezeichnet und erfordert, dass die Anweisungen in Programmreihenfolge ausgeführt werden.
Write-after-write (WAW)
Aufeinanderfolgende Schreibvorgänge in ein bestimmtes Register oder eine Speicherzelle müssen das Ergebnis des zweiten Schreibvorgangs enthalten. Dies kann gegebenenfalls durch das Überschreiben (auch bekannt als Abbrechen, Annullieren oder Wegwerfen) des ersten Schreibvorgangs behoben werden. WAW-Abhängigkeiten werden auch als Ausgabeabhängigkeiten bezeichnet .
Write-after-read (WAR)
Ein Lesevorgang aus einem Register oder Speicherbereich muss den zuletzt an diesen Speicherbereich geschriebenen Wert zurückgeben und nicht einen Wert, der nach dem Lesevorgang programmatisch geschrieben wurde. Dies ist eine Art Scheinabhängigkeit , die durch Umbenennen behoben werden kann. WAR-Abhängigkeiten werden auch als Anti-Abhängigkeiten bezeichnet .

Anstatt den Schreibvorgang zu verzögern, bis alle Lesevorgänge abgeschlossen sind, können zwei Kopien des Speicherorts verwaltet werden: der alte und der neue Wert. Lesevorgänge, die in der Programmreihenfolge vor dem Schreiben des neuen Werts erfolgen, können mit dem alten Wert versorgt werden, während nachfolgende Lesevorgänge den neuen Wert erhalten. Die Scheinabhängigkeit wird aufgehoben und zusätzliche Möglichkeiten für die Ausführung in beliebiger Reihenfolge geschaffen. Sobald alle Lesevorgänge, die den alten Wert benötigen, abgeschlossen sind, kann dieser verworfen werden. Dies ist das grundlegende Prinzip der Registerumbenennung.

Alles, was gelesen und geschrieben wird, kann umbenannt werden. Am häufigsten werden zwar Allzweck- und Gleitkommaregister besprochen, aber auch Flag- und Statusregister oder sogar einzelne Statusbits werden häufig umbenannt.

Speicheradressen können auch umbenannt werden, allerdings nicht so häufig wie Register. Der getaktete Speicherpuffer des Transmeta-Crusoe- Prozessors ist eine Form der Speicherumbenennung.

Wenn Programme Register nicht sofort wiederverwenden würden, wäre eine Registerumbenennung überflüssig. Einige Befehlssätze (z. B. IA-64 ) spezifizieren aus genau diesem Grund eine sehr große Anzahl von Registern. Dieser Ansatz hat jedoch seine Grenzen:

  • Es ist für den Compiler sehr schwierig, die Wiederverwendung von Registern zu vermeiden, ohne den Codeumfang erheblich zu vergrößern. In Schleifen beispielsweise müssten aufeinanderfolgende Iterationen unterschiedliche Register verwenden, was entweder eine Duplikation des Codes in einem Prozess namens Schleifenabwickeln oder die Verwendung von selbstmodifizierendem Code erfordert , um die Operandenziele in jeder Iteration zu ändern.
  • Eine große Anzahl von Registern erfordert mehr Bits, um ein Register als Operanden in einer Anweisung anzugeben, was zu einer größeren Codegröße führt.
  • Viele Befehlssätze sahen historisch bedingt eine geringere Anzahl von Registern vor und können nicht geändert werden, ohne die Abwärtskompatibilität zu beeinträchtigen.

Die Vergrößerung der Codegröße ist deshalb wichtig, weil bei einem größeren Programmcode der Befehlscache häufiger Fehler aufweist und der Prozessor beim Warten auf neue Befehle ins Stocken gerät.

Architektonische versus physische Register

Maschinensprachenprogramme spezifizieren Lese- und Schreibvorgänge in einem begrenzten Satz von Registern, der durch die Befehlssatzarchitektur (ISA) festgelegt ist. Die Alpha- ISA beispielsweise spezifiziert 32 Integer-Register mit jeweils 64 Bit Breite und 32 Gleitkomma-Register mit jeweils 64 Bit Breite. Dies sind die Architekturregister . Programme für Prozessoren mit dem Alpha-Befehlssatz spezifizieren Operationen zum Lesen und Schreiben dieser 64 Register. Hält ein Programmierer das Programm in einem Debugger an, kann er den Inhalt dieser 64 Register (und einiger Statusregister) beobachten, um den Fortschritt der Maschine zu ermitteln.

Ein bestimmter Prozessor, der diese ISA implementiert, der Alpha 21264 , verfügt über 80 physische Register für Ganzzahlen und 72 Register für Gleitkommazahlen . Auf einem Alpha-21264-Chip gibt es 80 physisch getrennte Speicherplätze, die die Ergebnisse von Ganzzahloperationen speichern können, und 72 Speicherplätze, die die Ergebnisse von Gleitkommaoperationen speichern können. (Tatsächlich gibt es sogar noch mehr Speicherplätze, diese zusätzlichen Speicherplätze sind jedoch für die Registerumbenennung nicht relevant.)

Im Folgenden werden zwei Arten der Registerumbenennung beschrieben, die sich durch die Schaltung unterscheiden, die die Daten für eine Ausführungseinheit bereithält.

Bei allen Umbenennungsverfahren wandelt die Maschine die im Befehlsstrom referenzierten Architekturregister in Tags um. Während die Architekturregister mit 3 bis 5 Bit spezifiziert werden, sind die Tags üblicherweise 6 bis 8 Bit lang. Die Umbenennungsdatei benötigt für jeden Eingang jedes umbenannten Befehls in jedem Zyklus einen Leseport und für jeden Ausgang jedes umbenannten Befehls in jedem Zyklus einen Schreibport. Da die Größe einer Registerdatei im Allgemeinen quadratisch mit der Anzahl der Ports wächst, ist die Umbenennungsdatei üblicherweise physisch groß und verbraucht viel Energie.

Bei der Registerdatei mit Tag-Indexierung existiert eine große Registerdatei für Datenwerte, die für jedes Tag ein eigenes Register enthält. Besitzt die Maschine beispielsweise 80 physische Register, werden 7-Bit-Tags verwendet. 48 der möglichen Tag-Werte bleiben in diesem Fall ungenutzt. Wird in dieser Variante ein Befehl an eine Ausführungseinheit gesendet, werden die Tags der Quellregister an die physische Registerdatei übertragen. Dort werden die entsprechenden Werte gelesen und an die Ausführungseinheit weitergeleitet.

Bei der Reservierungsstationsarchitektur existieren viele kleine assoziative Registerdateien, üblicherweise eine an den Eingängen jeder Ausführungseinheit. Jeder Operand eines Befehls in der Ausgabewarteschlange belegt einen Platz in einer dieser Registerdateien. Wird ein Befehl an eine Ausführungseinheit ausgegeben, werden die entsprechenden Registereinträge gelesen und an die Ausführungseinheit weitergeleitet.

Architekturregisterdatei oder Ruhestandsregisterdatei (RRF)
Der festgeschriebene Registerzustand der Maschine. RAM, indiziert durch logische Registernummern. Wird typischerweise beschrieben, sobald Ergebnisse aus einem Reorder-Puffer abgerufen oder festgeschrieben werden.
Zukunftsdatei
Der spekulativste Registerzustand der Maschine. RAM, indiziert durch logische Registernummern.
Aktive Registerdatei
Die Bezeichnung der Intel P6-Gruppe für Future File.
Verlaufpuffer
Wird typischerweise in Kombination mit einer zukünftigen Datei verwendet. Enthält die „alten“ Werte von Registern, die überschrieben wurden. Solange der Producer noch aktiv ist, kann er über die Nummer des Verlaufspuffers im RAM indiziert werden. Nach einer Fehlvorhersage einer Verzweigung müssen die Ergebnisse aus dem Verlaufspuffer verwendet werden – entweder werden sie kopiert, oder die Suche in der zukünftigen Datei wird deaktiviert und der Verlaufspuffer wird über die logische Registernummer im inhaltsadressierbaren Speicher (CAM) indiziert.
Reorder Buffer (ROB)
Eine Struktur, die für laufende Befehle sequenziell (zirkulärer) pro Operation indiziert wird. Sie unterscheidet sich von einem History Buffer, da der Reorder Buffer typischerweise nach der Future File (sofern vorhanden) und vor der Architekturregisterdatei liegt. Reorder Buffer können datenleer oder datenbehaftet sein. Beispiele: Im ROB von Willamette verweisen die ROB-Einträge auf Register in der physischen Registerdatei (PRF) und enthalten außerdem weitere Verwaltungsdaten. Dies war auch der erste Out-of-Order-Entwurf von Andy Glew an der University of Illinois mit HaRRM. Im ROB von P6 enthalten die ROB-Einträge Daten; es gibt keine separate PRF. Datenwerte aus dem ROB werden beim Verlassen des ROB in die RRF kopiert. Ein kleiner Hinweis: Bei zeitlicher Lokalität der ROB-Einträge (d. h., wenn Befehle in der Von-Neumann-Befehlssequenz zeitlich nahe beieinander liegen und zeitnah zurückgeschrieben werden) kann möglicherweise eine Schreibkombination auf ROB-Einträgen durchgeführt werden, wodurch weniger Ports benötigt werden als bei einem separaten ROB/PRF. Es ist unklar, ob dies einen Unterschied macht, da eine PRF gespeichert werden sollte. ROBs verfügen üblicherweise nicht über assoziative Logik, und keines der von Andy Glew entworfenen ROBs besitzt CAMs. Keith Diefendorff bestand viele Jahre darauf, dass ROBs komplexe assoziative Logik besitzen. Der erste ROB-Vorschlag könnte CAMs enthalten haben.

Tag-indexierte Registerdatei

Dies ist der Umbenennungsstil, der im MIPS R10000 , im Alpha 21264 und im FP-Bereich des AMD Athlon verwendet wird .

In der Umbenennungsphase wird jedes referenzierte Architekturregister (zum Lesen oder Schreiben) in einer architekturindizierten Remap-Datei nachgeschlagen . Diese Datei liefert ein Tag und ein Bereitschaftsbit. Das Tag ist nicht bereit, wenn eine in der Warteschlange befindliche Anweisung, die in dieses Register schreiben soll, noch nicht ausgeführt wurde. Bei Leseoperationen ersetzt dieses Tag das Architekturregister in der Anweisung. Für jeden Registerschreibvorgang wird ein neues Tag aus einem FIFO für freie Tags entnommen und eine neue Zuordnung in die Remap-Datei geschrieben, sodass zukünftige Anweisungen, die das Architekturregister lesen, auf dieses neue Tag verweisen. Das Tag wird als nicht bereit markiert, da die Anweisung noch nicht ausgeführt wurde. Das zuvor für dieses Architekturregister reservierte physische Register wird zusammen mit der Anweisung im Reorder-Puffer gespeichert . Dieser FIFO speichert die Anweisungen in Programmreihenfolge zwischen der Dekodierungs- und der Abschlussphase.

Die Befehle werden anschließend in verschiedene Ausgabewarteschlangen eingereiht . Während der Ausführung eines Befehls werden die Tags seiner Ergebnisse gesendet, und die Ausgabewarteschlangen gleichen diese Tags mit den Tags der noch nicht bereiten Quelloperanden ab. Eine Übereinstimmung bedeutet, dass der Operand bereit ist. Die Remapping-Datei gleicht diese Tags ebenfalls ab, um die entsprechenden physischen Register als bereit zu markieren. Sobald alle Operanden eines Befehls in einer Ausgabewarteschlange bereit sind, kann dieser Befehl ausgeführt werden. Die Ausgabewarteschlangen wählen in jedem Taktzyklus bereite Befehle aus, die an die verschiedenen Funktionseinheiten gesendet werden. Nicht bereite Befehle verbleiben in den Ausgabewarteschlangen. Diese ungeordnete Entfernung von Befehlen aus den Ausgabewarteschlangen kann diese groß und energieintensiv machen.

Ausgegebene Befehle werden aus einer tagindizierten physischen Registerdatei gelesen (wobei gerade gesendete Operanden umgangen werden) und anschließend ausgeführt. Die Ausführungsergebnisse werden in die tagindizierte physische Registerdatei geschrieben und zusätzlich an das Bypass-Netzwerk vor jeder Funktionseinheit gesendet. Bei der Graduierung wird das vorherige Tag des beschriebenen Architekturregisters in die freie Warteschlange gestellt, sodass es für einen neu dekodierten Befehl wiederverwendet werden kann.

Eine Ausnahme oder eine Fehlvorhersage einer Verzweigung führt dazu, dass die Remap-Datei mithilfe von Zustands-Snapshots und dem Durchlaufen der vorherigen Tags in der In-Order-Vorab-Warteschlange auf den Remap-Zustand der letzten gültigen Anweisung zurückgesetzt wird. Da dieser Mechanismus erforderlich ist und jeden Remap-Zustand wiederherstellen kann (nicht nur den Zustand vor der aktuell ausgeführten Anweisung), können Fehlvorhersagen von Verzweigungen behandelt werden, bevor die Verzweigung ausgeführt wird. Dadurch kann die Latenz der Fehlvorhersage potenziell minimiert werden.

Reservierungsstationen

Dies ist der Stil, der im Integer-Teil der AMD K7- und K8-Designs verwendet wird.

In der Umbenennungsphase wird jedes für Lesezugriffe referenzierte Architekturregister sowohl in der architektonisch indizierten Future-Datei als auch in der Umbenennungsdatei nachgeschlagen . Der Lesezugriff auf die Future-Datei liefert den Wert des jeweiligen Registers, sofern noch keine Schreibanweisung vorliegt (d. h., das Register ist bereit). Sobald die Anweisung in die Ausgabewarteschlange gestellt wird, werden die aus der Future-Datei gelesenen Werte in die entsprechenden Einträge der Reservierungsstationen geschrieben. Registerschreibvorgänge innerhalb der Anweisung führen dazu, dass ein neues, noch nicht bereites Tag in die Umbenennungsdatei geschrieben wird. Die Tag-Nummer wird üblicherweise sequenziell in der Reihenfolge der Anweisungen vergeben – ein FIFO für freie Tags ist nicht erforderlich.

Wie beim tagbasierten Verfahren warten die Ausgabewarteschlangen auf übereinstimmende Tag-Broadcasts für nicht bereite Operanden. Im Gegensatz zum tagbasierten Verfahren bewirkt das Übereinstimmen von Tags jedoch, dass der entsprechende Broadcast-Wert in die Reservierungsstation des Ausgabewarteschlangeneintrags geschrieben wird.

Die ausgegebenen Befehle lesen ihre Argumente von der Reservierungsstation, umgehen gerade gesendete Operanden und werden dann ausgeführt. Wie bereits erwähnt, sind die Registerdateien der Reservierungsstation üblicherweise klein und enthalten etwa acht Einträge.

Die Ausführungsergebnisse werden in den Reorder-Puffer , in die Reservierungsstationen (falls der Eintrag in der Ausgabewarteschlange ein passendes Tag hat) und in die Future-Datei geschrieben, wenn dies die letzte Anweisung ist, die auf dieses Architekturregister abzielt (in diesem Fall wird das Register als bereit markiert).

Graduation kopiert den Wert aus dem Reorder-Puffer in die Architekturregisterdatei. Die Architekturregisterdatei dient ausschließlich der Fehlerbehebung bei Ausnahmen und Fehlvorhersagen von Verzweigungen.

Ausnahmen und Fehlvorhersagen von Verzweigungen, die beim Abschluss erkannt werden, führen dazu, dass die Architekturdatei in die zukünftige Datei kopiert und alle Register in der Umbenennungsdatei als bereit markiert werden. Normalerweise lässt sich der Zustand der zukünftigen Datei für eine zwischen Dekodierung und Abschluss ausgeführte Anweisung nicht rekonstruieren, sodass eine frühzeitige Korrektur von Fehlvorhersagen von Verzweigungen üblicherweise nicht möglich ist.

Vergleich der Systeme

In beiden Systemen werden Befehle der Reihe nach in die Ausgabewarteschlangen eingefügt, aber in beliebiger Reihenfolge entfernt. Wenn die Warteschlangen leere Plätze nicht schließen, enthalten sie entweder viele ungenutzte Einträge oder erfordern eine variable Prioritätskodierung für den Fall, dass mehrere Befehle gleichzeitig zur Ausführung bereitstehen. Warteschlangen, die Lücken schließen, haben eine einfachere Prioritätskodierung, benötigen aber eine einfache, aber große Schaltung, um die Befehle durch die Warteschlange zu bewegen.

Reservierungsstationen weisen eine geringere Latenz zwischen Umbenennung und Ausführung auf, da die Umbenennungsphase die Registerwerte direkt ermittelt, anstatt die physische Registernummer zu finden und anschließend den Wert zu bestimmen. Diese Latenz wirkt sich als Bestandteil der Latenz bei Fehlvorhersagen von Verzweigungen aus.

Reservierungsstationen weisen zudem eine geringere Latenz zwischen Befehlsausgabe und -ausführung auf, da jede lokale Registerdatei kleiner ist als die große zentrale Datei des tagindizierten Schemas. Auch die Tag-Generierung und die Ausnahmebehandlung sind im Reservierungsstationsschema einfacher, wie nachfolgend erläutert wird.

Die von Reservierungsstationen verwendeten physischen Registerdateien fassen üblicherweise ungenutzte Einträge parallel zur Ausgabewarteschlange zusammen. Dadurch sind diese Registerdateien insgesamt größer, verbrauchen mehr Energie und sind komplexer als die einfacheren Registerdateien eines tagbasierten Systems. Erschwerend kommt hinzu, dass jeder Eintrag in jeder Reservierungsstation von jedem Ergebnisbus beschrieben werden kann. So benötigt eine Reservierungsstation mit beispielsweise acht Ausgabewarteschlangeneinträgen pro Funktionseinheit typischerweise neunmal so viele Bypass-Netzwerke wie eine vergleichbare tagbasierte Maschine. Folglich verbraucht die Ergebnisweiterleitung deutlich mehr Energie und Fläche als in einem tagbasierten System.

Darüber hinaus verfügt das Reservierungsstationsschema über vier Speicherorte (Zukunftsdatei, Reservierungsstation, Reorder-Puffer und Architekturdatei), an denen ein Ergebniswert gespeichert werden kann, während das tagbasierte Schema nur einen Speicherort (die physische Registerdatei) besitzt. Da die Ergebnisse der Funktionseinheiten, die an all diese Speicherorte gesendet werden, eine wesentlich größere Anzahl von Speicherorten im System erreichen müssen als beim tagbasierten Schema, benötigt diese Funktion mehr Energie, Fläche und Zeit. Dennoch können Reservierungsstationen auf Systemen mit sehr präzisen Sprungvorhersageverfahren und bei kritischen Ausführungslatenzen bemerkenswert gut funktionieren.

Geschichte

Das IBM System/360 Modell 91 war eine der ersten Maschinen, die die Ausführung von Befehlen in beliebiger Reihenfolge unterstützte; sie verwendete den Tomasulo-Algorithmus , der Registerumbenennung nutzt.

Der POWER1 aus dem Jahr 1990 war der erste Mikroprozessor , der Registerumbenennung und Out-of-Order-Ausführung nutzte. Dieser Prozessor implementierte die Registerumbenennung ausschließlich für Gleitkomma-Ladeoperationen. Da der POWER1 nur eine Gleitkommaeinheit (FPU) besaß, war die Umbenennung für andere Gleitkomma-Befehle als Speicheroperationen unnötig. Der POWER2 hingegen verfügte über mehrere FPUs, sodass die Registerumbenennung für alle Gleitkomma-Befehle verwendet wurde. [ 1 ]

Das ursprüngliche Design des R10000 verfügte weder über zusammenfallende Ausgabewarteschlangen noch über eine variable Prioritätskodierung und litt daher unter Befehlsengpässen – der älteste Befehl in der Warteschlange wurde mitunter erst ausgeführt, nachdem die Befehlsdekodierung aufgrund fehlender Umbenennungsregister vollständig stoppte und alle anderen Befehle ausgeführt worden waren. Spätere Überarbeitungen des Designs, beginnend mit dem R12000, verwendeten einen teilweise variablen Prioritätskodierer, um dieses Problem zu beheben.

Frühe Out-of-Order-Systeme trennten die Umbenennungs- und ROB/PRF-Speicherfunktionen nicht. Einige der frühesten Systeme, wie beispielsweise Sohis RUU oder Metaflow DCAF, kombinierten sogar Scheduling, Umbenennung und Speicherung in derselben Struktur.

Die meisten modernen Rechner führen Umbenennungen durch, indem sie eine Zuordnungstabelle im RAM mit der logischen Registernummer indizieren. Beispielsweise tat dies der P6; zukünftige Dateisysteme verwenden dasselbe und speichern Daten in derselben Struktur.

Frühere Maschinen verwendeten jedoch inhaltsadressierbaren Speicher (CAM) im Umbenennungsprozess. Beispielsweise nutzte die HPSM RAT (Register Alias ​​Table) im Wesentlichen einen CAM auf der logischen Registernummer in Kombination mit verschiedenen Versionen des Registers.

Die Geschichte der ungeordneten Mikroarchitektur verdeutlicht in vielerlei Hinsicht, wie diese CAMs schrittweise eliminiert wurden. Kleine CAMs sind nützlich, große hingegen unpraktisch.

Die P6-Mikroarchitektur war die erste Mikroarchitektur von Intel, die sowohl Out-of-Order-Ausführung als auch Registerumbenennung implementierte. Sie kam in den Mikroprozessoren Pentium Pro, Pentium II, Pentium III, Pentium M, Core und Core 2 zum Einsatz. Der am 2. Oktober 1995 erschienene Cyrix M1 [ 2 ] war der erste x86-Prozessor, der Registerumbenennung und Out-of-Order-Ausführung nutzte. Weitere 1996 veröffentlichte x86-Prozessoren (wie der NexGen Nx686 und der AMD K5 ) boten ebenfalls Registerumbenennung und Out-of-Order-Ausführung von RISC -μ-Operationen (anstelle nativer x86-Befehle). [ 3 ] [ 4 ]

Referenzen

  1. ^ Simu, D. (September–Oktober 2000). „Der Gestaltungsspielraum von Registerumbenennungstechniken“ (PDF) . IEEE Micro . 20 (5). IEEE: 70–83 . doi : 10.1109/40.877952 .
  2. ^ „Cyrix 6x86 Prozessor“ . Archiviert vom Original am 09.01.2023.
  3. ^ „NexGen stellt die Prozessortechnologie der sechsten Generation, den Nx686, vor“ (Pressemitteilung).
  4. ^ „100 MHz und darüber hinaus“ . PC Magazine . 13 (21). Ziff Davis: 172. 06.12.1994. ISSN 0888-8507 .