¿Hay alguna herramienta en Python que sea como el parfor de Matlab? Encontré este hilo , pero tiene cuatro años. Pensé que tal vez alguien aquí podría tener una experiencia más reciente.
Aquí hay un ejemplo del tipo de cosas que me gustaría paralelizar:
X = np.random.normal(size=(10, 3))
F = np.zeros((10, ))
for i in range(10):
F[i] = my_function(X[i,:])
donde my_function
toma un ndarray
tamaño (1,3)
y devuelve un escalar.
Al menos, me gustaría usar varios núcleos simultáneamente, como parfor. En otras palabras, suponga un sistema de memoria compartida con 8 a 16 núcleos.
python
parallel-computing
Paul G. Constantine
fuente
fuente
Respuestas:
Joblib hace lo que quieres. El patrón de uso básico es:
donde
arg_instances
es la lista de valores para los quemyfun
se calcula en paralelo. La restricción principal es quemyfun
debe ser una función de nivel superior. Elbackend
parámetro puede ser"threading"
o"multiprocessing"
.Puede pasar parámetros comunes adicionales a la función paralelizada. El cuerpo de
myfun
también puede referirse a variables globales inicializadas, los valores que estarán disponibles para los hijos.Los argumentos y los resultados pueden ser prácticamente cualquier cosa con el backend de subprocesos, pero los resultados deben ser serializables con el backend de multiprocesamiento.
Dask también ofrece una funcionalidad similar. Puede ser preferible si está trabajando con datos fuera del núcleo o si está tratando de paralelizar cálculos más complejos.
fuente
threading
backend sufre el cuello de botella de GIL y elmultiprocessing
backend genera una gran sobrecarga debido a la serialización de todos los parámetros y valores de retorno. Vea esta respuesta para los detalles de bajo nivel del procesamiento paralelo en Python.map
que puede usar directamente. Además, si utiliza mkl compilado numpy, paralelizará las operaciones vectorizadas automáticamente sin que usted haga nada. El numpy en Ananconda está habilitado para mkl por defecto. Sin embargo, no hay una solución universal. Joblib está muy preocupado y hubo menos oportunidades en 2015.Lo que estás buscando es Numba , que puede paralelizar automáticamente un bucle for. De su documentación
fuente
Sin suponer que algo especial en la
my_function
elecciónmultiprocessing.Pool().map()
es una buena suposición para paralelizar dichos bucles simples.joblib
,dask
,mpi
Cálculos onumba
como se propone en otras respuestas no se ve con lo que ninguna ventaja para este tipo de casos de uso y agregar dependencias inútiles (para resumir que son una exageración). Es poco probable que el uso de subprocesos como se propone en otra respuesta sea una buena solución, ya que debe ser íntimo con la interacción GIL de su código o su código debe hacer principalmente entrada / salida.Dicho esto,
numba
podría ser una buena idea acelerar el código secuencial de Python puro, pero creo que esto está fuera del alcance de la pregunta.Sin embargo, hay algunas advertencias (pero que no deberían afectar la mayoría de las aplicaciones):
if __name__ == "__main__"
my_function
no debe depender de estados compartidos como comunicarse con variables globales porque los estados no se comparten entre procesos. Las funciones puras (funciones en los sentidos matemáticos) son ejemplos de funciones que no comparten estadosfuente
Mi impresión de parfor es que MATLAB está encapsulando los detalles de implementación, por lo que podría estar utilizando tanto el paralelismo de memoria compartida (que es lo que quiere) como el paralelismo de memoria distribuida (si está ejecutando un servidor de computación distribuida de MATLAB ).
Si desea un paralelismo de memoria compartido y está ejecutando algún tipo de bucle paralelo de tareas, el paquete de biblioteca estándar de multiprocesamiento es probablemente lo que desea, tal vez con un buen front-end, como joblib , como se menciona en la publicación de Doug. La biblioteca estándar no va a desaparecer, y se mantiene, por lo que es de bajo riesgo.
También hay otras opciones, como Parallel Python y las capacidades paralelas de IPython . Un vistazo rápido a Parallel Python me hace pensar que está más cerca del espíritu de parfor, ya que la biblioteca encapsula los detalles del caso distribuido, pero el costo de hacerlo es que tienes que adoptar su ecosistema. El costo de usar IPython es similar; debes adoptar la forma de hacer las cosas de IPython, que puede o no valer la pena para ti.
Si le importa la memoria distribuida, le recomiendo mpi4py . Lisandro Dalcin hace un gran trabajo, y mpi4py se usa en los envoltorios de PETSc Python, por lo que no creo que desaparezca pronto. Al igual que el multiprocesamiento, es una interfaz de bajo (er) nivel de paralelismo que parfor, pero es probable que dure un tiempo.
fuente
Antes de buscar una herramienta de "recuadro negro", que pueda usarse para ejecutar en paralelo funciones "genéricas" de Python, sugeriría analizar cómo
my_function()
se puede paralelizar manualmente.Primero, compare el tiempo de ejecución de la sobrecarga del bucle de
my_function(v)
Pythonfor
: [C] Losfor
bucles de Python son bastante lentos, por lo que el tiempo invertidomy_function()
podría ser insignificante.Segunda verificación si hay una implementación vectorial simple
my_function(v)
que no requiere bucles:F[:] = my_vector_function(X)
(Estos dos primeros puntos son bastante triviales, perdóname si los mencioné aquí solo para completarlos).
El tercer y más importante punto, al menos para las implementaciones de CPython, es verificar si
my_function
pasa la mayor parte del tiempo dentro o fuera del bloqueo global del intérprete , o GIL . Si se pasa tiempo fuera del GIL, se debe usar elthreading
módulo de biblioteca estándar . ( Aquí un ejemplo). Por cierto, uno podría pensar en escribirmy_function()
como una extensión C solo para liberar el GIL.Finalmente, si
my_function()
no libera el GIL, uno podría usar elmultiprocessing
módulo .Referencias: documentos de Python sobre ejecución simultánea e introducción numpy / scipy sobre procesamiento paralelo .
fuente
Puedes probar Julia. Está bastante cerca de Python y tiene muchas construcciones de MATLAB. La traducción aquí es:
Esto hace que los números aleatorios también sean paralelos, y simplemente concatena los resultados al final durante la reducción. Eso usa multiprocesamiento (por lo que debe hacer
addprocs(N)
para agregar procesos antes de usar, y esto también funciona en múltiples nodos en un HPC como se muestra en esta publicación de blog ).También puedes usar
pmap
en su lugar:Si desea paralelismo de subprocesos, puede usar
Threads.@threads
(aunque asegúrese de hacer que el algoritmo sea seguro para subprocesos). Antes de abrir Julia, configure la variable de entorno JULIA_NUM_THREADS, luego es:Aquí hago una matriz separada para cada hilo, de modo que no choquen cuando se agreguen a la matriz, luego simplemente concatenen las matrices después. Los subprocesos son bastante nuevos, por lo que en este momento solo hay un uso directo de los subprocesos, pero estoy seguro de que se agregarán reducciones de subprocesos y mapas como lo fue para el multiprocesamiento.
fuente
Recomiendo usar las funciones paralelas y retrasadas de la biblioteca joblib para usar el módulo "tempfile" para crear memoria temporal compartida para grandes matrices, los ejemplos y el uso se pueden encontrar aquí https://pythonhosted.org/joblib/parallel.html
fuente