Python Language
Parallele Berechnung
Suche…
Bemerkungen
Aufgrund der GIL (Global Interpretersperre) wird nur eine Instanz des Python-Interpreters in einem einzigen Prozess ausgeführt. Im Allgemeinen verbessert die Verwendung von Multithreading nur IO-gebundene Berechnungen, nicht CPU-gebundene. Das multiprocessing
Modul wird empfohlen, wenn Sie CPU-gebundene Aufgaben parallelisieren möchten.
GIL gilt für CPython, die populärste Implementierung von Python, sowie für PyPy. Andere Implementierungen wie Jython und IronPython haben keine GIL .
Verwenden des Multiprocessing-Moduls zum Parallelisieren von Aufgaben
import multiprocessing
def fib(n):
"""computing the Fibonacci in an inefficient way
was chosen to slow down the CPU."""
if n <= 2:
return 1
else:
return fib(n-1)+fib(n-2)
p = multiprocessing.Pool()
print(p.map(fib,[38,37,36,35,34,33]))
# Out: [39088169, 24157817, 14930352, 9227465, 5702887, 3524578]
Da die Ausführung jedes Aufrufs von fib
parallel ausgeführt wird, ist die Ausführungszeit des vollständigen Beispiels um das 1,8- fache schneller als bei sequentieller Ausführung auf einem Dualprozessor.
Python 2.2+
Übergeordnete und untergeordnete Skripts verwenden, um Code parallel auszuführen
Kind.py
import time
def main():
print "starting work"
time.sleep(1)
print "work work work work work"
time.sleep(1)
print "done working"
if __name__ == '__main__':
main()
parent.py
import os
def main():
for i in range(5):
os.system("python child.py &")
if __name__ == '__main__':
main()
Dies ist nützlich für parallele, unabhängige HTTP-Anforderungs- / Antworttasks oder Datenbankauswahl / -inserts. Befehlszeilenargumente können auch an das child.py- Skript übergeben werden. Die Synchronisation zwischen den Skripts kann erreicht werden, indem alle Skripts regelmäßig einen separaten Server (wie eine Redis-Instanz) überprüfen.
Verwendung einer C-Erweiterung zum Parallelisieren von Aufgaben
Die Idee dabei ist, die rechenintensiven Jobs (mit speziellen Makros) unabhängig von Python nach C zu verschieben und den GIL während der Arbeit mit dem C-Code freizugeben.
#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args) {
...
Py_BEGIN_ALLOW_THREADS
// Threaded C code
...
Py_END_ALLOW_THREADS
...
}
Verwenden des PyPar-Moduls zum Parallelisieren
PyPar ist eine Bibliothek, die die Message Passing-Schnittstelle (MPI) verwendet, um Parallelität in Python bereitzustellen. Ein einfaches Beispiel in PyPar (wie auf https://github.com/daleroberts/pypar zu sehen) sieht folgendermaßen aus:
import pypar as pp
ncpus = pp.size()
rank = pp.rank()
node = pp.get_processor_name()
print 'I am rank %d of %d on node %s' % (rank, ncpus, node)
if rank == 0:
msh = 'P0'
pp.send(msg, destination=1)
msg = pp.receive(source=rank-1)
print 'Processor 0 received message "%s" from rank %d' % (msg, rank-1)
else:
source = rank-1
destination = (rank+1) % ncpus
msg = pp.receive(source)
msg = msg + 'P' + str(rank)
pypar.send(msg, destination)
pp.finalize()