Je voudrais utiliser un tableau numpy en mémoire partagée pour une utilisation avec le module multitraitement. La difficulté est de l'utiliser comme un tableau numpy, et pas seulement comme un tableau ctypes.
from multiprocessing import Process, Array
import scipy
def f(a):
a[0] = -a[0]
if __name__ == '__main__':
# Create the array
N = int(10)
unshared_arr = scipy.rand(N)
arr = Array('d', unshared_arr)
print "Originally, the first two elements of arr = %s"%(arr[:2])
# Create, start, and finish the child processes
p = Process(target=f, args=(arr,))
p.start()
p.join()
# Printing out the changed values
print "Now, the first two elements of arr = %s"%arr[:2]
Cela produit une sortie telle que:
Originally, the first two elements of arr = [0.3518653236697369, 0.517794725524976]
Now, the first two elements of arr = [-0.3518653236697369, 0.517794725524976]
Le tableau peut être accédé de manière ctypes, par exemple a du arr[i]
sens. Cependant, ce n'est pas un tableau numpy et je ne peux pas effectuer d'opérations telles que -1*arr
, ou arr.sum()
. Je suppose qu'une solution serait de convertir le tableau ctypes en un tableau numpy. Cependant (en plus de ne pas pouvoir faire ce travail), je ne crois pas que ce serait plus partagé.
Il semble qu'il y aurait une solution standard à ce qui doit être un problème commun.
python
numpy
multiprocessing
shared
Ian Langmore
la source
la source
subprocess
plutôt quemultiprocessing
.Réponses:
À ajouter aux réponses de @ unutbu (plus disponible) et de @Henry Gomersall. Vous pouvez utiliser
shared_arr.get_lock()
pour synchroniser l'accès en cas de besoin:Exemple
Si vous n'avez pas besoin d'un accès synchronisé ou si vous créez vos propres verrous, ce
mp.Array()
n'est pas nécessaire. Vous pouvez utilisermp.sharedctypes.RawArray
dans ce cas.la source
count
ànumpy.frombuffer()
. Vous pouvez essayer de le faire à un niveau inférieur en utilisantmmap
ou quelque chose commeposix_ipc
directement pour implémenter un analogique RawArray redimensionnable (peut impliquer une copie lors du redimensionnement) (ou rechercher une bibliothèque existante). Ou si votre tâche le permet: copiez les données par parties (si vous n'en avez pas besoin en même temps). "Comment redimensionner une mémoire partagée" est une bonne question distincte.Pool()
définit le nombre de processus (le nombre de cœurs CPU disponibles est utilisé par défaut).M
est le nombre de fois que laf()
fonction est appelée.L'
Array
objet a uneget_obj()
méthode qui lui est associée, qui retourne le tableau ctypes qui présente une interface de tampon. Je pense que ce qui suit devrait fonctionner ...Lorsqu'il est exécuté, cela imprime le premier élément d'
a
être maintenant 10.0, montranta
etb
sont juste deux vues dans la même mémoire.Afin de vous assurer qu'il est toujours sécurisé pour le multiprocesseur, je pense que vous devrez utiliser les méthodes
acquire
etrelease
qui existent sur l'Array
objeta
, et son verrou intégré pour vous assurer que tout est accessible en toute sécurité (bien que je ne sois pas un expert sur le module multiprocesseur).la source
mp.Array
.Bien que les réponses déjà données soient bonnes, il existe une solution beaucoup plus simple à ce problème à condition que deux conditions soient remplies:
Dans ce cas, vous n'avez pas besoin de jouer avec le partage explicite des variables, car les processus enfants seront créés à l'aide d'un fork. Un enfant forké partage automatiquement l'espace mémoire du parent. Dans le contexte du multitraitement Python, cela signifie qu'il partage toutes les variables au niveau du module ; notez que cela ne vaut pas pour les arguments que vous passez explicitement à vos processus enfants ou aux fonctions que vous appelez sur un
multiprocessing.Pool
ou deux.Un exemple simple:
la source
J'ai écrit un petit module python qui utilise la mémoire partagée POSIX pour partager des tableaux numpy entre des interpréteurs python. Peut-être que vous le trouverez pratique.
https://pypi.python.org/pypi/SharedArray
Voici comment ça fonctionne:
la source
Vous pouvez utiliser le
sharedmem
module: https://bitbucket.org/cleemesser/numpy-sharedmemVoici donc votre code d'origine, cette fois en utilisant la mémoire partagée qui se comporte comme un tableau NumPy (notez la dernière instruction supplémentaire appelant une
sum()
fonction NumPy ):la source