Python Language
Parallelle berekening
Zoeken…
Opmerkingen
Vanwege de GIL (Global interpreter lock) wordt slechts één exemplaar van de python-interpreter in één proces uitgevoerd. Dus in het algemeen verbetert het gebruik van multi-threading alleen IO-gebonden berekeningen, niet CPU-gebonden berekeningen. De multiprocessing
module wordt aanbevolen als u CPU-gebonden taken wilt parallelliseren.
GIL is van toepassing op CPython, de meest populaire implementatie van Python, evenals PyPy. Andere implementaties zoals Jython en IronPython hebben geen GIL .
De multiprocessing-module gebruiken om taken te parallelliseren
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]
Omdat de uitvoering van elke oproep tot fib
parallel plaatsvindt, is de uitvoeringstijd van het volledige voorbeeld 1,8 x sneller dan wanneer dit op een sequentiële manier op een dubbele processor wordt gedaan.
Python 2.2+
Parent and Children-scripts gebruiken om code parallel uit te voeren
child.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()
Dit is handig voor parallelle, onafhankelijke HTTP-aanvraag / antwoordtaken of Databaseselectie / invoegingen. Er kunnen ook opdrachtregelargumenten aan het child.py- script worden gegeven. Synchronisatie tussen scripts kan worden bereikt door alle scripts regelmatig een afzonderlijke server te laten controleren (zoals een Redis-instantie).
Een C-extensie gebruiken om taken te parallelliseren
Het idee hier is om de rekenintensieve taken naar C te verplaatsen (met behulp van speciale macro's), onafhankelijk van Python, en de C-code de GIL te laten vrijgeven terwijl deze werkt.
#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args) {
...
Py_BEGIN_ALLOW_THREADS
// Threaded C code
...
Py_END_ALLOW_THREADS
...
}
Met behulp van de PyPar-module om te parallelliseren
PyPar is een bibliotheek die de Message Passing Interface (MPI) gebruikt om parallelliteit in Python te bieden. Een eenvoudig voorbeeld in PyPar (te zien op https://github.com/daleroberts/pypar) ziet er als volgt uit:
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()