Zitat:
Zitat von spartan-b292
Das Müsste dann iin der Pipeline irgendwie so aussehen:
Takt......... : 1 , 2 , 3 , 4, 5, 6, 7, 8 (ergänzung von mir)
Befehl n....: IF, ID, EX, DM, WB
Befehl n+1: ##,IF, ID, EX, ##,##
Befehl n+2: ##,##,IF, ID, EX, DM,WB
Befehl n+3: ##,##,##,IF, ID, EX, ##, WB
|
So hätte ich das auch gemacht
Als kleine Ergänzung noch dazu. Jeder Befehl besteht aus mehreren Operationen wie zum beispiel dem decodieren des Befehls, das laden der Operatoren usw..
Ohne Pipelining würde immer nur ein Befehl alle seine Operationen ausführen bis er fertig ist. Das ist aber (offensichtlich) sehr langsam, wesswegen die Befehle die Operationen parallel durchlaufen.
Zum Beispiel kann gleichzeitig ein Operator von Befehl 2 geladen werden, während Befehl 3 decodiert wird und Befehl 1 die ALU beansprucht.
Das ganze bringt ungefähr einen Geschwindigkeitsvorteil in Abhängigkeit von der Anzahl der Pipelinestuffen (Bei einer vierstufigen Pipeline (Decode, Fetch, Execute, Store) hättest du also den Faktor x4).
Probleme: Da die CPU nicht in die Zukunft gucken kann, muss ein Compiler/Entwickler darauf achten, dass die Befehle sich nicht behindern. Es kann nämlich passieren, dass Befehle die voneinander abhängen falsch bearbeitet werden (Pipeline-Hazard).
Beispiel: Du addierst etwas in einem register und verwendest den erzeugten Wert im nächsten Befehlsaufruf (Data-Hazard). Nun kann es sein, dass dein zweiter Befehl den alten Wert geladen hat bevor der erste Befehl den Wert in das register zurückgeschrieben hat (aufgrund der Pipeline-Schritte). Abhilfe schaffen hier sogenannte NOP-Befehle (No Operation), die nichts machen (bzw. keine Auswirkung haben). Diese werden regulär in die Pipeline gepackt und abgearbeitet und schaffen Zeit. Anstatt NOP-Befehle kann man die bestehdenen Befehle (sofern möglich) neu anordnen, so dass diese richtig in der Pipeline landen (ist für die Performance besser!). Alternativ gibt es auch die Möglichkeit ein berechneten Wert an den nächsten Befehl weiterzugeben (forwarding) wofür aber extra Hardware benötigt wird.
Neben den Data-Hazards gibt es das gleiche noch für Sprünge (Control-Hazards) wenn du z.B. bei einem bne-Befehl vorher abhängigkeiten hast (du willst bei 0 Springen aber in der Pipeline wurde der Befehl noch nicht zurückgeschrieben und es wird ein falscher Wert geladen und verglichen). Auch hier kann man mit NOPs arbeiten oder aber man benutzt die Branch-Prediction in dem man den Sprung "vorhersagt" (über Analyse/Anmerkungen), z.B. ist es wahrscheinlicher in einer Schleife diese zu wiederholen so das ein Sprung innerhalb der Schleife wahrscheinlicher ist als ein Sprung aus der Schleife raus. Sollte man sich geirrt haben wird die Pipeline geleert und zurückgesetzt.