Multithreading (architecture informatique)

Multithreading entrelacé/temporelEdit

Article principal : Multithreading temporel

Multithreading à gros grainEdit

Le type de multithreading le plus simple se produit lorsqu’un thread s’exécute jusqu’à ce qu’il soit bloqué par un événement qui devrait normalement créer un décrochage à longue latence. Un tel blocage peut être un manque de cache qui doit accéder à la mémoire hors puce, ce qui peut prendre des centaines de cycles CPU pour que les données reviennent. Au lieu d’attendre que le blocage soit résolu, un processeur threadé bascule l’exécution vers un autre thread prêt à fonctionner. Ce n’est que lorsque les données du thread précédent étaient arrivées que celui-ci était replacé sur la liste des threads prêts à fonctionner.

Par exemple :

  1. Cycle i : l’instruction j du thread A est émise.
  2. Cycle i + 1 : l’instruction j + 1 du thread A est émise.
  3. Cycle i + 2 : l’instruction j + 2 du thread A est émise, ce qui est une instruction de chargement qui manque dans tous les caches.
  4. Cycle i + 3 : le planificateur de threads est invoqué, il passe au thread B.
  5. Cycle i + 4 : l’instruction k du thread B est émise.
  6. Cycle i + 5 : l’instruction k + 1 du thread B est émise.

Conceptuellement, il est similaire au multi-tâches coopératif utilisé dans les systèmes d’exploitation en temps réel, dans lequel les tâches abandonnent volontairement du temps d’exécution lorsqu’elles doivent attendre un certain type de l’événement. Ce type de multithreading est connu sous le nom de multithreading par blocs, coopératif ou à gros grains.

Le but du support matériel du multithreading est de permettre une commutation rapide entre un thread bloqué et un autre thread prêt à s’exécuter. Pour atteindre cet objectif, le coût matériel consiste à répliquer les registres visibles du programme, ainsi que certains registres de contrôle du processeur (comme le compteur de programme). Le passage d’un thread à un autre signifie que le matériel passe de l’utilisation d’un jeu de registres à un autre ; pour passer efficacement d’un thread actif à un autre, chaque thread actif doit avoir son propre jeu de registres. Par exemple, pour passer rapidement d’un thread à l’autre, le matériel de registre doit être instancié deux fois.

Une prise en charge matérielle supplémentaire du multithreading permet de réaliser la commutation de threads en un seul cycle de CPU, ce qui apporte des améliorations de performances. De plus, le matériel supplémentaire permet à chaque thread de se comporter comme s’il s’exécutait seul et ne partageait aucune ressource matérielle avec les autres threads, ce qui minimise la quantité de modifications logicielles nécessaires au sein de l’application et du système d’exploitation pour prendre en charge le multithreading.

De nombreuses familles de microcontrôleurs et de processeurs embarqués disposent de banques de registres multiples pour permettre une commutation rapide du contexte pour les interruptions. De tels schémas peuvent être considérés comme un type de multithreading en bloc entre le thread du programme utilisateur et les threads d’interruption.

Multithreading entrelacéModifier

Article principal : Processeur baril

Le but du multithreading entrelacé est de supprimer tous les décrochages de dépendance de données du pipeline d’exécution. Puisqu’un thread est relativement indépendant des autres threads, il y a moins de chance qu’une instruction dans un étage du pipeline ait besoin d’une sortie d’une instruction plus ancienne dans le pipeline. Conceptuellement, il est similaire au multitâche préemptif utilisé dans les systèmes d’exploitation ; une analogie serait que la tranche de temps donnée à chaque thread actif est un cycle de CPU.

Par exemple :

  1. Cycle i + 1 : une instruction du thread B est émise.
  2. Cycle i + 2 : une instruction du thread C est émise.

Ce type de multithreading a d’abord été appelé traitement en tonneau, dans lequel les douelles d’un tonneau représentent les étapes du pipeline et leurs threads d’exécution. Le multithreading entrelacé, préemptif, à grain fin ou découpé dans le temps est une terminologie plus moderne.

En plus des coûts matériels discutés dans le type de multithreading en bloc, le multithreading entrelacé a un coût supplémentaire de chaque étage de pipeline qui suit l’ID du thread de l’instruction qu’il traite. De plus, comme il y a plus de threads exécutés simultanément dans le pipeline, les ressources partagées telles que les caches et les TLB doivent être plus grandes pour éviter le thrashing entre les différents threads.

Multithreading simultanéModification

Article principal : Multithreading simultané

Le type le plus avancé de multithreading s’applique aux processeurs superscalaires. Alors qu’un processeur superscalaire normal émet plusieurs instructions à partir d’un seul thread à chaque cycle de CPU, dans le multithreading simultané (SMT), un processeur superscalaire peut émettre des instructions à partir de plusieurs threads à chaque cycle de CPU. Reconnaissant que tout thread unique a une quantité limitée de parallélisme au niveau des instructions, ce type de multithreading tente d’exploiter le parallélisme disponible sur plusieurs threads pour diminuer le gaspillage associé aux créneaux d’émission inutilisés.

Par exemple :

  1. Cycle i : les instructions j et j + 1 du thread A et l’instruction k du thread B sont émises simultanément.
  2. Cycle i + 1 : l’instruction j + 2 du thread A, l’instruction k + 1 du thread B et l’instruction m du thread C sont toutes émises simultanément.
  3. Cycle i + 2 : l’instruction j + 3 du thread A et les instructions m + 1 et m + 2 du thread C sont toutes émises simultanément.

Pour distinguer les autres types de multithreading du SMT, le terme « multithreading temporel » est utilisé pour désigner le cas où les instructions d’un seul thread peuvent être émises à la fois.

En plus des coûts matériels discutés pour le multithreading entrelacé, le SMT a le coût supplémentaire de chaque étage du pipeline qui suit l’ID du thread de chaque instruction en cours de traitement. Là encore, les ressources partagées telles que les caches et les TLB doivent être dimensionnées pour le grand nombre de threads actifs traités.

Les implémentations comprennent DEC (puis Compaq) EV8 (non achevé), Intel Hyper-Threading Technology, IBM POWER5, Sun Microsystems UltraSPARC T2, Cray XMT, et les microarchitectures AMD Bulldozer et Zen.