2010-06-25 5 views
5

J'ai décidé d'apprendre comment le multi-threading est fait en Python, et j'ai fait une comparaison pour voir quel genre de gain de performance je pourrais obtenir sur un processeur dual-core. J'ai trouvé que mon code multithread simple s'exécute plus lentement que l'équivalent séquentiel, et je n'arrive pas à comprendre pourquoi.Thread Python de manière inattendue plus lent

Le test que je parvins était de générer une grande liste de nombres aléatoires, puis imprimer le maximum

from random import random 
import threading 

def ox(): 
    print max([random() for x in xrange(20000000)]) 

ox() prend environ 6 secondes pour terminer sur mon processeur Intel Core 2 Duo, alors que ox();ox() prend environ 12 secondes. J'ai ensuite essayé d'appeler ox() à partir de deux threads pour voir à quelle vitesse cela se terminerait.

def go(): 
    r = threading.Thread(target=ox) 
    r.start() 
    ox() 

go() prend environ 18 secondes pour achever, avec l'impression de deux résultats à moins de 1 seconde de eachother. Pourquoi cela devrait-il être plus lent? ox() Je pense que ox() est parallélisé automatiquement, parce que si je regarde l'onglet de performance du gestionnaire de tâches Windows, et appelez ox() dans ma console python, les deux processeurs sautent à environ 75% d'utilisation jusqu'à ce qu'il se termine. Est-ce que Python parallélise automatiquement des choses comme max() quand c'est possible?

Répondre

9
  1. Python a le GIL. Le bytecode Python ne sera exécuté que par un seul processeur à la fois. Seuls certains modules C (qui ne gèrent pas l'état Python) pourront s'exécuter simultanément.
  2. Le Python GIL a un énorme coût de verrouillage de l'état entre les threads. Il y a des correctifs pour cela dans les nouvelles versions ou dans les branches de développement - ce qui devrait à tout le moins rendre le code lié au processeur multi-thread aussi rapide qu'un code à un seul thread.

Vous devez utiliser une structure multi-processus pour paralléliser avec Python. Heureusement, le module multiprocessing livré avec Python rend cela assez facile.

Très peu de langages peuvent auto-paralléliser des expressions. Si c'est la fonctionnalité que vous voulez, je suggère Haskell (Data Parallel Haskell)

+5

Il est à noter que le threading est toujours utile en Python pour certains types de tâches, tels que les opérations liées aux E/S. –

1

Le problème est dans la fonction random() Si vous supprimez aléatoire de votre code. Les deux cœurs essayent d'accéder à l'état partagé de la fonction aléatoire. Les cores fonctionnent de manière conséquente et ont passé beaucoup de temps sur la synchronisation des caches. Un tel comportement est appelé partage faux. Lire cet article False Sharing

Questions connexes