Le multithreading et le multitraitement sont les deux moyens les plus courants d'atteindre la concurrence et la parallélisation. Peu de développeurs comprennent la différence entre eux et ne parviennent pas à choisir lequel utiliser. Dans cet article, nous discuterons des différences. Nous pouvons utiliser le module Threading Python pour comprendre et implémenter le concept. Le module de threading offre une API intuitive pour générer facilement plusieurs threads qui peuvent être utilisés lorsqu'il y a plus de puissance de traitement requise. Pour ce faire, vous devrez utiliser quelque chose connu sous le nom de **Lock** ou **Global Interpreter Lock en Python.
Company Mentioned
Coin Mentioned
Le multithreading et le multitraitement sont les deux moyens les plus courants d'atteindre la concurrence et la parallélisation, cependant, peu de développeurs comprennent la différence entre eux et ne parviennent pas à choisir efficacement lequel utiliser et quand.
Dans cet article, nous discuterons des différences entre le multithreading et le multitraitement et comment décider quoi utiliser et comment l'implémenter en Python.
Qu'est-ce qu'un fil ?
Un thread est un flux d'exécution indépendant. Il peut être essentiellement considéré comme un composant individuel léger d'un processus, qui peut s'exécuter en parallèle. Le threading est une fonctionnalité généralement fournie par le système d'exploitation. Il peut y avoir plusieurs threads dans un processus, qui partagent le même espace mémoire, ce qui signifie qu'ils partagent entre eux le code à exécuter et les variables déclarées dans le programme.
Pour mieux comprendre cela, considérons un exemple des programmes en cours d'exécution sur votre ordinateur portable en ce moment. Vous lisez probablement cet article avec plusieurs onglets ouverts dans votre navigateur. Pendant ce temps, l'application de bureau Spotify est ouverte pour écouter de la musique. Désormais, le navigateur et l'application de bureau Spotify sont comme deux processus distincts qui peuvent utiliser plusieurs processus ou threads pour atteindre le parallélisme. Ainsi, les différents onglets de votre navigateur peuvent être exécutés dans différents threads. De même, Spotify peut lire de la musique en utilisant un fil et en utiliser un autre pour télécharger votre chanson préférée sur Internet, et en utiliser un troisième pour afficher l'interface utilisateur. Et cela s'appelle le multithreading.
Qu'est-ce que le multithreading en Python ?
Le multithreading, comme son nom l'indique, est une tâche ou une opération qui peut exécuter plusieurs threads en même temps. Il s'agit d'une technique populaire qui rationalise plusieurs tâches en succession rapide en même temps et facilite le partage rapide et facile des ressources entre plusieurs threads avec le thread principal.
L'image suivante explique le multithreading en Python :
Python est un langage linéaire, mais nous pouvons utiliser le module Threading Python pour comprendre et implémenter le concept de multithreading en Python. Le module de threading offre une API intuitive pour générer facilement plusieurs threads qui peuvent être utilisés lorsqu'il y a plus de puissance de traitement requise.
Il peut être utilisé comme indiqué ci-dessous :
import threading from queue import Queue import time def testThread(num): print num if __name__ == '__main__': for i in range(5): t = threading.Thread(target=testThread, arg=(i,)) t.start()
Dans l'extrait de code ci-dessus, target est utilisé comme objet appelable, args pour transmettre des paramètres à la fonction et start pour démarrer le thread.
Maintenant, voici quelque chose d'intéressant - la serrure.
Verrouillage global de l'interpréteur
Il y a souvent des cas en programmation où vous voudriez que vos threads puissent modifier ou utiliser les variables communes aux threads. Cependant, pour ce faire, vous devrez utiliser quelque chose connu sous le nom de Lock ou Global Interpreter Lock (GIL) en Python.
Du Python :
Dans CPython, le verrou d'interpréteur global , ou GIL , est un mutex qui protège l'accès aux objets Python, empêchant plusieurs threads d'exécuter des bytecodes Python à la fois. Ce verrou est nécessaire principalement parce que la gestion de la mémoire de CPython n'est pas thread-safe.
Au niveau de l'interpréteur, Python sérialise essentiellement les instructions. Pour qu'un thread puisse exécuter une fonction, il doit d'abord obtenir un verrou global. Étant donné qu'un seul thread peut obtenir ce verrou à la fois, l'interpréteur doit finalement exécuter les instructions en série. Cette architecture rend la gestion de la mémoire sécurisée pour les threads, mais elle ne peut pas du tout utiliser plusieurs cœurs de processeur.
En termes simples, chaque fois qu'une fonction souhaite utiliser ou modifier une variable, elle verrouille cette variable de sorte que si une autre fonction souhaite utiliser ou modifier cette variable spécifique, elle devra attendre que cette variable soit déverrouillée.
Considérons deux fonctions qui itèrent chacune une variable de un. Vous pouvez utiliser le verrou pour vous assurer qu'une fonction peut lire la variable, exécuter des calculs et y écrire avant qu'une autre fonction ne le puisse, afin d'éviter la corruption des données.
Cas d'utilisation de la lecture multiple en Python
Le threading en Python est plus utile pour les opérations d'E/S ou les tâches liées au réseau telles que l'exécution de scripts par exemple, dans le cas du scraping Web plutôt que pour les tâches qui peuvent être gourmandes en CPU. Un autre exemple est , qui utilise un pool de threads pour transformer les données en parallèle.
Outre ces applications, les interfaces utilisateur graphiques (GUI) utilisent en permanence le multithreading pour rendre les applications réactives et interactives. Un exemple courant pourrait être un programme d'édition de texte où dès que l'utilisateur saisit du texte, celui-ci s'affiche à l'écran. Ici, un thread s'occupe de l'entrée de l'utilisateur tandis que l'autre thread gère la tâche pour l'afficher. Nous pouvons ajouter plus de threads pour plus de fonctionnalités telles que la vérification orthographique, la saisie semi-automatique, etc.
Maintenant, après avoir discuté des threads en détail, passons aux processus.
Qu'est-ce qu'un processus ?
Un processus est simplement une instance du programme informatique en cours d'exécution. Chaque processus a son propre espace mémoire qui est utilisé pour stocker les instructions en cours d'exécution et toutes les données auxquelles il a besoin d'accéder ou de stocker pour l'exécution du code. Pour cette raison, la création d'un processus prend plus de temps et est plus lente qu'un thread.
Comme nous l'avons vu précédemment, lorsque nous exécutons plusieurs applications sur notre bureau, chaque application est un processus et lorsque nous exécutons ces processus en même temps, cela s'appelle le multitraitement.
Qu'est-ce que le multitraitement en Python ?
Le multitraitement est la capacité d'un processeur à exécuter simultanément plusieurs tâches indépendantes. Il vous permet de créer des programmes pouvant s'exécuter simultanément, en contournant le verrouillage global de l'interpréteur (GIL) et en utilisant l'intégralité du cœur du processeur pour une exécution efficace des tâches.
Bien que le concept de multitraitement soit fondamentalement différent du multithreading, leur syntaxe ou leur utilisation en Python est assez similaire. Semblable au module Threading, nous avons un module Multiprocessing en Python qui aide à générer différents processus, où chaque processus a son propre interpréteur Python et un GIL.
Étant donné que les processus ne partagent pas la même mémoire, ils ne peuvent pas modifier la même mémoire simultanément, ce qui nous évite le risque de tomber dans une impasse ou de corruption de données.
Il peut être utilisé comme indiqué ci-dessous :
import multiprocessing def spawn(num): print(num) if __name__ == '__main__': for i in range(5): p = multiprocessing.Process(target=spawn, args=(i,)) p.start() p.join() # this line allows you to wait for processes
Cas d'utilisation du multitraitement en Python
Comme nous l'avons également mentionné précédemment, le multitraitement est un choix plus judicieux dans le cas où les tâches sont gourmandes en CPU et n'ont pas d'opérations d'E/S ou d'interactions avec l'utilisateur.
Différences, mérites et inconvénients
Voici quelques points pour résumer les différences, mérites et inconvénients du Multiprocessing et du Multithreading :
Les threads partagent le même espace mémoire alors que chaque processus possède son propre espace mémoire.
Le partage d'objets entre les threads est plus simple, mais vous devez prendre des précautions supplémentaires pour la synchronisation des objets afin de vous assurer que deux threads n'écrivent pas dans le même objet en même temps et qu'une condition de concurrence ne se produit pas.
La programmation multithread est plus sujette aux bogues que le multitraitement en raison de la surcharge de programmation supplémentaire pour la synchronisation des objets.
Le processus de génération prend plus de temps et de ressources que les threads car ils ont une surcharge inférieure à celle des processus.
Les threads ne peuvent pas atteindre un parallélisme complet en exploitant plusieurs cœurs de processeur en raison des contraintes GIL en Python. Il n'y a pas de telles contraintes avec le multitraitement.
Le système d'exploitation gère la planification des processus, tandis que l'interpréteur Python gère la planification des threads.
Les processus enfants peuvent être interrompus et tués, mais les threads enfants ne le peuvent pas. Vous devez attendre que les threads se terminent ou se rejoignent.
Conclusion
Nous pouvons tirer les conclusions suivantes de cette discussion :
Le threading est recommandé pour les programmes nécessitant une interaction IO ou utilisateur.
Pour les applications gourmandes en ressources processeur, le multitraitement doit être utilisé.
Maintenant que vous comprenez comment Python Multiprocessing et Multithreading fonctionnent et comment ils se comparent, vous pouvez écrire du code efficacement et appliquer les deux approches dans diverses circonstances.
J'espère que vous avez trouvé cet article utile. Continue de lire!