2017-08-25 5 views
2

J'ai créé un programme assez volumineux qui prend beaucoup de temps et j'ai commencé à chercher des moyens d'accélérer le programme.Exécution de Python sur plusieurs cœurs

J'ai trouvé que si j'ouvre le gestionnaire de tâches pendant l'exécution du programme, un seul cœur est utilisé.

Après quelques recherches, je trouve ce site: Why does multiprocessing use only a single core after I import numpy? qui donne une solution de os.system("taskset -p 0xff %d" % os.getpid()), mais cela ne fonctionne pas pour moi, et mon programme continue de fonctionner sur un seul noyau.

J'ai alors trouvé ceci: is python capable of running on multiple cores?, qui pointait vers l'utilisation du multitraitement.

Alors après avoir regardé multitraitement, je suis tombé sur ce documentaire sur la façon de l'utiliser https://docs.python.org/3/library/multiprocessing.html#examples

J'ai essayé le code:

from multiprocessing import Process 

def f(name): 
    print('hello', name) 

if __name__ == '__main__': 
    p = Process(target=f, args=('bob',)) 
    p.start() 
    p.join() 

a = input("Finished") 

Après l'exécution du code (pas IDLE) Il a dit ceci:

Finished 
hello bob 
Finished 

note: après avoir annoncé terminé la première fois que je pressais entrer

Donc, après cela, je suis encore plus confus et j'ai deux questions

Première: Il ne fonctionne toujours pas avec plusieurs noyaux (j'ai un 8 core Intel Core i7)

Deuxième: Pourquoi est-il fait entrée "Terminé" avant d'exécuter le code d'instruction if (et il n'est même pas encore terminé!)

+0

Oui, parce que vous avez un seul processus, il n'utilisera un seul noyau. –

+0

Aussi, utilisez-vous 'numpy'? Parce que ce lien ne semble pas pertinent. –

+0

Alors, comment est-ce que j'utiliserais plusieurs noyaux dans la situation de devoir faire beaucoup de multiplier/soustraire dans une instruction for? par exemple. 'pour chaque gamme comprise (1000): a = a * each' –

Répondre

2

Pour répondre d'abord à votre deuxième question, "Terminé" est imprimé sur le terminal car a = input("Finished") est en dehors de votre bloc de code if __name__ == '__main__':. Il s'agit donc d'une constante de niveau de module qui est affectée lors du premier chargement du module et s'exécutera avant que le code du module ne soit exécuté.

Pour répondre à la première question, vous n'avez créé qu'un processus que vous exécutez et attendez ensuite pour terminer avant de continuer. Cela vous donne zéro avantages du multitraitement et entraîne des frais généraux de création du nouveau processus. Étant donné que vous souhaitez créer plusieurs processus, vous devez créer un pool via une collection quelconque (par exemple, une liste python), puis démarrer tous les processus.

En pratique, vous devez vous soucier de plus que du nombre de processeurs (tels que la quantité de mémoire disponible, la possibilité de redémarrer les agents qui se plantent, etc.). Cependant, voici un exemple simple qui complète votre tâche ci-dessus.

import datetime as dt 
from multiprocessing import Process, current_process 
import sys 

def f(name): 
    print('{}: hello {} from {}'.format(
     dt.datetime.now(), name, current_process().name)) 
    sys.stdout.flush() 

if __name__ == '__main__': 
    worker_count = 8 
    worker_pool = [] 
    for _ in range(worker_count): 
     p = Process(target=f, args=('bob',)) 
     p.start() 
     worker_pool.append(p) 
    for p in worker_pool: 
     p.join() # Wait for all of the workers to finish. 

    # Allow time to view results before program terminates. 
    a = input("Finished") # raw_input(...) in Python 2. 

Notez également que si vous rejoignez les travailleurs immédiatement après leur départ, vous attendez pour chaque travailleur pour terminer sa tâche avant de commencer le prochain travailleur. Ceci est généralement indésirable sauf si l'ordre des tâches doit être séquentiel.

En général Mauvais

worker_1.start() 
worker_1.join() 

worker_2.start() # Must wait for worker_1 to complete before starting worker_2. 
worker_2.join() 

Habituellement désiré

worker_1.start() 
worker_2.start() # Start all workers. 

worker_1.join() 
worker_2.join() # Wait for all workers to finish. 

Pour plus d'informations, s'il vous plaît consulter les liens suivants:

+0

Réponse incroyable. +99999;) –