Hyper-Threading: Optimierungen und Fallen

Sicher ist sicher

Auf einer Single-CPU sind Variablen in der Pipeline kein Problem. Unterbricht der Scheduler einen Thread, läuft zunächst einiges an Betriebssystem-Code, bevor ein anderer Thread zum Zuge kommt. Bis dahin haben alle Thread-spezifischen Variablen die Pipeline längst verlassen. Auf Hyper-Threading-Systemen kann dieser Zustand jedoch sehr häufig auftreten - in unserem Beispiel in jedem dritten Fall. Es hilft also alles nichts: Wer auf globale Variablen auch schreibend zugreift, muss diese aufwendig absichern.

Rechenfehler

ILoopThread[0]

iLoopThread[0]

Summe

iLoops

Gemessen mit Pentium 4 3,06 GHz unter Windows XP

Ohne Hyper-Threading

245.606.869

231.350.580

476.957.449

476.957.449

Mit Hyper-Threading

23.575.428

24.237.485

47.812.913

29.339.340

Bevor einige Methoden zur Absicherung miteinander verglichen werden, noch eine allgemeine Anmerkung zu globalen Variablen. Die rund 90 Prozent schlechtere Performance mit Hyper-Threading in obigem Beispiel beruht allein auf dem Update von iLoops. Schreibt eine CPU-Pipeline einen Wert in den Cache zurück, muss sie dazu die entsprechende Cacheline für eine relativ lange Zeit exklusiv sperren. Während dieser Zeit kann die andere Pipeline nicht weiterarbeiten, wenn sie Daten aus dieser Line benötigt. In unserem Extrembeispiel kostet dieser Effekt 90 Prozent Performance. Da in der Praxis die Threads neben dem Update gemeinsamer Variablen auch noch etwas anderes zu tun haben, ist dieser Effekt weniger dramatisch. Dennoch gilt: "Threads sollten so unabhängig wie nur irgend möglich voneinander sein."