Hyper-Threading: Optimierungen und Fallen

Critical Section oder Mutex?

Das vorangegangene Beispiel verdeutlicht, dass man beim Update von gemeinsamen Variablen entsprechende Vorsichtsmaßnahmen treffen muss. Für das Update von Integer-Variablen stehen dafür sogar spezielle Interlocked-Funktionen zur Verfügung. So erhöht InterlockedIncrement( ) einen Integer Thread-sicher um Eins. Da die Interlocked-Funktionen allerdings nur Integer-Variablen abdecken, werden sie im Folgenden nicht weiter betrachtet.

Die Klassiker für den Thread-sicheren Zugriff auf beliebige Variablen sind unter Windows die Critical Section und der Mutex. Bei der Critical Section definiert man einen Code-Abschnitt, der immer nur von einem Thread betreten werden kann. Ein Mutex dagegen ist ein Objekt, dass immer nur einen Thread als Besitzer hat. Während eine Critical Section nur innerhalb eines Programms zur Verfügung steht, ist ein Mutex ein Kernel-Objekt. Dadurch kann er auch die Synchronisation zwischen verschiedenen Programmen regeln.

In der Literatur ist allgemein zu lesen, dass ein Mutex rund 100 Mal langsamer wäre als eine Critical Section. Doch auch hier muss man bei Hyper-Threading umdenken.

Das Testprogramm ist im Wesentlichen gleich geblieben. Die eigentliche Benchmark-Schleife while (Status != STOP) zählt die Thread-spezifische iLoopsThread[num] und die gemeinsame globale Variable iLoops hoch. Im ersten Fall sorgt der Scheduler dafür, dass immer nur maximal ein Thread innerhalb der Critical Section läuft.

Im zweiten Fall wartet jeder Thread so lange, bis er den Mutex mMutex exklusiv besitzt. Dann erhöht er die Variablen und gibt den Mutex wieder frei.

In beiden Fällen ist sichergestellt, dass immer nur ein Thread gleichzeitig auf die Variablen zugreift. Damit kann kein Verzählen mehr stattfinden.