[PYTHON] Traitement parallèle prenant en charge plusieurs arguments et le nombre de processus spécifiés par le multitraitement [Enregistrer PDF]

Contexte

Je voulais enregistrer un graphique de certaines données de mesure (csv) au format PDF. Lorsque le nombre de données était important (1000 données), cela prenait beaucoup de temps (environ 8 minutes), j'ai donc pensé à l'améliorer.

Objectif

Je souhaite enregistrer une grande quantité de PDF à grande vitesse et éviter que le PC ne reste bloqué pendant le fonctionnement.

Méthode

J'ai principalement fait ce qui suit en utilisant python.

  1. Voir toutes les données de mesure (csv)
  2. Enregistrez toutes les données de mesure dans un tableau
  3. Lire toutes les données des conditions de mesure
  4. Boucle avec toutes les données pour chaque donnée ← Accélérez cela
  5. Recevoir les données de mesure et les conditions de mesure (arguments multiples)
  6. Dessinez avec matplot
  7. Enregistrer au format PDF

Tel quel

Boucle For normalement en python

Treading

J'avais de l'expérience dans sa mise en œuvre pour diverses raisons, alors je l'ai essayé → Il semble que la vitesse ne change pas beaucoup car ce type ne peut utiliser qu'un seul noyau. Pourtant, il est surprenant que 4 minutes changent

multiprocessing.Process

Étant donné que la fonction que je souhaite traiter en parallèle a plusieurs arguments, j'ai utilisé Process. Cependant, peu importe combien de gg j'ai fait, je ne savais pas comment limiter le nombre de threads, donc je ne pouvais pas l'implémenter. Pour cette raison, lorsque je l'ai exécuté, il a traité 1000 processus parallèles, ce qui a rendu mon PC en désordre.

multiprocessing.Pool

Il ne peut avoir qu'un seul argument, mais vous pouvez facilement spécifier le nombre de threads. Les fonctions suivantes peuvent être utilisées pour plusieurs arguments.

def wrapper(self, args):
	return self.f(*args)

codage

Le codage du multitraitement est OK si vous procédez comme suit. C'est la configuration minimale (il n'y a pas de sens de parallélisation) qui montre seulement comment coder. Pour plus de détails, reportez-vous à cet article. J'ai étudié en profondeur le traitement parallèle et le traitement parallèle de Python --Qiita

from multiprocessing import Process, Pool
import multiprocessing

def f(a, b): #Fonctions à traiter en parallèle
    print(a, end=",") #C'est juste un contrôle de fonctionnement, donc c'est simple

def wrapper(args):  #La piscine ne peut accepter qu'un seul argument, alors mordez-la et développez-la.
    f(*args)

def main():
    #Traitement parallèle par processus(Arguments multiples: o,Nombre de processus spécifié: x)
    print('Process')
    p_list = []
    for i in range(20):
        p = Process(
            target=f,
            kwargs={'a': i, 'b': 0})
        p.start()  #début
        p_list.append(p)

    for p in p_list:
        p.join()  #Attends la fin

    #Traitement parallèle par Pool(Arguments multiples: x,Nombre de processus spécifié: o)
    print('\nPool')
    p = Pool(multiprocessing.cpu_count())  #Traitement parallèle pour le nombre de CPU
    values = []

    for i in range(20):
        values.append((i, 0))
    p.map(wrapper, values)  #Développer un argument unique en plusieurs

if __name__ == "__main__":
    main()

résultat

Process
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
Pool
6,0,8,14,2,10,16,3,11,17,5,13,18,1,9,15,4,12,19,7,

Conclusion

Temps de fonctionnement

Le classement est le suivant.

  1. multitraitement (Pool limite le nombre de threads au nombre de cœurs PC) 1min 50sec
  2. multitraitement (pas de limite sur le nombre de threads) Environ 4min 30sec
  3. threading 5min 41sec
  4. Pas de parallélisation (parallélisation automatique par python? Uniquement) 9min 33sec

Considération

Comparez 1 et 2. En 1., le processus se déroulera dans l'ordre de 8 pièces.

En 2., tous les traitements (1000 traitements cette fois) seront effectués en parallèle.

―― N'est-ce pas censé être 2. plus rapide? En fait, la CPU ne peut pas traiter en parallèle en principe. Ce qui semble être un traitement parallèle ne fait que changer ce que vous faites. Par exemple, le traitement parallèle des processus 1, 2 et 3 Process 1 (exécution 1 μs) → Process 2 (exécution 1 μs) → Process 3 (exécution 1 μs) → Process 1 (exécution 1 μs à partir de la suite de l'étape précédente) → ... Il prétend juste être en parallèle. Donc Processus 1 (exécuter jusqu'à la fin) → Process 2 (exécuter jusqu'à la fin) → Process 3 (exécuter jusqu'à la fin) Cependant, en principe, l'heure ne change pas. (Quelquefois) Cependant, comme le traitement parallèle peut être effectué pour le nombre de cœurs (nombre de processeurs), le traitement sera plus rapide jusque-là.

――Pourquoi êtes-vous allé plus vite? Est-ce parce que vous pouvez utiliser beaucoup de mémoire? En 2., 1000 processus sont exécutés, donc la mémoire devient encombrée. N'est-ce pas parce qu'il s'est amélioré?

Recommended Posts

Traitement parallèle prenant en charge plusieurs arguments et le nombre de processus spécifiés par le multitraitement [Enregistrer PDF]
Traitement parallèle Python (multitraitement et Joblib)
Comment prendre plusieurs arguments lors d'un traitement parallèle à l'aide du multitraitement en python