Hyper-Threading im Detail

Interner Ablauf

Das Betriebssystem verwaltet den einen Multi-Threaded-Prozessor mit den beiden logischen Prozessoren im Wesentlichen so wie zwei getrennte physische Prozessoren. Die nächsten auszuführenden Befehle der zwei Threads werden in die beiden Instruction Pointer (IP) gelegt und gelangen von dort zur Ausführung in die nächsten Stufen. Nach dem Abarbeiten der vorbereitenden Ausführungsschritte verteilt der Scheduler die unabhängigen Instruktionen auf die verfügbaren Ausführungseinheiten.

Die Arbeitsweise eines Hyper-Threading-Prozessors sieht beispielsweise so aus:

  • 1. Zu Beginn sind beide logischen Prozessoren im Idle-Zustand.

  • 2. Das Betriebssystem startet einen Thread 1 auf dem logischen Prozessor LP0. Während der Zeit, in der nur ein Thread aktiv ist, kann dieser allein über die Ressourcen des Prozessors verfügen. Von den doppelt vorhandenen Komponenten wird nur eine Ausführung betrieben.

  • 3. Das Betriebssystem startet einen zweiten Thread auf dem logischen Prozessor LP1. Die beiden Threads teilen sich nun die vorhandenen Ressourcen. Dabei konkurrieren sie um die einfach und um die doppelt vorhandenen Hardware-Einheiten, die sie parallel nutzen. Einfach vorhandene Komponenten, die hälftig verwendet werden, sind entsprechend zu partitionieren. Für diese Aufteilung wird die Pipeline mit dem Thread 1 geleert (flushen) und anschließend mit beiden Threads neu gefüllt.

  • 4. Wenn Thread 1 beendet ist, stehen die im vorherigen Punkt genannten Ressourcen Thread 2 vollständig zur Verfügung. Hierzu sollte Thread 1 explizit mit einem HALT beendet werden. Das Flushen und erneute Auffüllen der Pipeline kostet Zeit, weshalb ein zu häufiger Thread-Wechsel nicht empfehlenswert ist. Der erzielbare Leistungsgewinn würde sonst den Aufwand nicht rechtfertigen. Neben dem Leeren der Ausführungs-Pipelines ist auch eine besondere Behandlung von Sperrvariablen (Spin Locks) zu beachten. Sperrvariablen werden in zeitlich beschränkten kritischen Bereichen von Prozessen und Threads eingesetzt, um deren Unterbrechung zu vermeiden. Der neu eintretende Prozess muss entsprechend warten, bis die Sperrvariable aufgehoben wurde. Dies geschieht in der Regel durch eine zyklische Abfrage (Spin Wait Loops). Um dabei die Verzögerung beim Verlassen der Schleife so gering wie möglich zu halten, ist der neu eintretende Task in einem PAUSE-Status zu halten. Wenn ihm eine längere Wartezeit bevorsteht, ist diese zyklische Abfrage nicht mehr effizient. Er muss sich dann an das Betriebssystem wenden, damit der sperrende Task unterbrochen (suspend) wird. Diese Vorkehrungen sind abwärtskompatibel auch auf IA-32-Prozessoren ausführbar, die kein Hyper-Threading unterstützen.