Einfache parallele Ausführung mit Python-Unterprozess

-Ich möchte eine große Datenmenge parallel verarbeiten. -Ich möchte die CPU effektiv nutzen, da sie viele Kerne hat. -Ich habe vorerst versucht, das Skript zu schreiben, aber ich kann es mir nicht leisten, es für die parallele Ausführung neu zu schreiben.

Ich habe verschiedene Dinge recherchiert und es schien einfach zu sein, subprocess.Popen () zu verwenden, also habe ich experimentiert.

Referenzartikel https://qiita.com/HidKamiya/items/e192a55371a2961ca8a4

Ausführungsumgebung und Beispielcode für den Lasttest

Windows 10 (64bit) Python 3.7.6

Die CPU ist Ryzen 9 3950X und dies ist die Umgebung. タスク マネージャー 2020_06_27 20_15_14.png

Experimentieren Sie mit dem folgenden Code. (Zeigen Sie nur die letzten beiden Ziffern der durch das Befehlszeilenargument angegebenen Fibonacci-Zahlenspalte an.)

fib_sample.py


import sys

def fib(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

if __name__ == "__main__":
    num = int(sys.argv[1])
    result = fib(num)
    print("n = {0}, result % 100 = {1}".format(num, result % 100))

Wenn Sie beispielsweise "python fib_sample.py 10000" ausführen, wird "n = 10000", das Ergebnis% 100 = 75 "angezeigt und beendet.

Nacheinander ausführen

Versuchen Sie zunächst, es nacheinander mit subprocess.run () auszuführen. Führen Sie Python mit einem Argument in "subprocess.run ([" Python ", r". \ Fib_sample.py ", str (500000 + i)])" aus. Wenn Sie das Befehlszeilenargument von 500000 in 500063 ändern und 64 Mal ausführen,

batch_sequential.py


from time import time
import subprocess

start=time()

loop_num = 64
for i in range(loop_num):
    subprocess.run(['python', r".\fib_sample.py", str(500000 + i)])

end=time()
print("%f sec" %(end-start))
> python .\batch_sequential.py
n = 500000, result % 100 = 25
n = 500001, result % 100 = 26
n = 500002, result % 100 = 51
(Weggelassen)
n = 500061, result % 100 = 86
n = 500062, result % 100 = 31
n = 500063, result % 100 = 17
130.562213 sec

Es dauerte etwas mehr als zwei Minuten. Offensichtlich wird der CPU-Kern überhaupt nicht verwendet. タスク マネージャー 2020_06_27 20_12_28.png

Parallele Ausführung

Versuchen Sie, denselben Prozess parallel zu subprocess.Popen () auszuführen. Im Gegensatz zu subprocess.run () wartet subprocess.Popen () nicht auf den Abschluss des erzeugten Prozesses. Der folgende Code wiederholt die Prozessausführung → Warten Sie, bis alle abgeschlossen sind → Die nächste Prozessausführung → ... für die von max_process angegebene Nummer.

batch_parallel.py


from time import time
import subprocess

start=time()

#Maximale Anzahl paralleler Prozessausführungen
max_process = 16
proc_list = []

loop_num = 64
for i in range(loop_num):
    proc = subprocess.Popen(['python', r".\fib_sample.py", str(500000 + i)])
    proc_list.append(proc)
    if (i + 1) % max_process == 0 or (i + 1) == loop_num:
        #max_Warten Sie für jeden Prozess auf das Ende aller Prozesse
        for subproc in proc_list:
            subproc.wait()
        proc_list = []

end=time()
print("%f sec" %(end-start))

Das Ergebnis der parallelen Ausführung von 16 entsprechend der Anzahl der physischen Kerne von Ryzen 3950X.

> python .\batch_parallel.py
n = 500002, result % 100 = 51
n = 500004, result % 100 = 28
n = 500001, result % 100 = 26
(Weggelassen)
n = 500049, result % 100 = 74
n = 500063, result % 100 = 17
n = 500062, result % 100 = 31
8.165289 sec

Da sie parallel ausgeführt werden, ist die Reihenfolge, in der die Verarbeitung endet, nicht in der richtigen Reihenfolge. Es war fast 16-mal schneller von 130,562 Sekunden auf 8,165 Sekunden.

Sie können sehen, dass alle Kerne verwendet werden und parallel parallel korrekt ausgeführt werden. タスク マネージャー 2020_06_27 20_22_37.png

Übrigens ist es nicht schnell, 32 parallel nach der Anzahl der logischen Kerne anstelle der Anzahl der physischen Kerne auszuführen. Eher manchmal wird es spät. Die folgende Grafik zeigt die durchschnittliche Ausführungszeit, wenn die Anzahl der parallelen Ausführungen jeweils dreimal geändert und ausgeführt wird. プレゼンテーション1.png Ich habe verschiedene Anwendungen im Hintergrund ausgeführt, daher ist dies nicht sehr genau, aber ich denke, der Trend ist korrekt.

Zusammenfassung

Es war ziemlich einfach zu beschleunigen. Mit dem obigen Code wartet er nach dem Start der parallelen Ausführung auf das Ende des Prozesses mit der längsten Verarbeitungszeit. Wenn es also einen Prozess mit einer langen Verarbeitungszeit gibt, erhöht sich der Aufwand für das Warten auf das Ende dieses Prozesses. Ursprünglich denke ich, dass der Code den nächsten Prozess starten sollte, sobald jeder Prozess die Ausführung beendet hat, und den Code so gestalten sollte, dass die Anzahl der Parallelen immer konstant ist. In der Realität bestand der Zweck jedoch darin, Anwendungen wie das Anwenden einer großen Anzahl von Datendateien derselben Länge auf dieselbe Signalverarbeitung zu beschleunigen. Daher schloss ich meine Augen mit der Erwartung, dass die Ausführungszeit ungefähr gleich sein würde. Vorerst war ich zufrieden, weil ich den Zweck der Beschleunigung leicht erreichen konnte.

Recommended Posts

Einfache parallele Ausführung mit Python-Unterprozess
[Python] Einfache Parallelverarbeitung mit Joblib
[Analyse des gemeinsamen Auftretens] Einfache Analyse des gemeinsamen Auftretens mit Python! [Python]
Einfache Ordnersynchronisation mit Python
Messung der Ausführungszeit mit Python With
Einfache Python-Kompilierung mit NUITKA-Utilities
Einfacher HTTP-Server mit Python
Python-Memorandum zur parallelen / asynchronen Ausführung
Einfache Python + OpenCV-Programmierung mit Canopy
Bayesianische Optimierung, die mit Python sehr einfach ist
Lesen Sie Dateien parallel zu Python
Visualisieren Sie Ihre Daten ganz einfach mit Python Seaborn.
Einfache Schlüsselwortextraktion mit TermExtract für Python
[Python] Super einfacher Test mit Assert-Anweisung
[Python] Einfache Überprüfung des Argumenttyps mit Datenklasse
Einfache Einführung der Spracherkennung mit Python
[Easy Python] Lesen von Excel-Dateien mit openpyxl
Verarbeiten Sie Bilder in Python ganz einfach mit Pillow
[Easy Python] Lesen von Excel-Dateien mit Pandas
Einfaches Web-Scraping mit Python und Ruby
Parallele Taskausführung mit concurrent.futures in Python
[Python] Probieren Sie mit Keras-RL ganz einfach erweitertes Lernen (DQN) aus
FizzBuzz in Python3
Scraping mit Python
Python ist einfach
Statistik mit Python
Scraping mit Python
Python mit Go
Twilio mit Python
In Python integrieren
Spielen Sie mit 2016-Python
AES256 mit Python
Getestet mit Python
Python beginnt mit ()
mit Syntax (Python)
Bingo mit Python
Zundokokiyoshi mit Python
Excel mit Python
Mikrocomputer mit Python
Mit Python besetzen
[Python] Einfache Einführung in das maschinelle Lernen mit Python (SVM)
Bereiten Sie die Ausführungsumgebung von Python3 mit Docker vor
Beenden Sie die Python-Ausführung mit Strg-C (reagiert auf SIGINT)
So messen Sie die Ausführungszeit mit Python Teil 1
Parallele Verarbeitung ohne tiefe Bedeutung in Python
Einfache LASSO-Regressionsanalyse mit Python (keine Theorie)
Erstellen Sie eine Python-Ausführungsumgebung mit VS-Code
So messen Sie die Ausführungszeit mit Python Part 2
✨ Einfach mit Python ☆ Geschätzte verstrichene Zeit nach dem Tod ✨
Serielle Kommunikation mit Python
Zip, entpacken mit Python
Django 1.11 wurde mit Python3.6 gestartet
Primzahlbeurteilung mit Python
Socket-Kommunikation mit Python
Datenanalyse mit Python 2
Easy Grad-CAM mit Pytorch-Gradcam
Versuchen Sie es mit Python.
Python lernen mit ChemTHEATER 03