Python ist [GIL (Global Interpolator Lock)](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3% 83% AB% E3% 82% A4% E3% 83% B3% E3% 82% BF% E3% 83% 97% E3% 83% AA% E3% 82% BF% E3% 83% AD% E3% 83% 83% E3% 82% AF) wird angewendet. Wenn Sie über mehrere CPU-Kerne verfügen, können Sie nicht alle Ressourcen verwenden, indem Sie einfach den Code schreiben.
Wenn Sie jedoch eine große Datenmenge verarbeiten, möchten Sie manchmal alle CPU-Ressourcen des Computers verwenden, um Berechnungen so schnell wie möglich durchzuführen.
Mit Schlüsselwörtern wie Python-Parallelverarbeitung Wenn Sie suchen, können Sie häufig die Erklärung von Multiprocessing-Modul in der Standardbibliothek sehen, daher denke ich, dass viele Leute dies verwenden. ..
Ich würde dieses Modul gerne verwenden, wenn ich ein System mit paralleler Verarbeitung erstelle, aber ehrlich gesagt ist es ein wenig mühsam, wenn ich nur verlassenen Code schreibe ...
Daher möchte ich ein Modul namens Joblib vorstellen, das die parallele Verarbeitung einfacher und schneller ausführen kann.
Ganz zu schweigen von der reduzierten Menge an Code als einem weiteren Vorteil
Und so weiter. Alle sind sehr nützlich für mich, weil ich sie selbst in Multiprocessing implementieren muss.
Erstens ist die Installation. Es ist ein Schuss mit Pip. Die Version zum Zeitpunkt des Schreibens dieses Artikels ist 0.9.3.
pip install joblib
Successfully installed joblib-0.9.3
Die für den Test verwendete Umgebung ist MacBook Pro mit 4 virtuellen Kernen und 2 physischen Kernen.
Um die Berechnungszeiten einfach zu vergleichen, testen Sie mit Code wie dem folgenden. Der Berechnungsinhalt selbst hat keine besondere Bedeutung.
Wiederholen Sie zunächst eine einfache Berechnung, messen Sie die Berechnungszeit mit dem Zeitmodul und zeigen Sie sie an.
# -*- coding: utf-8 -*-
from time import time
def process(n):
return sum([i*n for i in range(100000)])
start = time()
#Iterative Berechnung
total = 0
for i in range(10000):
total += process(i)
print(total)
print('{}Es dauerte eine Sekunde'.format(time() - start))
249972500250000000
78.Es dauerte 2647480965 Sekunden
Die Antwort auf die Berechnung lautet 249972500250000000, was 78 Sekunden dauert.
Lassen Sie uns nur den iterativen Berechnungsteil des obigen Codes ändern und parallelisieren. Die Mehrprozessparallelisierung kann durch Kombination von Parallel und Verzögerung erreicht werden.
# -*- coding: utf-8 -*-
from joblib import Parallel, delayed
from time import time
def process(n):
return sum([i*n for i in range(100000)])
start = time()
#Iterative Berechnung(Parallelisierung)
r = Parallel(n_jobs=-1)( [delayed(process)(i) for i in range(10000)] )
print(sum(r))
print('{}Es dauerte eine Sekunde'.format(time() - start))
249972500250000000
37.5521140099 nahm
Es wurde auf 37 Sekunden verkürzt! Die Antwort auf die Berechnung ist ebenfalls richtig. Ich konnte die Berechnungszeit schnell verkürzen, indem ich einen Teil des Codes neu schrieb.
Das parallele Argument n_jobs gibt die Anzahl der zu verwendenden Kerne an. Wenn Sie dies auf -1 setzen, wird es immer mit der maximalen Anzahl von Kernen ausgeführt, die verwendet werden können.
Wenn Sie 1 festlegen, entspricht dies der Ausführung ohne Parallelisierung, sodass die Wiederherstellung einfach ist. Es scheint kein Problem zu geben, selbst wenn der iterative Prozess grundsätzlich parallel geschrieben ist.
Wenn Sie im ausführlichen Argument einen numerischen Wert von 0 bis 10 angeben, wird der Fortschritt entsprechend der angegebenen Häufigkeit ausgegeben. (0 bedeutet keine Ausgabe, 10 ist am häufigsten)
r = Parallel(n_jobs=-1, verbose=10)( [delayed(process)(i) for i in range(10000)] )
Im obigen Codebeispiel kann auf eine Variable verwiesen werden, die in einem externen Bereich innerhalb der parallel ausgeführten Prozessmethode vorhanden ist, es ist jedoch nicht möglich, einen neuen Wert zuzuweisen. Dies liegt daran, dass der Speicherbereich, auf den verwiesen werden kann, für jeden Prozess unterschiedlich ist.
Der folgende Code funktioniert normal, aber der parallelisierte Code verursacht einen Fehler und kann nicht ausgeführt werden.
#Referenzieren und Bearbeiten der externen Variablennummer innerhalb der Prozessmethode
number = 0
def process(n):
number = 3.14
return sum([i*n for i in range(100000)])
Um dies zu lösen, muss eine Variable erstellt werden, die einen Speicherbereich zwischen Prozessen teilt. Es wird im Multiprocessing-Modul bereitgestellt. Verwenden wir es also.
Der obige Code kann wie folgt realisiert werden.
# -*- coding: utf-8 -*-
from joblib import Parallel, delayed
from multiprocessing import Value, Array
shared_int = Value('i', 1)
def process(n):
shared_int.value = 3.14
return sum([i*n for i in range(100000)])
#Iterative Berechnung(Parallelisierung)
Parallel(n_jobs=-1)( [delayed(process)(i) for i in range(10000)] )
print(shared_int.value)
3.14
Mit der Value-Klasse können Sie Zahlen wie int und double als gemeinsam genutzte Variablen vorbereiten. Bitte beachten Sie, dass der Typ mit dem ersten Argument im Voraus angegeben werden muss.
Es ist auch möglich, eine Liste der angegebenen Typen mit "Array ('d', [0.0, 0.0, 0.0])" zu erstellen.
Es scheint nützlich zu sein, wenn Sie Ihren eigenen benutzerdefinierten Fortschritt anzeigen möchten!
Ich war überrascht, dass ich es reibungslos implementieren konnte, als ich versuchte, parallel mit Python zu verarbeiten.
Der Autor veröffentlicht täglich verschiedene technische Informationen auf Twitter. Ich wäre Ihnen dankbar, wenn Sie mir folgen könnten.
https://twitter.com/YuhsakInoue
Recommended Posts