[Python] Einfache Parallelverarbeitung mit Joblib

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.

Installation

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.

Zum Testen verwendeter Code

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.

Parallelisieren Sie mit Joblib

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)] )

Bonus: Manipulieren Sie Variablen außerhalb der Methode

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!

Schließlich

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

[Python] Einfache Parallelverarbeitung mit Joblib
Python-Parallelverarbeitung (Multiprocessing und Joblib)
Einfache parallele Ausführung mit Python-Unterprozess
Verarbeiten Sie Bilder in Python ganz einfach mit Pillow
Bildverarbeitung mit Python
Parallelverarbeitung mit Mehrfachverarbeitung
So führen Sie eine Mehrkern-Parallelverarbeitung mit Python durch
Parallele Verarbeitung ohne tiefe Bedeutung in Python
Bildverarbeitung mit Python (Teil 2)
100 Sprachverarbeitungsklopfen mit Python 2015
Parallelverarbeitung mit lokalen Funktionen
"Apple-Verarbeitung" mit OpenCV3 + Python3
[Analyse des gemeinsamen Auftretens] Einfache Analyse des gemeinsamen Auftretens mit Python! [Python]
Akustische Signalverarbeitung mit Python (2)
Einfache Ordnersynchronisation mit Python
Parallele Verarbeitung mit Parallel von Scikit-Learn
Bildverarbeitung mit Python (Teil 1)
Bildverarbeitung mit Python (3)
Einfache Python-Kompilierung mit NUITKA-Utilities
Einfacher HTTP-Server mit Python
[Python] Bildverarbeitung mit Scicit-Image
Einführung in die verteilte Parallelverarbeitung von Python durch Ray
100 Sprachverarbeitungsklopfen mit Python (Kapitel 1)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 3)
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
Einfache Python + OpenCV-Programmierung mit Canopy
Einfache Mailübertragung mit Eile Python3
Bayesianische Optimierung, die mit Python sehr einfach ist
Beispielcode-Zusammenfassung für die parallele / parallele Python-Verarbeitung
Lesen Sie Dateien parallel zu Python
Visualisieren Sie Ihre Daten ganz einfach mit Python Seaborn.
100 Bildverarbeitung mit Python Knock # 2 Graustufen
Grundlagen der binärisierten Bildverarbeitung durch Python
Bildverarbeitung mit Python 100 Knock # 10 Medianfilter
Einfache Schlüsselwortextraktion mit TermExtract für Python
[Python] Super einfacher Test mit Assert-Anweisung
[Python] Einfache Überprüfung des Argumenttyps mit Datenklasse
100 Bildverarbeitung mit Python Knock # 8 Max Pooling
Führen Sie regelmäßig eine beliebige Verarbeitung mit Python Twisted durch
Lassen Sie Heroku die Hintergrundverarbeitung mit Python durchführen
Einfache Einführung der Spracherkennung mit Python
100 Sprachverarbeitungsklopfen mit Python (Kapitel 2, Teil 2)
Bildverarbeitung mit Python & OpenCV [Tonkurve]
3. Verarbeitung natürlicher Sprache durch Python 2-1. Netzwerk für das gleichzeitige Auftreten
Bildverarbeitung mit Python 100 Knock # 12 Bewegungsfilter
3. Verarbeitung natürlicher Sprache durch Python 1-1. Word N-Gramm
[Easy Python] Lesen von Excel-Dateien mit openpyxl
100 Sprachverarbeitungsklopfen mit Python (Kapitel 2, Teil 1)
Einfache Web-App mit Python + Flask + Heroku
Zeichnen mit Matrix-Reinventor von Python Image Processing-
Die Bildverarbeitung mit Python 100 führt zu einem durchschnittlichen Pooling von # 7
[Easy Python] Lesen von Excel-Dateien mit Pandas
Einfaches Web-Scraping mit Python und Ruby
[Python] Probieren Sie mit Keras-RL ganz einfach erweitertes Lernen (DQN) aus
Leichte Bildverarbeitung mit Python x OpenCV
Bildverarbeitung mit Python 100 Knock # 9 Gauß-Filter
FizzBuzz in Python3
Scraping mit Python
Python ist einfach