Wie funktioniert die Branchenvorhersage, wenn Sie noch nach den Bedingungen suchen müssen?


30

Ich habe die beliebte Antwort zu Branch Prediction von https://stackoverflow.com/q/11227809/555690 gelesen und etwas verwirrt mich:

  • Wenn Sie richtig geraten haben, geht es weiter.
  • Wenn Sie falsch geraten haben, stoppt der Kapitän, macht einen Rückzieher und schreit Sie an, den Schalter zu betätigen. Dann kann es den anderen Pfad neu starten.

Wenn Sie jedes Mal richtig raten, wird der Zug niemals anhalten müssen.

Wenn Sie zu oft falsch raten, verbringt der Zug viel Zeit damit, anzuhalten, zu sichern und neu zu starten.

Aber das ist, was ich nicht verstehe: Um zu wissen, ob Ihre Vermutung richtig oder falsch war, müssen Sie trotzdem eine Zustandsüberprüfung durchführen . Wie funktioniert die Verzweigungsvorhersage überhaupt, wenn Sie in beiden Fällen immer noch dieselbe bedingte Prüfung durchführen?

Was ich damit sagen will, ist, ist die Verzweigungsvorhersage nicht genau das Gleiche wie die Verzweigungsvorhersage, weil Sie sowieso die gleichen bedingten Prüfungen durchführen? (offensichtlich irre ich mich, aber ich verstehe es nicht)


1
Dieser Wiki- Artikel erklärt das ziemlich gut.
Enderland

8
Eine moderne CPU ist ein Pipeline-Prozessor und kann mehrere Aufgaben gleichzeitig ausführen. So kann es beginnen, seine Vermutung auszuführen, während es noch herausfindet, ob es richtig geraten hat. Wenn die Vermutung richtig war, läuft die Pipeline weiter. Bei einer falschen Vermutung wird die Pipeline verworfen und die Ausführung wird ab dem Punkt "Richtige Antwort" neu gestartet.
markspace

2
Verwandte Lesung: Pipeline . Ich würde auch empfehlen, die akzeptierte Antwort auf diese SO-Frage erneut zu lesen, da sie Ihre Frage hier beantwortet.

Antworten:


19

Natürlich wird der Zustand jedes Mal überprüft. Aber bis es überprüft wird, ist es weit oben in der CPU-Pipeline. In der Zwischenzeit sind weitere Anweisungen in die Pipeline eingegangen und befinden sich in verschiedenen Phasen der Ausführung.

Normalerweise folgt unmittelbar auf eine Bedingung eine bedingte Verzweigungsanweisung, die entweder verzweigt, wenn die Bedingung WAHR ergibt, oder durchfällt, wenn die Bedingung FALSCH ergibt. Dies bedeutet, dass nach dem Bedingungsbefehl und dem Verzweigungsbefehl zwei verschiedene Befehlsströme in die Pipeline geladen werden können, je nachdem, ob die Bedingung TRUE oder FALSE ergibt. Unglücklicherweise weiß die CPU unmittelbar nach dem Laden der Bedingungsanweisung und der Verzweigungsanweisung noch nicht, wie die Bedingung ausgewertet wird, muss jedoch weiterhin Daten in die Pipeline laden. Es wird also eine der beiden Anweisungen ausgewählt, basierend auf einer Vermutung, wie die Bedingung ausgewertet wird.

Später, wenn der Bedingungsbefehl die Pipeline hinaufläuft, ist es an der Zeit, ihn auszuwerten. Zu diesem Zeitpunkt findet die CPU heraus, ob ihre Vermutung richtig oder falsch war.

Wenn sich herausstellt, dass die Vermutung richtig ist, wurde der Zweig an die richtige Stelle verschoben, und die richtigen Anweisungen wurden in die Pipeline geladen. Wenn sich herausstellt, dass die Vermutung falsch war, dann müssen alle Befehle, die nach dem bedingten Verzweigungsbefehl in die Pipeline geladen wurden, verworfen werden, und das Abrufen von Befehlen muss erneut an der richtigen Stelle beginnen.

Änderung

Als Antwort auf den Kommentar von StarWeaver, um eine Vorstellung davon zu bekommen, was die CPU tun muss, um einen einzelnen Befehl auszuführen:

Betrachten Sie etwas so Einfaches, wie MOV AX,[SI+10]wir Menschen es naiv als "AX mit dem Wort bei SI plus 10 laden" betrachten. Grob gesagt muss die CPU:

  1. den Inhalt des PCs (das "Programmzählerregister") an den Adressbus senden;
  2. Lesen des Befehls-Opcodes vom Datenbus;
  3. Inkrement PC;
  4. Dekodiere den Opcode, um herauszufinden, was damit zu tun ist.
  5. den Inhalt des PCs an den Adressbus senden;
  6. Lese den Befehlsoperanden (in diesem Fall 10) vom Datenbus;
  7. Inkrement PC;
  8. führe den Operanden und SI dem Addierer zu;
  9. das Ergebnis des Addierers an den Adressbus ausgeben;
  10. Lesen Sie AX aus dem Datenbus.

Das sind satte 10 Schritte. Einige dieser Schritte werden auch bei nicht über Pipelines verbundenen CPUs wegoptimiert, zum Beispiel erhöht die CPU den PC fast immer parallel zum nächsten Schritt, was eine einfache Sache ist, da der PC ein sehr, sehr spezielles Register ist Nie für einen anderen Job verwendet, daher besteht zwischen verschiedenen Teilen der CPU keine Möglichkeit eines Konflikts um den Zugriff auf dieses bestimmte Register. Dennoch bleiben uns 8 Schritte für eine so einfache Anweisung, und ich nehme an, dass ich bereits ein gewisses Maß an Raffinesse für die CPU voraussetze, zum Beispiel gehe ich davon aus, dass für die keine zusätzlichen Schritte erforderlich sind Addierer, um die Addition tatsächlich durchzuführen, bevor das Ergebnis daraus abgelesen werden kann,

Bedenken Sie nun, dass es kompliziertere Adressierungsmodi wie MOV AX, [DX+SI*4+10]und sogar weitaus kompliziertere Befehle gibt, MUL AX, operanddie tatsächlich Schleifen in der CPU ausführen, um deren Ergebnis zu berechnen.

Mein Punkt hier ist also, dass die Metapher "atomarer Ebene" bei weitem nicht für die CPU-Befehlsebene geeignet ist. Es ist möglicherweise für die Pipeline-Step-Ebene geeignet, wenn Sie nicht zu weit auf die eigentliche Logik-Gate-Ebene heruntergehen möchten.


2
Huh, ich frage mich, ob ein Teil des Problems, das Menschen (einschließlich mir) damit zu tun haben, darin besteht, dass es (auf jeden Fall für mich) sehr schwierig ist, sich vorzustellen, dass eine CPU nur teilweise Kenntnisse über eine einzelne Anweisung hat. oder ein paar halbfertige Anweisungen "durch den Pizzabandofen gehen" zu haben ... zumindest fühlt es sich für mich wie eine Verschiebung der Skala zu atomar an, wenn ich es gewohnt bin, mit Dingen zwischen Montageset und Metalldrehmaschinenebene zu arbeiten.
StarWeaver

1
@StarWeaver Ihr Kommentar hat mir gefallen, daher habe ich meine Antwort geändert, um ihn zu adressieren.
Mike Nakis

1
Wow, schöne Erklärung. Ich neige dazu zu vergessen, wie viel in das Bewegen von Wörtern an nützlichere Orte fließt. Ich visualisiere eine CPU immer noch als einen Satz riemengetriebener Pizzaöfen: 3.
StarWeaver

Es ist zu bedenken, dass die vom OP verknüpfte Stapelüberlauf-Frage - die mit 1,3 Millionen Views, die wahrscheinlich über 1 Million Programmierer auf die bisher unbekannte Tatsache aufmerksam gemacht haben, dass "Branch Prediction" überhaupt existiert - ein Beispiel in Java darstellt . Für Leute wie mich, die es gewohnt sind, auf der Ebene der Abstraktion zu arbeiten, die Sprachen wie Java uns bieten, ist es sogar MOV AX,[SI+10]fremd, nicht "einfach". Die meisten Programmierer haben heute noch nie Assembler geschrieben. Wir denken nicht "naiv" daran, dass es irgendetwas bedeutet.
Mark Amery

@MarkAmery gut, okay, ich dachte, es ist ziemlich offensichtlich, dass mit "wir Menschen" meine ich "wir Menschen, die es wagen, Versammlung zu schreiben". Der Punkt ist, dass selbst Assembler-Programmierer nicht immer oder überhaupt an die Pipeline denken.
Mike Nakis

28

Stellen Sie es sich wie einen Ausflug ohne GPS vor. Sie kommen zu einer Kreuzung und denken, Sie müssen abbiegen, sind sich aber nicht ganz sicher. Sie biegen also ab, bitten aber Ihren Beifahrer, die Karte zu überprüfen. Vielleicht sind Sie drei Meilen die Straße hinunter, wenn Sie fertig sind mit Streiten darüber, wo Sie sind. Wenn Sie recht gehabt hätten, wären Sie drei Meilen weiter als wenn Sie angehalten und gestritten hätten, bevor Sie umgedreht wären. Wenn Sie sich geirrt haben, müssen Sie sich umdrehen.

CPU-Pipelines funktionieren genauso. Bis sie den Zustand überprüfen können, sind sie schon ein Stück weiter. Der Unterschied ist, dass sie die drei Meilen nicht zurück fahren müssen, sondern nur den Vorsprung verlieren. Das heißt, es schadet nicht, es zu versuchen.


2
Diese Erklärung ist ordentlich.
Sharptooth

2

Nach meinem Verständnis ist die Verzweigungsvorhersage am nützlichsten, wenn die zu überprüfende Bedingung das Ergebnis von etwas erfordert, das teuer ist oder noch in Bearbeitung ist, und Sie andernfalls Ihre Daumen drehen und auf den Wert warten, um die Bedingung zu bewerten.

Bei der Ausführung außerhalb der Reihenfolge können Sie die Verzweigungsvorhersage verwenden, um leere Stellen in der Pipeline auszufüllen, die die CPU sonst nicht verwenden könnte. In einer Situation, in der aus irgendeinem Grund keine Leerlaufzyklen in der Pipeline vorhanden sind, gibt es keine Verbesserung der Verzweigungsvorhersage.

Der Schlüssel hierbei ist jedoch, dass die CPU die Arbeit für einen der vorhergesagten Zweige startet, da sie den Zustand selbst noch nicht auswerten kann.


1

Kurzform:

Einige CPUs können mit der Bearbeitung eines neuen Befehls beginnen, bevor der alte abgeschlossen ist. Dies sind die CPUs, die die Verzweigungsvorhersage verwenden.

Ein Pseudocode-Beispiel:

int globalVariable;
int Read(int* readThis, int* readThat)
{
    if ((globalVariable*globalVariable % 17) < 5)
       return *readThis;
    else
       return *readThat;
}

Der obige Code prüft eine Bedingung und basierend auf dem Ergebnis muss er entweder den am Speicherort addThisgespeicherten Wert oder den am Speicherort gespeicherten Wert zurückgeben readThat. Wenn die Verzweigungsvorhersage den Zustand vorhersagt true, liest die CPU bereits den an der Speicherstelle gespeicherten Wert, addThiswährend sie die zur Auswertung der ifAnweisung erforderliche Berechnung vornimmt. Dies ist ein vereinfachtes Beispiel.


1

Ja, der Zustand wird so oder so geprüft. Der Vorteil der Verzweigungsvorhersage besteht jedoch darin, dass Sie arbeiten können, anstatt auf das Ergebnis der Bedingungsprüfung zu warten.

Nehmen wir an, Sie müssen einen Aufsatz schreiben und es kann sich um Thema A oder Thema B handeln. Sie wissen aus früheren Aufsätzen, dass Ihr Lehrer Thema A besser mag als B und wählt es häufiger aus. Anstatt auf seine Entscheidung zu warten, können Sie den Aufsatz über das erste Thema schreiben. Nun gibt es zwei mögliche Ergebnisse:

  1. Sie haben Ihren Aufsatz zum falschen Thema begonnen und müssen das, was Sie bisher geschrieben haben, fallen lassen. Sie müssen anfangen, über das andere Thema zu schreiben, und es ist derselbe Zeitaufwand, als hätten Sie gewartet.
  2. Sie haben richtig geraten und bereits gearbeitet.

Moderne CPUs laufen die meiste Zeit im Leerlauf, weil sie auf E / A-Antworten oder das Ergebnis anderer Berechnungen warten. Diese Zeit kann für zukünftige Arbeiten genutzt werden.

Selbst wenn Sie das, was Sie in dieser Leerlaufzeit tun, verwerfen müssen, ist es am effektivsten, wenn Sie den vom Programm gewählten Pfad erraten können. Und moderne CPUs haben diese Fähigkeit.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.