Python Language
Calcolo parallelo
Ricerca…
Osservazioni
A causa del GIL (Global interpreter lock), solo un'istanza dell'interprete python viene eseguita in un singolo processo. Quindi, in generale, l'utilizzo di multi-threading migliora solo i calcoli associati all'IO, non quelli legati alla CPU. Il modulo multiprocessing
è consigliato se si desidera parallelizzare le attività legate alla CPU.
GIL si applica a CPython, l'implementazione più popolare di Python, oltre a PyPy. Altre implementazioni come Jython e IronPython non hanno GIL .
Utilizzo del modulo multiprocessing per parallelizzare le attività
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]
Poiché l'esecuzione di ogni chiamata a fib
avviene in parallelo, il tempo di esecuzione dell'esempio completo è 1,8 × più veloce rispetto a se eseguito in modo sequenziale su un processore doppio.
Python 2.2+
Utilizzo degli script padre e figlio per eseguire il codice in parallelo
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()
Questo è utile per attività di richiesta / risposta HTTP parallele e indipendenti o selezione / inserimenti del database. Gli argomenti della riga di comando possono essere dati anche allo script child.py . La sincronizzazione tra gli script può essere ottenuta da tutti gli script che controllano regolarmente un server separato (come un'istanza Redis).
Utilizzo di un'estensione C per parallelizzare le attività
L'idea qui è di spostare i lavori ad alta intensità di calcolo su C (usando macro speciali), indipendentemente da Python, e rilasciare il codice C al GIL mentre funziona.
#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args) {
...
Py_BEGIN_ALLOW_THREADS
// Threaded C code
...
Py_END_ALLOW_THREADS
...
}
Utilizzando il modulo PyPar per parallelizzare
PyPar è una libreria che utilizza l'interfaccia di passaggio dei messaggi (MPI) per fornire il parallelismo in Python. Un semplice esempio in PyPar (come visto su https://github.com/daleroberts/pypar) assomiglia a questo:
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()