Je ne sais pas si le multithreading fonctionne ou non en Python.
Je sais qu'il y a eu beaucoup de questions à ce sujet et j'en ai lu beaucoup, mais je suis toujours confus. Je sais d'après ma propre expérience et j'ai vu d'autres personnes publier leurs propres réponses et exemples ici sur StackOverflow que le multithreading est en effet possible en Python. Alors pourquoi tout le monde continue-t-il à dire que Python est verrouillé par le GIL et qu'un seul thread peut s'exécuter à la fois? Cela fonctionne clairement. Ou y a-t-il une distinction que je ne parviens pas ici?
De nombreuses affiches / répondants continuent également de mentionner que le filetage est limité car il n'utilise pas plusieurs cœurs. Mais je dirais qu'ils sont toujours utiles car ils fonctionnent simultanément et accélèrent ainsi la charge de travail combinée. Je veux dire, pourquoi y aurait-il même un module de thread Python autrement?
Mettre à jour:
Merci pour toutes les réponses à ce jour. La façon dont je comprends les choses est que le multithreading ne fonctionnera qu'en parallèle pour certaines tâches d'E / S, mais ne peut en exécuter qu'une à la fois pour les tâches de base multiples liées au processeur.
Je ne suis pas tout à fait sûr de ce que cela signifie pour moi en termes pratiques, je vais donc simplement donner un exemple du type de tâche que j'aimerais effectuer en multithread. Par exemple, disons que je souhaite parcourir une très longue liste de chaînes et que je souhaite effectuer des opérations de base sur les chaînes sur chaque élément de la liste. Si je divise la liste, envoie chaque sous-liste à traiter par mon code de boucle / chaîne dans un nouveau thread, et renvoie les résultats dans une file d'attente, ces charges de travail s'exécuteront-elles à peu près en même temps? Plus important encore, cela accélérera-t-il théoriquement le temps nécessaire à l'exécution du script?
Un autre exemple pourrait être si je peux rendre et enregistrer quatre images différentes en utilisant PIL dans quatre threads différents, et est-ce que cela est plus rapide que de traiter les images une par une après l'autre? Je suppose que ce composant de vitesse est ce que je me demande vraiment plutôt que quelle est la terminologie correcte.
Je connais également le module de multitraitement, mais mon intérêt principal pour le moment est pour les charges de tâches petites à moyennes (10-30 secondes) et je pense donc que le multithreading sera plus approprié car les sous-processus peuvent être lents à démarrer.
la source
Réponses:
Le GIL n'empêche pas le filetage. Tout ce que fait le GIL est de s'assurer qu'un seul thread exécute le code Python à la fois; le contrôle bascule toujours entre les threads.
Ce que le GIL empêche alors, c'est d'utiliser plus d'un cœur de processeur ou des processeurs séparés pour exécuter des threads en parallèle.
Cela ne s'applique qu'au code Python. Les extensions C peuvent publier et libèrent le GIL pour permettre à plusieurs threads de code C et à un thread Python de s'exécuter sur plusieurs cœurs. Cela s'étend aux E / S contrôlées par le noyau, telles que les
select()
appels de lecture et d'écriture de socket, ce qui permet à Python de gérer les événements réseau de manière raisonnablement efficace dans une configuration multicœur multi-thread.Ce que font de nombreux déploiements de serveurs, c'est d'exécuter plus d'un processus Python, pour laisser le système d'exploitation gérer la planification entre les processus afin d'utiliser vos cœurs de processeur au maximum. Vous pouvez également utiliser la
multiprocessing
bibliothèque pour gérer le traitement parallèle sur plusieurs processus à partir d'une base de code et d'un processus parent, si cela convient à vos cas d'utilisation.Notez que le GIL n'est applicable qu'à l'implémentation CPython; Jython et IronPython utilisent une implémentation de thread différente (respectivement les threads d'exécution communs Java VM et .NET natifs).
Pour adresser directement votre mise à jour: toute tâche qui tente d'obtenir une augmentation de vitesse à partir d'une exécution parallèle, en utilisant du code Python pur, ne verra pas d'accélération car le code Python threadé est verrouillé sur un thread s'exécutant à la fois. Cependant, si vous mélangez des extensions C et des E / S (comme des opérations PIL ou numpy) et n'importe quel code C peut s'exécuter en parallèle avec un thread Python actif.
Le thread Python est idéal pour créer une interface graphique réactive ou pour gérer plusieurs requêtes Web courtes où les E / S sont le goulot d'étranglement plus que le code Python. Il ne convient pas pour paralléliser du code Python intensif en calcul, s'en tenir au
multiprocessing
module pour de telles tâches ou déléguer à une bibliothèque externe dédiée.la source
urllib.urlopen()
?), Pour appeler un script Python à partir d'une interface graphique Python, et appeler plusieurs opérations PIL (par exempleImage.transform()
) et numpy (par exemplenumpy.array()
) avec des threads. Et vous avez fourni d'autres exemples dans votre commentaire, comme l'utilisation de plusieurs threads pour lire des fichiers (par exemplef.read()
?). Je sais qu'une liste exhaustive n'est pas possible, je voulais juste les types d'exemples que vous avez donnés dans votre mise à jour. Quoi qu'il en soit, j'ai accepté votre réponse :)urllib.urlopen()
invoquerait les sockets réseau, attendre les E / S de socket est une excellente opportunité de changer de thread et de faire autre chose.Oui. :)
Vous avez le module de filetage de bas niveau et le module de filetage de niveau supérieur . Mais si vous souhaitez simplement utiliser des machines multicœurs, le module multitraitement est la solution.
Citation de la documentation :
la source
Le thread est autorisé en Python, le seul problème est que le GIL s'assurera qu'un seul thread est exécuté à la fois (pas de parallélisme).
Donc, fondamentalement, si vous voulez multi-threader le code pour accélérer le calcul, cela ne l'accélérera pas car un seul thread est exécuté à la fois, mais si vous l'utilisez pour interagir avec une base de données par exemple, ce sera le cas.
la source