Ich habe mich immer gefragt, warum Prozessoren bei 32 Registern stehen blieben. Es ist mit Abstand das schnellste Teil der Maschine. Warum nicht einfach größere Prozessoren mit mehr Registern herstellen? Würde das nicht bedeuten, weniger ins RAM zu gehen?
computer-architecture
Matt Capone
quelle
quelle
Antworten:
Erstens wurden nicht alle Prozessorarchitekturen bei 32 Registern gestoppt. Fast alle RISC-Architekturen, bei denen 32 Register im Befehlssatz verfügbar sind, haben tatsächlich 32 Ganzzahlregister und 32 weitere Gleitkommaregister (also 64). (Gleitkommazahl "add" verwendet andere Register als Ganzzahl "add".) Die SPARC-Architektur verfügt über Registerfenster. Auf dem SPARC können Sie nur auf 32 Integer-Register gleichzeitig zugreifen, aber die Register verhalten sich wie ein Stapel und Sie können jeweils 16 neue Register pushen und einfügen. Die Itanium-Architektur von HP / Intel enthielt 128 Ganzzahl- und 128 Gleitkommaregister im Befehlssatz. Moderne GPUs von NVidia, AMD, Intel, ARM und Imagination Technologies stellen eine enorme Anzahl von Registern in ihren Registerdateien zur Verfügung. (Ich weiß, dass dies auf die NVidia- und Intel-Architektur zutrifft. Ich bin nicht sehr vertraut mit den Befehlssätzen AMD, ARM und Imagination, aber ich denke, dass die Registerdateien dort auch groß sind.)
Zweitens implementieren die meisten modernen Mikroprozessoren eine Registerumbenennung , um unnötige Serialisierung zu vermeiden, die durch die Notwendigkeit der Wiederverwendung von Ressourcen verursacht wird. Daher können die zugrunde liegenden physischen Registerdateien größer sein (96, 128 oder 192 Register auf einigen Computern) Es ist erforderlich, dass der Compiler so viele eindeutige Registernamen generiert und dem Scheduler dennoch eine größere Registerdatei zur Verfügung stellt.
Es gibt zwei Gründe, warum es schwierig sein kann, die Anzahl der im Befehlssatz enthaltenen Register weiter zu erhöhen. Zunächst müssen Sie in der Lage sein, die Registerkennungen in jeder Anweisung anzugeben. Bei 32 Registern ist ein 5-Bit-Registerspezifizierer erforderlich, sodass Befehle mit 3 Adressen (wie sie bei RISC-Architekturen üblich sind) 15 der 32 Befehlsbits ausgeben, um nur die Register zu spezifizieren. Wenn Sie diesen Wert auf 6 oder 7 Bit erhöhen, haben Sie weniger Platz, um Opcodes und Konstanten anzugeben. GPUs und Itanium haben viel größere Anweisungen. Größere Anweisungen sind mit Kosten verbunden: Sie müssen mehr Anweisungsspeicher verwenden, damit das Verhalten des Anweisungscaches weniger ideal ist.
Der zweite Grund ist die Zugriffszeit. Je größer Sie einen Speicher machen, desto langsamer ist es, auf Daten von ihm zuzugreifen. (Nur in Bezug auf die Grundphysik: Die Daten werden im zweidimensionalen Raum gespeichert. Wenn Sie also Bits speichern , beträgt der durchschnittliche Abstand zu einem bestimmten Bit .) Eine Registerdatei ist nur eine kleiner Speicher mit mehreren Ports und eine der Einschränkungen beim Vergrößern besteht darin, dass Sie möglicherweise langsamer mit dem Takten Ihres Computers beginnen müssen, um die größere Registerdatei aufzunehmen. Normalerweise ist dies in Bezug auf die Gesamtleistung ein Verlust. O ( √n O(n−−√)
quelle
Nur zwei weitere Gründe, um die Anzahl der Register zu begrenzen:
quelle
Viele Codes verfügen über viele Speicherzugriffe (30% sind eine typische Zahl). Davon sind typischerweise etwa 2/3 Lesezugriffe und 1/3 Schreibzugriffe. Dies liegt nicht daran, dass die Register nicht mehr ausreichen, sondern dass auf Arrays, Objekt-Member-Variablen usw. zugegriffen wird.
Dies muss im Arbeitsspeicher (oder Datencache) erfolgen, da C / C ++ erstellt wird (alles, was Sie für einen Zeiger erhalten können, muss eine Adresse haben, die möglicherweise im Arbeitsspeicher gespeichert werden muss). Wenn der Compiler erraten kann, dass Sie mit verrückten indirekten Zeigertricks nicht willkürlich in Variablen schreiben, werden sie in Registern abgelegt, und dies funktioniert gut für Funktionsvariablen, aber nicht für global zugängliche (im Allgemeinen alles, was aus malloc herauskommt ()) weil es im Grunde unmöglich ist zu erraten, wie sich der globale Zustand ändern wird.
Aus diesem Grund ist es nicht üblich, dass der Compiler mit mehr als 16 allgemeinen Verwendungsregistern überhaupt etwas anfangen kann. Deshalb gibt es in allen gängigen Architekturen ungefähr so viele (ARM hat 16).
MIPS und andere RISCs haben in der Regel 32, weil es nicht sehr schwer ist, so viele Register zu haben - die Kosten sind niedrig genug, so dass es ein bisschen wie ein "Warum nicht?" Ist. Mehr als 32 sind meistens unbrauchbar und haben den Nachteil, dass der Zugriff auf die Registerdatei länger dauert (jede Verdoppelung der Anzahl der Register fügt möglicherweise eine zusätzliche Multiplexerschicht hinzu, die etwas mehr Verzögerung hinzufügt ...). Außerdem werden die Anweisungen im Durchschnitt etwas länger. Wenn Sie also Programme ausführen, die von der Bandbreite des Befehlsspeichers abhängen, verlangsamen Ihre zusätzlichen Register Sie tatsächlich!
Wenn Ihre CPU in Ordnung ist und keine Registerumbenennung durchführt und Sie versuchen, viele Operationen pro Zyklus auszuführen (mehr als 3), benötigen Sie theoretisch mehr Register, wenn die Anzahl der Operationen pro Zyklus steigt. Deshalb hat der Itanium so viele Register! Aber in der Praxis wird der meiste Code, abgesehen von numerischem Gleitkomma oder SIMD-orientiertem Code (in dem Itanium wirklich gut war), viele Speicher-Lese- / Schreibvorgänge und -Sprünge aufweisen, die diesen Traum von mehr als 3 Operationen pro Zyklus unmöglich machen (insbesondere in serverorientierter Software wie Datenbanken, Compilern, Hochsprachenausführung wie Javascript, Emulation usw.). Dies ist, was Itanium versenkte.
Auf den Unterschied zwischen Berechnung und Ausführung kommt es an!
quelle
Wer sagt Ihnen, dass der Prozessor immer 32 Register hat? x86 hat 8, ARM 32-Bit und x86_64 hat 16, IA-64 hat 128 und viele weitere Nummern. Sie können einen Blick hier . Selbst bei MIPS, PPC oder Architekturen mit 32 Allzweckregistern im Befehlssatz ist die Anzahl viel größer als 32, da es immer noch Flag-Register (falls vorhanden), Steuerregister ... ohne umbenannte Register und Hardwareregister gibt
Alles hat seinen Preis. Je größer die Anzahl der Register ist, desto mehr Arbeit haben Sie beim Taskwechsel, desto mehr Platz benötigen Sie in der Befehlskodierung. Wenn Sie weniger Register haben, müssen Sie nicht viel speichern und wiederherstellen, wenn Sie Funktionen aufrufen und von Funktionen zurückkehren oder Aufgaben wechseln, ohne dass das Fehlen von Registern in einem rechenintensiven Code in Frage kommt
Außerdem ist es umso teurer und komplexer, je größer die Registerdatei ist. SRAM ist der schnellste und teuerste Arbeitsspeicher und wird daher nur im CPU-Cache verwendet. Aber es ist immer noch viel billiger und nimmt weniger Fläche ein als eine Registerdatei mit der gleichen Kapazität.
quelle
Beispielsweise hat ein typischer Intel-Prozessor "offiziell" 16 Ganzzahl- und 16 Vektorregister. In Wirklichkeit gibt es aber noch viel mehr: Der Prozessor verwendet die "Registerumbenennung". Wenn Sie eine Anweisung reg3 = reg1 + reg2 haben, hätten Sie ein Problem, wenn eine andere Anweisung, die reg3 verwendet, noch nicht beendet wurde - Sie könnten die neue Anweisung nicht ausführen, falls sie reg3 überschreibt, bevor sie von der vorherigen Anweisung gelesen wurde.
Daher gibt es ungefähr 160 echte Register. Die einfache Anweisung oben wird also in "regX = reg1 + reg2" geändert, und denken Sie daran, dass regX reg3 enthält. Ohne Umbenennungsregister wäre die Ausführung in der falschen Reihenfolge im Wasser absolut tot.
quelle
Ich bin kein Elektrotechniker, aber ich denke, eine andere Möglichkeit, die Anzahl der Register zu begrenzen, ist das Routing. Es gibt eine begrenzte Anzahl von Recheneinheiten, und sie müssen in der Lage sein, Eingaben aus jedem Register zu übernehmen und in jedes Register auszugeben. Dies gilt insbesondere dann, wenn Sie über Pipeline-Programme verfügen, die viele Anweisungen pro Zyklus ausführen können.
Eine einfache Version davon hätte eine Komplexität von , was eine Erhöhung der Anzahl von Registern unskalierbar macht oder auf andere Weise eine Neugestaltung des Routings auf etwas viel komplizierteres erfordert, um alles mit einer besseren Komplexität zu routen.O(n2)
Die Idee zu dieser Antwort kam mir, als ich einige von Ivan Godards Vorträgen über die Mill-CPU sah. Ein Teil der Innovation der Mill-CPU besteht darin, dass Sie nicht in beliebige Register ausgeben können - die Ausgänge werden alle auf einen Registerstapel oder ein "Band" verschoben, wodurch Routing-Probleme reduziert werden, da Sie immer wissen, wohin die Ausgabe gehen wird. Beachten Sie, dass sie immer noch das Routing-Problem haben, die Eingangsregister zu den Recheneinheiten zu bringen.
Informationen zur Problemstellung und zur Lösung von Mill finden Sie unter Die Mill-CPU-Architektur - der Gürtel (2 von 9) .
quelle
Für die MIPS ISA, Hennessy und Patterson, Computer Organization und Design, 4. Auflage, S. 176, beantwortet diese spezielle Frage direkt:
quelle