11.4.3.2.1 : Threads, cœurs et processeurs
Au sein d'un nœud de calcul, il existe plusieurs concepts matériels proches dont on pourra parfois ignorer les nuances, mais qu'il est important de pouvoir différencier~:
- Un CPU multi-thread peut gérer plusieurs tâches concurrentes et basculer entre elles sans assistance du système d'exploitation.
- Un CPU multi-cœur possède la capacité d'exécuter plusieurs tâches simultanément.
- Un système multi-processeur possède plusieurs CPUs, généralement eux-mêmes multi-cœur et/ou multi-thread.
Ces trois concepts sont exposés par les systèmes d'exploitation via une abstraction unique, le thread, qui représente un sous-programme pouvant être associé à un thread du CPU ou s'exécuter sur un cœur CPU lorsque ces ressources matérielles seront disponibles.
Le multi-threading matériel n'est pas une forme de parallélisme, puisqu'il ne permet pas d'exécuter plus d'instructions en même temps. Mais il peut revêtir les apparences du parallélisme lorsqu'il est utilisé comme optimisation de performance, en permettant par exemple à un thread de prendre le relais d'un autre pendant que ce dernier attend un accès mémoire afin que les cycles CPU correspondants ne soient pas gaspillés.
Cette confusion est augmentée par le fait que les systèmes d'exploitation n'exposent la différence entre thread et cœur que dans leurs interfaces au plus bas niveau, et les fabricants de matériel abusent parfois de cette situation en entretenant la confusion pour pouvoir afficher des capacités multi-tâches supérieures dans leur communication.
Mais hélas, l'imposture est rapidement révélée quand on entreprend le processus d'optimisation. En effet, puisque le multi-threading matériel n'améliore les performances que quand un thread fait un usage inefficace du CPU (en attendant la mémoire par exemple), l'optimisation va avoir pour effet de diminuer l'impact de ce mécanisme sur les performances. Et sur un programme bien optimisé, le multi-threading matériel pourra même dégrader les performances, car il augmentera la pression sur les ressources CPU partagées entre les threads.
Face à cette situation, certains centres de calcul vont jusqu'à désactiver les fonctionnalités de multi-threading matériel au niveau OS. Sans cautionner cet extrémisme, qui force les utilisateurs à délaisser des ressources matérielles pouvant être utiles à certaines tâches comme la gestion des entrées-sorties, nous recommanderons de ne pas considérer le passage à l'échelle dans le régime de multi-threading matériel comme important, et de privilégier avant tout le parallélisme multi-cœur et multi-processeur.
La nuance entre multi-cœur et multi-processeur est plus subtile, et leur confusion est souvent plus pardonnable. Mais elle a une importance lors des accès mémoire et des communications~:
- Les cœurs situés sur un processeur étant physiquement éloignés des cœurs situés sur un autre processeur, leurs communications ont plus de latence et doivent composer avec une bande passante plus faible.
- Chaque processeur possède généralement un accès privilégié à une partie de la RAM, les autres processeurs devant communiquer avec lui pour y accéder. Pour faire un usage optimal du bus mémoire, il faut alors privilégier l'accès aux données "locales".
Alors que le nombre de cœur des processeurs augmente, ce type d'hétérogénéité des communications et des accès mémoires commence à apparaître même au sein des processeurs individuels. La frontière du processeur devient donc progressivement moins pertinente, et on tend à lui préférer aujourd'hui les concepts plus généraux de distance et de localité.