traitement en parallèle d'une matrice 3d
La méthode de la carte de python ainsi que la methode de pool.map ne peut avoir un objet d'entrée. Voir par exemple https://stackoverflow.com/a/10973817/4045774
Pour réduire les entrées à une entrée, nous pouvons utiliser par exemple functools. L'entrée qui reste doit être sur la dernière place.
from functools import partial
import numpy as np
import multiprocessing as mp
def main():
matrix3d=np.empty([10,10,1000])
matrix3d[:]=np.random.randint(10)
matrix3d_1=np.empty([10,10,1000])
x=10
y=1
pool=mp.Pool(processes=4)
func_p=partial(func,x,y)
#parallel map returns a list
res=pool.map(func_p,(matrix3d[:,:,z] for z in xrange(0,matrix3d.shape[2])))
#copy the data to array
for i in xrange(0,matrix3d.shape[2]):
matrix3d_1[:,:,i]=res[i]
def func(x,y,matrix):
return matrix*x+y
Version parallèle en utilisant numba
Cette version échelle bien sur tous les noyaux et au moins 200 fois plus rapide que multitraitement simples ci-dessus. J'ai modifié le code que vous avez lié à un peu, pour se débarrasser de toutes les dépendances que numpy.
import numpy
from numba import njit, prange
nb_meanInterp = njit("float32[:,:](float32[:,:],int64,int64)")(meanInterp)
resample_3d_nb = njit("float32[:,:,:](float32[:,:,:],int64,int64)",parallel=True)(resample_3d)
def resample_3d(matrix_3d,x,y):
matrix3d_res=numpy.empty((x,y,matrix_3d.shape[2]),dtype=numpy.float32)
for z in prange(0,matrix_3d.shape[2]):
matrix3d_res[:,:,z]=nb_meanInterp(matrix_3d[:,:,z],x,y)
return matrix3d_res
def meanInterp(data, m, n):
newData = numpy.zeros((m,n),dtype=numpy.float32)
mOrig, nOrig = data.shape
hBoundariesOrig, vBoundariesOrig = numpy.linspace(0,1,mOrig+1),
numpy.linspace(0,1,nOrig+1)
hBoundaries, vBoundaries = numpy.linspace(0,1,m+1), numpy.linspace(0,1,n+1)
for iOrig in range(mOrig):
for jOrig in range(nOrig):
for i in range(m):
if hBoundaries[i+1] <= hBoundariesOrig[iOrig]: continue
if hBoundaries[i] >= hBoundariesOrig[iOrig+1]: break
for j in range(n):
if vBoundaries[j+1] <= vBoundariesOrig[jOrig]: continue
if vBoundaries[j] >= vBoundariesOrig[jOrig+1]: break
#boxCoords = ((hBoundaries[i], vBoundaries[j]),(hBoundaries[i+1], vBoundaries[j+1]))
#origBoxCoords = ((hBoundariesOrig[iOrig], vBoundariesOrig[jOrig]),(hBoundariesOrig[iOrig+1], vBoundariesOrig[jOrig+1]))
#area=overlap(boxCoords, origBoxCoords)
#hopefully this is equivivalent (not tested)-----
T_x=(hBoundaries[i],hBoundaries[i+1],hBoundariesOrig[iOrig],hBoundariesOrig[iOrig+1])
T_y=(vBoundaries[j],vBoundaries[j+1],vBoundariesOrig[jOrig],vBoundariesOrig[jOrig+1])
tx=(T_x[1]-T_x[0]+T_x[3]-T_x[2])-(max(T_x)-min(T_x))
ty=(T_y[1]-T_y[0]+T_y[3]-T_y[2])-(max(T_y)-min(T_y))
area=tx*ty
#------------------------
newData[i][j] += area * data[iOrig][jOrig]/(hBoundaries[1] * vBoundaries[1])
return newData
Est-ce que 'matrix * x + y' est l'implémentation réelle de' func'? – Divakar
Non, 'func' n'est qu'un exemple. En fait j'utilise cette [fonction] (https://stackoverflow.com/questions/26912112/resample-2d-numpy-array-to-arbitrary-dimensions) dans la réponse. Mais je crois qu'il n'y a pas de grande différence. –
Le code que vous ne voulez pas utiliser contient des boucles imbriquées (4). Ceux-ci sont extrêmement lents en python pur. En utilisant simplement un compilateur jit, vous pouvez obtenir plus de 100x accélérer ici. En fonction de votre plate-forme (Python 2.7 et Unix ou Python 3), la parallélisation est généralement très facile à réaliser. C'est beaucoup plus que ce que vous pouvez obtenir de la parallélisation du code python pur avec le multitraitement. Jetez un coup d'oeil à ceci par exemple https://stackoverflow.com/a/45337873/4045774. Votre principale préoccupation est-elle vraiment de faire fonctionner le multitraitement python? – max9111