2016-08-26 1 views
4

J'ai le code ci-dessous:Python multithreading vs multitraitement vs exécution séquentielle

import time 
from threading import Thread 
from multiprocessing import Process 

def fun1(): 

for _ in xrange(10000000): 
     print 'in fun1' 
     pass 

def fun2(): 

for _ in xrange(10000000): 
     print 'in fun2' 
     pass 

def fun3(): 

for _ in xrange(10000000): 
     print 'in fun3' 
     pass 

def fun4(): 

for _ in xrange(10000000): 
     print 'in fun4' 
     pass 

if __name__ == '__main__': 

    #t1 = Thread(target=fun1, args=()) 
    t1 = Process(target=fun1, args=()) 
    #t2 = Thread(target=fun2, args=()) 
    t2 = Process(target=fun2, args=()) 
    #t3 = Thread(target=fun3, args=()) 
    t3 = Process(target=fun3, args=()) 
    #t4 = Thread(target=fun4, args=()) 
    t4 = Process(target=fun4, args=()) 
    t1.start() 
    t2.start() 
    t3.start() 
    t4.start() 
    start = time.clock() 
    t1.join() 
    t2.join() 
    t3.join() 
    t4.join() 
    end = time.clock() 
    print("Time Taken = ",end-start) 

    ''' 
    start = time.clock() 
    fun1() 
    fun2() 
    fun3() 
    fun4() 
    end = time.clock() 
    print("Time Taken = ",end-start) 
    ''' 

Je courais le programme ci-dessus de trois façons:

  • Première exécution séquentielle ALONE (regardez le code commenté et commentaire le code supérieur)
  • Deuxième exécution multithread ALONE
  • Troisième exécution multitraitement ALONE

Les observations pour le temps end_time démarrage sont les suivantes:

temps de course global

  • ('Taken = Temps', 342,5981313667716) --- Durée par exécution filetée
  • ('Time Taken =', 232.94691744899296) --- Durée de fonctionnement Exécution séquentielle
  • ('Time Taken =', 307,91093406618216) --- Durée par multitraitement exécution

Question:

Je vois l'exécution séquentielle prend moins de temps et multithreading prend le plus de temps . Pourquoi? Je suis incapable de comprendre et également surpris par les résultats. Veuillez clarifier. Comme il s'agit d'une tâche gourmande en ressources processeur et que GIL est acquis, ma compréhension était Le multitraitement prendrait moins de temps alors que l'exécution par thread prendrait le plus de temps. Veuillez valider ma compréhension.

Répondre

5

Vous utilisez time.clock, ce qui vous donne le temps CPU et non le temps réel: vous ne pouvez pas l'utiliser dans votre cas, car il vous donne le temps d'exécution (combien de temps avez-vous utilisé le CPU pour exécuter votre code, presque en même temps pour chacun de ces cas)

Exécution de votre code avec time.time() au lieu de time.clock m'a donné ces temps sur mon ordinateur:

Process : ('Time Taken = ', 5.226783990859985) 
seq : ('Time Taken = ', 6.3122560000000005) 
Thread : ('Time Taken = ', 17.10062599182129) 

la tâche donnée ici (impression) est si rapide que la l'accélération de l'utilisation du multitraitement est presque équilibrée par le surdébit. Pour Threading, comme vous ne pouvez avoir qu'un seul thread en cours d'exécution à cause du GIL, vous finissez par exécuter toutes vos fonctions séquentiellement MAIS vous avez la surcharge du threading (changer les threads chaque fois que plusieurs itérations peuvent coûter jusqu'à plusieurs millisecondes à chaque fois) . Donc, vous vous retrouvez avec quelque chose de beaucoup plus lent.

Threading est utile si vous avez des temps d'attente, de sorte que vous pouvez exécuter des tâches entre les deux.

Multiprocessing est utile pour des tâches coûteuses en calcul, si possible complètement indépendantes (pas de variables partagées). Si vous avez besoin de partager des variables, vous devez faire face au GIL et c'est un peu plus compliqué (mais pas impossible la plupart du temps).

EDIT: En fait, en utilisant time.clock comme vous l'avez fait, vous avez obtenu des informations sur la quantité de frais généraux en utilisant Threading et .

0

Fondamentalement, vous avez raison. Quelle plate-forme utilisez-vous pour exécuter l'extrait de code? Je suppose que Windows. Notez que "print" n'est pas lié à la CPU alors vous devriez commenter "print" et essayer de l'exécuter sous Linux pour voir la différence (ça devrait être ce que vous attendez). Utilisez le code comme ceci:

def fun1(): 

for _ in xrange(10000000): 
     # No print, and please run on linux 
     pass