Python mondial interprète Lock (GIL) solution de contournement sur les systèmes multi-core en utilisant taskset sur Linux?

StackOverflow https://stackoverflow.com/questions/990102

Question

Je viens de regarder ce discours sur le Python mondial interprète Lock (GIL) http://blip.tv/ fichier / 2232410 .

L'essentiel de ce que le GIL est une très bonne conception pour les systèmes de base unique (Python essentiellement le traitement laisse de fil / planification au système d'exploitation). Mais que cela peut sérieusement se retourner contre les systèmes multi-core et vous vous retrouvez avec IO fils intensifs étant fortement bloqués par CPU fils intensifs, les frais de changement de contexte, le problème ctrl-C [*] et ainsi de suite.

Alors, depuis le GIL nous limite à exécuter essentiellement un programme Python sur un CPU ma pensée est pourquoi ne pas accepter cela et il suffit d'utiliser taskset sur Linux pour définir l'affinité du programme à un certain noyau / cpu sur le système (en particulier dans une situation avec de multiples applications python fonctionnant sur un système multi-core)?

Alors, finalement, ma question est la suivante: quelqu'un a essayé d'utiliser taskset sur Linux avec des applications Python (en particulier lors de l'exécution de plusieurs applications sur un système Linux afin que plusieurs noyaux peuvent être utilisés avec une ou deux applications Python liées à un noyau spécifique) et Si oui, quels étaient les résultats? est-il en vaut la peine? Est-il empirer les choses pour certaines charges de travail? Je prévois de le faire et le tester (voir essentiellement si le programme prend plus ou moins de temps pour courir) mais aimerait entendre d'autres à vos expériences.

Addition: David Beazley (le gars donnant la parole dans la vidéo liée) a fait remarquer que certaines extensions C / C ++ Annulez manuellement le verrou GIL et si ces extensions sont optimisées pour le multi-core (analyse des données scientifiques ou numérique / etc .), alors plutôt que d'obtenir les avantages de multi-core pour le nombre crissant l'extension serait effectivement paralysé en ce sens qu'elle est limitée à un seul noyau (ralentissant ainsi potentiellement votre programme en forte baisse). D'autre part, si vous ne l'utilisez des extensions telles que cela

La raison pour laquelle je ne suis pas en utilisant le module de multitraitement est que (dans ce cas) une partie du programme est fortement réseau lié aux E / S (requêtes HTTP) afin d'avoir un pool de threads de travail est une excellente façon de serrer la performance sur une boîte depuis un feu de fil au large d'une requête HTTP et puisqu'il est en attente sur les E / S donne le GIL et un autre thread peut le faire est chose, de sorte qu'une partie du programme peut facilement exécuter plus de 100 threads sans nuire à l'unité centrale de traitement beaucoup plus et laissez me utilise en fait la bande passante réseau disponible. Quant à stackless Python / etc Je ne suis pas trop intéressé à réécrire le programme ou le remplacement de ma pile Python (disponibilité serait également une préoccupation).

[*] Seul le thread principal peut recevoir des signaux, donc si vous envoyez un ctrl-C l'interpréteur Python essaie essentiellement d'obtenir le thread principal pour exécuter de sorte qu'il peut gérer le signal, mais comme il ne contrôle pas directement quel fil est exécuté (ce qui est laissé au système d'exploitation), il indique essentiellement le système d'exploitation pour maintenir des fils de commutation jusqu'à ce qu'il frappe finalement le fil conducteur (qui, si vous êtes malchanceux peut prendre un certain temps).

Était-ce utile?

La solution

Je ne l'ai jamais entendu parler de quelqu'un en utilisant taskset pour un gain de performance avec Python. Ne veut pas dire qu'il ne peut pas se produire dans votre cas, mais certainement publier vos résultats pour que les autres peuvent critiquer vos méthodes d'étalonnage et de fournir une validation.

Personnellement, cependant, je découpler vos fils d'E / S des fils liés CPU en utilisant une file d'attente de messages. De cette façon, votre extrémité avant est maintenant complètement en réseau d'E / S lié (certaines avec interface HTTP, certaines avec l'interface de file d'attente de messages) et idéal pour votre situation de filetage. Ensuite, la CPU processus intenses peuvent soit utiliser multitraitement ou être juste des processus individuels d'attente pour le travail pour arriver à la file d'attente des messages.

À plus long terme, vous pouvez également envisager de remplacer votre front-end I / O filetée avec Twisted ou quelque chose comme eventlets parce que, même si elles ne vont pas aider la performance qu'ils devraient améliorer l'évolutivité. Votre arrière-plan est maintenant déjà évolutive parce que vous pouvez exécuter la file d'attente de messages sur un certain nombre de machines + CPUs au besoin.

Autres conseils

Une autre solution est: http://docs.python.org/library/multiprocessing.html

Note 1:. Ceci est pas une limitation du langage Python, mais la mise en œuvre CPython

Note 2: En ce qui concerne l'affinité, votre système d'exploitation ne devrait pas avoir un problème qui se fait

.

Une solution intéressante est l'expérience rapportée par Ryan Kelly sur son blog: http://www.rfk.id.au/blog/entry/a-gil-adventure-threading2/

Les résultats semble très satisfaisant.

J'ai trouvé la règle suivante suffisante au fil des ans: Si les travailleurs dépendent un état partagé, j'utilise un processus de multitraitement par cœur (lié CPU), et par cœur une piscine fixe de threads de travail (I / O lié). Le système d'exploitation se chargera de assigining les différents processus de Python aux noyaux.

Le Python GIL est par interpréteur Python. Cela signifie que le seul pour éviter des problèmes avec elle tout en faisant multitraitement est simplement en train d'interprètes multiples (à savoir l'aide de processus séparés au lieu de threads pour la concurrence), puis en utilisant un autre IPC primitif pour la communication entre les processus (tels que les prises). Cela étant dit, le GIL est pas un problème lors de l'utilisation de threads avec blocage des appels d'E / S.

Le principal problème de la GIL comme mentionné plus haut est que vous ne pouvez pas exécuter 2 threads différents de code python en même temps. Un fil de blocage sur un blocage d'appel d'E / S est bloqué et ne sont donc pas exécutio code python. Cela signifie qu'il ne bloque pas le GIL. Si vous avez deux tâches intensives CPU en fils de python séparés, c'est où le GIL tue multitraitement en Python (uniquement la mise en œuvre CPython, comme l'a souligné plus haut). Parce que le GIL arrête CPU # 1 d'exécuter un fil de python tandis que CPU # 0 est occupé exécuter l'autre thread python.

Jusqu'à ce que le GIL est retiré de Python, co-routines peuvent être utilisés à la place des fils. Je l'ai sur la bonne autorité que cette stratégie a été mise en œuvre par deux démarrages réussis, en utilisant greenlets dans au moins un cas.

Ceci est une question assez ancienne mais depuis chaque fois que je recherche sur les informations relatives à python et les performances sur les systèmes multi-core ce poste est toujours sur la liste des résultats, je ne laisserais pas ce passé devant moi un ne partage pas mes pensées.

Vous pouvez utiliser le module de multitraitement qui plutôt que de créer des fils pour chaque tâche, il crée un autre processus de Compier de CPython interpréter votre code. Il serait votre application pour tirer parti des systèmes multi-cœurs. Le seul problème que je vois sur cette approche est que vous aurez un surcoût considérable en créant toute une nouvelle pile de processus sur la mémoire. ( http://en.wikipedia.org/wiki/Thread_(computing)#How_threads_differ_from_processes )

Module python multitraitement: http://docs.python.org/dev/library/multiprocessing.html

«La raison pour laquelle je ne suis pas en utilisant le module de multitraitement est que (dans ce cas) une partie du programme est le réseau fortement lié aux E / S (requêtes HTTP) afin d'avoir un pool de threads de travail est une excellente façon de presser les performances d'une boîte ... "

A ce propos, je pense que vous pouvez avoir une piscine de processus trop: http://docs.python.org/dev/library/multiprocessing.html#using-a-pool-of-workers

Att, Leo

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top