Tratando de nuevo como acabo de ver la generosidad;)
Básicamente creo que el mensaje de error significa lo que dijo - multiprocesamiento compartida matrices de memoria no puede pasado como argumentos (por decapado). No tiene sentido serializar los datos; el punto es que los datos son memoria compartida. Entonces tienes que hacer que la matriz compartida sea global. Creo que es mejor ponerlo como el atributo de un módulo, como en mi primera respuesta, pero simplemente dejarlo como una variable global en tu ejemplo también funciona bien. Tomando en cuenta su punto de no querer establecer los datos antes del tenedor, aquí hay un ejemplo modificado. Si quisiera tener más de una posible matriz compartida (y es por eso que quería pasar aShare como argumento) podría hacer una lista global de matrices compartidas, y simplemente pasar el índice a count_it (que se convertiría en for c in toShare[i]:
).
from sys import stdin
from multiprocessing import Pool, Array, Process
def count_it(key):
count = 0
for c in toShare:
if c == key:
count += 1
return count
if __name__ == '__main__':
# allocate shared array - want lock=False in this case since we
# aren't writing to it and want to allow multiple processes to access
# at the same time - I think with lock=True there would be little or
# no speedup
maxLength = 50
toShare = Array('c', maxLength, lock=False)
# fork
pool = Pool()
# can set data after fork
testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"
if len(testData) > maxLength:
raise ValueError, "Shared array too small to hold data"
toShare[:len(testData)] = testData
print pool.map(count_it, ["a", "b", "s", "d"])
[EDIT: Lo anterior no funciona en las ventanas, porque de no usar tenedor. Sin embargo, el siguiente no funciona en Windows, sigue utilizando la piscina, así que creo que esto es lo más cercano a lo que quiere:
from sys import stdin
from multiprocessing import Pool, Array, Process
import mymodule
def count_it(key):
count = 0
for c in mymodule.toShare:
if c == key:
count += 1
return count
def initProcess(share):
mymodule.toShare = share
if __name__ == '__main__':
# allocate shared array - want lock=False in this case since we
# aren't writing to it and want to allow multiple processes to access
# at the same time - I think with lock=True there would be little or
# no speedup
maxLength = 50
toShare = Array('c', maxLength, lock=False)
# fork
pool = Pool(initializer=initProcess,initargs=(toShare,))
# can set data after fork
testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"
if len(testData) > maxLength:
raise ValueError, "Shared array too small to hold data"
toShare[:len(testData)] = testData
print pool.map(count_it, ["a", "b", "s", "d"])
No sé por qué mapa no se Conserve en vinagre la matriz, pero Proceso y piscina habrá - Creo quizás se haya transferido en el punto de la inicialización del subproceso en Windows. Tenga en cuenta que los datos aún están configurados después de la horquilla.
Desafortunadamente eso no es posible. La forma recomendada según la documentación de mp es usar inheritence (en plataformas fork). Para los datos de solo lectura que tiene aquí, uno normalmente usaría un global, pero puede usar una matriz compartida para la comunicación de lectura/escritura. La bifurcación es barata, por lo que puede recrear el Pool cada vez que recibe los datos, luego ciérrelo. Desafortunadamente, en Windows esto no es posible: la solución consiste en utilizar una matriz de memoria compartida (incluso en el caso de solo lectura) pero esto solo se puede pasar a los subprocesos en la creación del proceso (imagino que deben agregarse a la lista de acceso) ... – robince
para el segmento de memoria compartida y que esta lógica no se implementa excepto en el inicio del subproceso). Puede pasar la matriz de datos compartidos en el inicio del grupo como lo mostré, o a un proceso de manera similar. No puede pasar una matriz de memoria compartida a un grupo abierto; debe crear el grupo después de la memoria. Maneras fáciles de solucionar esto incluyen asignar un búfer de tamaño máximo, o simplemente asignar el arreglo cuando se conoce el tamaño requerido antes de iniciar el Pool. Si mantiene bajas sus variables globales, el pool tampoco debería ser demasiado caro en Windows: las variables globales son automáticamente ... – robince
escabeche y enviadas a los subprocesos, por lo que sugiero que haga un buffer de tamaño suficiente al inicio (donde, con suerte, su cantidad de variables globales es pequeña), entonces Pool, es mejor. Me tomé el tiempo para entender y resolver su problema de buena fe, antes de editar su pregunta, así que aunque comprendo que si desea dejarlo funcionar, espero que al final considere aceptar mi respuesta si nada sustancialmente diferente/mejor llega. a lo largo. – robince