CPU-Grundlagen: Multithreading

Multiskalarer Prozessor

Der bestechend einfache Ansatz mit PEs wird aber durch die dynamische Verwaltung und vor allem die Datenabhängigkeiten zwischen verschiedenen Microthreads komplex. Im Unterschied zu einem Multiprozessoransatz (meist als CMP, Chip-integrated Multiprocessing bezeichnet) bestimmt nicht der Compiler oder der Assembler-Programmierer, welcher Prozessor welchen Teil berechnet.

Diese Aufgabe übernimmt die CPU dynamisch zur Laufzeit. Das bedeutet, dass sie eine dynamische Zuordnung von Microthreads zu PEs durchführen muss, meist ohne zusätzliche Informationen vom Compiler. Die zweite Schwierigkeit besteht in den möglichen Datenabhängigkeiten. Wie soll der multiskalare Prozessor solche Datenabhängigkeiten auflösen oder auch nur erkennen?

Das Bild gibt Aufschluss über den Aufbau und damit auch die Arbeitsweise des multiskalaren Ansatzes. Die Processing Elements PE (Anzahl n) sind in einer Art einfacher Verkettung zu einem Ring miteinander verbunden. Zunächst ist es die Aufgabe des Sequencers, die Microthreads an die PEs zu verteilen. Zur Vorhersage des Kontrollflusses ist auch die Branch Prediction in dieser Einheit enthalten. Die einzelnen PEs sind dann für den Fetch ihrer Instruktionen selbst verantwortlich und besitzen auch einen eigenen Instruktions-Cache.

Jedes PE enthält auch ein vollständiges Register File (mit je einem physikalischen Register pro logischem Register). Beim Instruktionsblock fetch detektiert der multiskalare Prozessor, welche logischen Register potenziell beschrieben werden. Er informiert alle im Ring nachfolgenden PEs über diesen Schreibzugriff und löst eventuell bestehende RAW-Hazards durch Wartezyklen auf. Die Kommunikation über die betroffenen Register erfolgt typisch über Bitmasken.

Die Auflösung von Speicherzugriffen ist schwieriger. Dafür ist ein Address Resolution Buffer (ARB) zuständig, den die PEs über einen gemeinsamen Interconnect ansprechen. Der ARB löst Schreib-/Lesezugriffe auf gemeinsame Adressen auf und vermeidet so Zugriffskonflikte. Letztendlich ist aber der Speicherzugriff einer der entscheidenden Engpässe der multiskalaren Architektur. Typisch findet man daher auch noch zwei Formen der Spekulation:

  • Kontrollflussspekulation: Die Sequencer-Einheit spekuliert auf Grund der Vorinformationen und des bisherigen Programmverlaufs über den weiteren Ablauf der Instruktionsblöcke.

  • Datenspekulationen: Ähnlich wie bei der Itanium Architektur kann der gemeinsame Interconnect Datenzugriffe im Speicher spekulativ ausführen.