1.1 Histoire de l'apparition
L'humanité arrive souvent à l'idée de construire un nouveau projet gigantesque qui éclipsera tous les précédents projets grandioses. La pyramide de Khéops à Gizeh — la plus grande, le Burj Khalifa à Dubaï — le plus haut, et la Grande Muraille de Chine — le plus long.
Cependant, organiser le travail sur de tels projets est très complexe. Si nous voulons construire une nouvelle pyramide deux fois plus haute, elle exigera huit fois plus de pierres. Cela signifie qu'il faut soit augmenter la productivité des carrières, soit en ouvrir de nouvelles.
Il faudra aussi trouver huit fois plus d'ingénieurs, peut-être ouvrir des écoles d'ingénierie, standardiser les plans, la géométrie, l'écriture. Bref, un bon casse-tête...
Depuis la construction des pyramides, rien n'a changé en milliers d'années — les gens continuent à réfléchir à comment réaliser de plus en plus de travaux en moins de temps. Et quand les ordinateurs ont été inventés, les meilleurs esprits de l'humanité ont commencé à s'attacher à cette tâche.
Comment exécuter un programme dix fois plus vite ? Cela semble être une question étrange — si le processeur fonctionne déjà à pleine vitesse, il semble que ce ne soit pas possible. Cependant, je n'ai pas mentionné les meilleurs esprits de l'humanité pour rien. Ils ont analysé le fonctionnement de tous les programmes et ont conclu qu'il y avait trois grandes directions de croissance.
Élimination des temps d'arrêt
Il s'avère que la plupart du temps, un programme est inactif. Il attend constamment quelque chose : les données doivent être copiées d'un endroit de la mémoire à un autre, chargées depuis le disque dur dans la mémoire, attendre la réponse du serveur à une requête, l'entrée de données de l'utilisateur, etc.
Toutes ces tâches ne sont pas effectuées par le processeur central, mais par les contrôleurs de mémoire, disque, etc. Et le processeur central pourrait être utilisé à bon escient pendant ce temps. Ainsi est née l'idée de lancer dans un même processeur plusieurs threads d'exécution de commandes plutôt qu'un seul.
Et pendant que, par exemple, un thread attend l'entrée de l'utilisateur, un autre télécharge quelque chose sur le réseau, un troisième traite les données, un quatrième dessine les images à l'écran. Puis cette tâche évolue vers des tâches asynchrones et des coroutines, mais nous en parlerons plus tard.
Plus de programmes
Si les programmes sont inactifs 80% du temps, c'est bien sûr un problème. D'un autre côté, il n'est pas possible de réécrire tous les programmes selon nos nouvelles approches. Peut-être que ce problème peut être résolu autrement — nous pouvons simplement exécuter plusieurs programmes sur un ordinateur en même temps.
Dans ce cas, le système d'exploitation surveille l'exécution des programmes, et si un programme est inactif, il alloue son temps d'exécution à un autre programme. Ce commutateur se produit des dizaines de fois par seconde, et l'utilisateur ne remarque pas les changements — à son avis, les programmes s'exécutent simultanément.
Plus de processeurs
L'exécution simultanée de programmes est géniale, mais que se passe-t-il si nous avons de nombreux programmes, et qu'ils sont peu inactifs ? Pas de temps d'arrêt — pas d'utilisation efficace. Par exemple, nous avons dix programmes qui effectuent des calculs, ou un jeu exigeant en ressources et encore quelque chose en même temps.
La solution à ce problème a été d'ajouter au processeur plusieurs processeurs. Pour éviter la confusion, on les a appelés cœurs. Maintenant, nous avons des processeurs qui ont plusieurs cœurs (sous-processeurs), sur lesquels des dizaines de programmes fonctionnent en parallèle.
C'est intéressant ! Nombre de cœurs dans les processeurs
De nos jours, les processeurs de serveurs peuvent avoir de 64 à 256 cœurs, et dans certains cas spécialisés, encore plus. Par exemple, les processeurs AMD EPYC de 4ème génération proposent jusqu'à 96 cœurs, et l'IBM POWER10 peut avoir jusqu'à 240 cœurs par puce. Les processeurs pour utilisateurs ont également beaucoup évolué : les CPU de bureau haute performance, tels que l'AMD Threadripper, peuvent avoir jusqu'à 64 cœurs, tandis que les modèles plus répandus ont généralement entre 6 et 16 cœurs.
Où aller après ça ? Il y a encore des progrès à faire ! Premièrement, sur une carte mère de serveur on peut installer plusieurs processeurs, par exemple deux ou même quatre. Ensuite, les serveurs peuvent être regroupés dans des racks de serveurs de 10 à 20 pièces. Et les racks de serveurs — dans des centres de données où il y a des milliers de ces racks.
Les systèmes distribués et les architectures de microservices sont devenus une pratique courante dans le développement logiciel moderne. De nombreuses grandes entreprises, comme Google, Amazon, Netflix, et même des entreprises plus petites, utilisent des systèmes distribués pour traiter de grands volumes de données, assurer une haute disponibilité et une évolutivité de leurs services. Ces systèmes permettent d'utiliser efficacement les ressources de nombreux serveurs fonctionnant ensemble comme une seule entité, ce qui augmente considérablement la performance et la résilience des applications.
1.2 Avantages
Le multithreading, ou l'exécution simultanée de tâches au sein d'un programme, offre plusieurs avantages clés qui peuvent considérablement améliorer la performance et l'efficacité des logiciels. Examinons les principaux avantages du multithreading.
1. Amélioration de la performance et de la vitesse d'exécution
Exécution parallèle des tâches : Le multithreading permet d'exécuter simultanément plusieurs tâches, ce qui est particulièrement utile pour les programmes nécessitant l'exécution de nombreuses opérations indépendantes. Cela permet d'accélérer l'exécution du programme, car les tâches sont exécutées en parallèle, utilisant toutes les ressources disponibles du processeur.
Utilisation des processeurs multicœurs : Les processeurs modernes ont plusieurs cœurs, et le multithreading permet d'utiliser pleinement leur puissance, en répartissant les threads sur différents cœurs pour exécuter les tâches en parallèle.
2. Amélioration de la réactivité et de l'interaction avec l'utilisateur
Tâches en arrière-plan : Le multithreading permet d'exécuter des opérations longues ou gourmandes en ressources en arrière-plan, tout en gardant le thread principal, responsable de l'interface utilisateur, réactif. Cela améliore l'expérience de l'utilisateur, car l'interface ne se bloque pas lors de l'exécution de tâches lourdes.
Opérations asynchrones : L'interaction avec l'utilisateur et le traitement des événements peuvent se produire en parallèle avec l'exécution des tâches principales, rendant les applications plus réactives et efficaces.
3. Utilisation efficace des ressources système
Optimisation des ressources : Le multithreading permet une utilisation plus efficace des ressources système, telles que le temps processeur et la mémoire. Cela est particulièrement important pour les serveurs et les systèmes de calcul haute performance, où le multithreading permet de traiter un grand nombre de requêtes et de tâches simultanément.
Gestion des entrées/sorties : Les applications multithread peuvent gérer les tâches d'entrée/sortie (par exemple, opérations réseau, lecture et écriture de fichiers) plus efficacement, car les threads peuvent exécuter d'autres tâches pendant que l'une d'elles attend la fin d'une opération d'entrée/sortie.
4. Support de la multitâche
Multitâche : Le multithreading permet d'exécuter plusieurs tâches simultanément dans un même processus, ce qui simplifie le développement d'applications nécessitant de la multitâche, telles que les serveurs web, les bases de données et les applications en temps réel.
Traitement parallèle des données : Dans les tâches liées au traitement de grandes quantités de données, le multithreading permet de diviser les données en parties et de les traiter en parallèle, ce qui accélère considérablement l'exécution de la tâche.
Exemples d'utilisation du multithreading
Serveurs web : Le multithreading permet aux serveurs web de traiter de nombreuses requêtes clients simultanément, augmentant la performance et l'évolutivité des serveurs.
Interfaces graphiques utilisateur (GUI) : Dans les applications avec interface graphique, le multithreading permet d'exécuter de longs calculs en arrière-plan, en gardant l'interface réactive.
Calculs scientifiques : Le multithreading est utilisé pour le traitement parallèle des données dans les calculs scientifiques, ce qui permet d'accélérer considérablement l'exécution de tâches de calcul complexes.
Jeux et simulations : Dans les jeux, le multithreading permet de traiter simultanément la physique, les graphismes, les sons et les actions de l'utilisateur, améliorant la performance et le réalisme.
1.3 Nom correct
Il y a des réserves concernant le nom « multithreading ». Il se compose de deux mots : « multi » et « thread », comme s'il insinuait qu'à l'intérieur du programme se trouvent de nombreux « threads d'exécution de commandes » qui font quelque chose.
Une belle analogie, mais dans la littérature anglaise (originale) pour désigner plusieurs actions exécutées en parallèle, on utilise le terme « thread » (thread). Et, en conséquence, le multithreading est écrit multi-threading.
Cela pourrait être considéré comme un simple malentendu — quelle différence cela fait-il, comment différents termes se traduisent dans une autre langue, si en programmation ça devient une habitude d'utiliser des concepts comme stream, qui ne peut être traduit que par le mot « flux ».
Par conséquent, il existe actuellement une certaine confusion dans la terminologie francophone, qui est résolue de deux manières :
-
Thread(fil) est traduit par « thread d'exécution [de commandes] ». Stream(flux) est traduit par « flux de données ».
D'un autre côté, de nombreux programmeurs ont simplement commencé à utiliser des termes anglais sans traduction :
-
Thread(fil) est prononcé « thread », et multi-threading comme « multi-threading ». Stream(flux) est prononcé « stream ».
On appelle souvent un thread un fil, mais le terme « multi-fils » n'a pas pris racine. Donc, souvent dans les conversations, on utilise « fil » et « multithreading » simultanément.
L'utilisation d'un grand nombre de termes empruntés enrichit la langue, permet de donner aux mots un nouveau sens et facilite la communication avec des collègues d'autres pays. Je suis totalement pour cette approche.
GO TO FULL VERSION