Python Language
Calcul parallèle
Recherche…
Remarques
En raison du GIL (Global Interpreter Lock), une seule instance de l'interpréteur python s'exécute en un seul processus. Donc, en général, l'utilisation du multi-threading n'améliore que les calculs liés aux entrées-sorties, pas ceux liés au processeur. Le module de multiprocessing
est recommandé si vous souhaitez paralléliser les tâches liées au processeur.
GIL s'applique à CPython, l'implémentation la plus populaire de Python, ainsi que PyPy. D'autres implémentations telles que Jython et IronPython n'ont pas de GIL .
Utilisation du module de multitraitement pour paralléliser des tâches
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]
Comme l'exécution de chaque appel à fib
se déroule en parallèle, le temps d'exécution de l'exemple complet est 1,8 fois plus rapide que s'il était exécuté de manière séquentielle sur un processeur double.
Python 2.2+
Utiliser les scripts Parent et Children pour exécuter du code en parallèle
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()
Ceci est utile pour les tâches de requête / réponse HTTP parallèles et indépendantes ou pour les sélections / insertions de base de données. Des arguments de ligne de commande peuvent également être donnés au script child.py . La synchronisation entre les scripts peut être réalisée par tous les scripts vérifiant régulièrement un serveur distinct (comme une instance Redis).
Utiliser une extension C pour paralléliser des tâches
L'idée ici est de déplacer les travaux intensifs en calcul vers C (en utilisant des macros spéciales), indépendamment de Python, et de faire en sorte que le code C libère le GIL pendant qu'il fonctionne.
#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args) {
...
Py_BEGIN_ALLOW_THREADS
// Threaded C code
...
Py_END_ALLOW_THREADS
...
}
Utiliser le module PyPar pour paralléliser
PyPar est une bibliothèque qui utilise l'interface de transmission de messages (MPI) pour fournir le parallélisme en Python. Un exemple simple dans PyPar (vu à https://github.com/daleroberts/pypar) ressemble à ceci:
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()