Pipelining (auch Instruktions-Pipelining) ist das Fließband-Prinzip der CPU: Die Ausführung eines Maschinenbefehls wird in mehrere Stufen zerlegt, und während ein Befehl noch in einer Stufe steckt, arbeitet die nächste Stufe bereits am nächsten Befehl. Dadurch steigt der Durchsatz der CPU deutlich, ohne die Latenz eines einzelnen Befehls zu verkürzen.
Die klassische Fünf-Stufen-Pipeline
Die Lehrbuch-Pipeline stammt aus der RISC-Ära (MIPS, Patterson/Hennessy) und teilt jeden Befehl in fünf Stufen:
- IF (Instruction Fetch): Befehl aus dem Speicher holen.
- ID (Instruction Decode): Befehl dekodieren, Register lesen.
- EX (Execute): ALU-Operation ausführen.
- MEM (Memory Access): Speicherzugriff bei Load/Store.
- WB (Write Back): Ergebnis ins Ziel-Register schreiben.
Bei vollständiger Überlappung beendet die Pipeline pro Takt einen Befehl (CPI = 1), obwohl ein einzelner Befehl fünf Takte braucht. Der theoretische Speedup entspricht der Stufenzahl; praktisch sinkt er durch Hazards sowie Auf- und Abbau der Pipeline.
Gefahren: Hazards
Hazards verhindern die ideale Überlappung. Man unterscheidet drei Klassen:
- Daten-Hazards: Ein Befehl braucht das Ergebnis des Vorgängers, das noch nicht geschrieben ist (RAW). Gegenmittel: Forwarding/Bypassing leitet das Ergebnis direkt von der EX-Stufe weiter; sonst Stall (Pipeline-Bubble). Der Compiler kann Befehle umsortieren (Instruction Scheduling), ein typischer Job der Codegenerierung.
- Kontroll-Hazards: Bei Sprüngen weiß die Pipeline nicht, welcher Befehl als Nächstes kommt. Gegenmittel: Branch Prediction (statisch oder dynamisch mit History-Tabellen) und das Leeren der Pipeline bei fehlerhafter Vorhersage — jeder falsch vorhergesagte Sprung kostet so viele Takte, wie die Pipeline Stufen hat.
- Strukturelle Hazards: Zwei Stufen brauchen dieselbe Ressource, etwa einen gemeinsamen Speicher für IF und MEM. Klassische Lösung ist die Harvard-artige Trennung von Befehls- und Datencache auf L1-Ebene (Cache-Speicher).
Weiterentwicklungen
Superskalare Prozessoren betreiben mehrere Pipelines parallel und beenden mehrere Befehle pro Takt. Out-of-Order-Ausführung lässt nachfolgende Befehle bei Hazards weiterlaufen und ordnet die Ergebnisse am Ende (Reorder Buffer) wieder in die Programmlogik ein — dazu braucht die CPU die Umbenennung auf physische Register (siehe Register-Bank). Wie all diese Mechanismen konkret gebaut sind, beschreibt die Mikroarchitektur.
RISC und CISC
Die Pipeline-Tiefe hängt stark vom Instruktionssatz ab: RISC-Befehle sind regelmäßig und gleich lang, dadurch lassen sich Pipelines einfach und tief bauen. CISC-Prozessoren (x86) zerlegen komplexe Befehle in Mikrooperationen, die dann auf einer RISC-artigen Pipeline laufen — der Opcode eines x86-Befehls bestimmt dabei, in welche Mikrooperationen er aufgeteilt wird.
Vom Maschinensprache-Standpunkt ist Pipelining für die Software transparent: Die CPU führt dieselben Bytes aus, nur eben überlappend. Erst bei der Leistungsoptimierung muss der Compiler die Pipeline-Tiefe und Sprungvorhersage der Ziel-Mikroarchitektur kennen.
Abgrenzung: Eine Pipeline im Software-Sinn (Datenfluss, CI/CD, Unix-Pipes) ist ein anderes Konzept — dieser Artikel behandelt ausschließlich die Pipeline in der CPU.