¿Cómo hago que los procesos puedan escribir en una matriz del progtwig principal?

Estoy creando un grupo de procesos y cada uno de ellos necesita escribir en diferentes partes de una matriz que existe en el progtwig principal. No existe el temor de sobrescribir la información, ya que cada proceso funcionará con diferentes filas de la matriz. ¿Cómo puedo hacer que la matriz se pueda escribir desde dentro de los procesos?

El progtwig es un multiplicador matricial que un profesor me asignó y debe ser multiprocesado. Creará un proceso para cada núcleo que tenga la computadora. El progtwig principal enviará diferentes partes de la matriz a los procesos y los computarán, luego los devolverán de una manera que pueda identificar qué respuesta corresponde a qué fila se basó.

La multiplicación de matrices significa que cada elemento de la matriz resultante se calcula por separado. Eso parece ser un trabajo para Pool . Ya que es tarea (y también para seguir el código SO), solo ilustraré el uso del Pool en sí, no la solución completa.

Entonces, tienes que escribir una rutina para calcular el elemento (i, j) -th de la matriz resultante:

def getProductElement(m1, m2, i, j): # some calculations return element 

Luego inicializas el Pool:

 from multiprocessing import Pool, cpu_count pool = Pool(processes=cpu_count()) 

Entonces tienes que enviar los trabajos. También puede organizarlos en una matriz, pero para qué molestarse, hagamos una lista.

 result = [] # here you need to iterate through the the columns of the first and the rows of # the second matrix. How you do it, depends on the implementation (how you store # the matrices). Also, make sure you check the dimensions are the same. # The simplest case is if you have a list of columns: N = len(m1) M = len(m2[0]) for i in range(N): for j in range(M): results.append(pool.apply_async(getProductElement, (m1, m2, i, j))) 

Luego llene la matriz resultante con los resultados:

 m = [] count = 0 for i in range(N): column = [] for j in range(M): column.append(results[count].get()) m.append(column) 

Una vez más, la forma exacta del código depende de cómo se representan las matrices.

¿Has intentado usar la clase multiprocessing.Array para establecer algo de memoria compartida?

Vea también el ejemplo de la documentación :

 from multiprocessing import Process, Value, Array def f(n, a): n.value = 3.1415927 for i in range(len(a)): a[i] = -a[i] if __name__ == '__main__': num = Value('d', 0.0) arr = Array('i', range(10)) p = Process(target=f, args=(num, arr)) p.start() p.join() print num.value print arr[:] 

Simplemente extiéndalo a una matriz de tamaño h*w con la indexación de i*w+j style. Luego, agregue múltiples procesos usando un Grupo de Procesos .

El costo de crear nuevos procesos o copiar matrices entre ellos si los procesos se reutilizan supera el costo de la multiplicación de matrices. De numpy.dot() modos, numpy.dot() puede utilizar diferentes núcleos de CPU por sí mismo.

La multiplicación de matrices se puede distribuir entre procesos al calcular diferentes filas del resultado en diferentes procesos, por ejemplo, dadas las matrices de entrada a y b , el elemento del resultado (i,j) es:

 out[i,j] = sum(a[i,:] * b[:,j]) 

Así que la i -fila puede ser calculada como:

 import numpy as np def dot_slice(a, b, out, i): t = np.empty_like(a[i,:]) for j in xrange(b.shape[1]): # out[i,j] = sum(a[i,:] * b[:,j]) np.multiply(a[i,:], b[:,j], t).sum(axis=1, out=out[i,j]) 

numpy matriz numpy acepta un sector como índice, por ejemplo, a[1:3,:] devuelve las filas 2 y 3.

a , b son de solo lectura, por lo que pueden heredarse como lo hacen los procesos secundarios (que explotan la copia en escritura en Linux ), el resultado se calcula utilizando una matriz compartida. Solo se copian los índices durante los cálculos:

 import ctypes import multiprocessing as mp def dot(a, b, nprocesses=mp.cpu_count()): """Perform matrix multiplication using multiple processes.""" if (a.shape[1] != b.shape[0]): raise ValueError("wrong shape") # create shared array mp_arr = mp.RawArray(ctypes.c_double, a.shape[0]*b.shape[1]) # start processes np_args = mp_arr, (a.shape[0], b.shape[1]), a.dtype pool = mp.Pool(nprocesses, initializer=init, initargs=(a, b)+np_args) # perform multiplication for i in pool.imap_unordered(mpdot_slice, slices(a.shape[0], nprocesses)): print("done %s" % (i,)) pool.close() pool.join() # return result return tonumpyarray(*np_args) 

Dónde:

 def mpdot_slice(i): dot_slice(ga, gb, gout, i) return i def init(a, b, *np_args): """Called on each child process initialization.""" global ga, gb, gout ga, gb = a, b gout = tonumpyarray(*np_args) def tonumpyarray(mp_arr, shape, dtype): """Convert shared multiprocessing array to numpy array. no data copying """ return np.frombuffer(mp_arr, dtype=dtype).reshape(shape) def slices(nitems, mslices): """Split nitems on mslices pieces. >>> list(slices(10, 3)) [slice(0, 4, None), slice(4, 8, None), slice(8, 10, None)] >>> list(slices(1, 3)) [slice(0, 1, None), slice(1, 1, None), slice(2, 1, None)] """ step = nitems // mslices + 1 for i in xrange(mslices): yield slice(i*step, min(nitems, (i+1)*step)) 

Para probarlo:

 def test(): n = 100000 a = np.random.rand(50, n) b = np.random.rand(n, 60) assert np.allclose(np.dot(a,b), dot(a,b, nprocesses=2)) 

En Linux, esta versión de multiprocesamiento tiene el mismo rendimiento que la solución que utiliza subprocesos y libera GIL (en la extensión C) durante los cálculos :

 $ python -mtimeit -s'from test_cydot import a,b,out,np' 'np.dot(a,b,out)' 100 loops, best of 3: 9.05 msec per loop $ python -mtimeit -s'from test_cydot import a,b,out,cydot' 'cydot.dot(a,b,out)' 10 loops, best of 3: 88.8 msec per loop $ python -mtimeit -s'from test_cydot import a,b; import mpdot' 'mpdot.dot(a,b)' done slice(49, 50, None) ..[snip].. done slice(35, 42, None) 10 loops, best of 3: 82.3 msec per loop 

Nota: la prueba se cambió para usar np.float64 todas partes.

Usted no

O devuelven sus ediciones en un formato que puede usar en el progtwig principal, o usa algún tipo de comunicación entre procesos para hacer que envíen sus ediciones, o usa algún tipo de almacenamiento compartido, como una base de datos o una estructura de datos. servidor como redis.