sklearn parallel python joblib

python - sklearn - joblib parallel



¿Qué hace la función delayed()(cuando se usa con joblib en Python) (3)

He leído la documentation , pero no entiendo qué se entiende por: The delayed function is a simple trick to be able to create a tuple (function, args, kwargs) with a function-call syntax.

Lo estoy usando para iterar sobre la lista en la que quiero operar (todas las imágenes) de la siguiente manera:

def joblib_loop(): Parallel(n_jobs=8)(delayed(getHog)(i) for i in allImages)

Esto devuelve mis funciones de HOG, como quiero (y con la ganancia de velocidad usando todos mis 8 núcleos), pero no estoy seguro de lo que realmente está haciendo.

Mi conocimiento de Python está bien en el mejor de los casos, y es muy posible que me esté perdiendo algo básico. Cualquier puntero en la dirección correcta sería más apreciado


De la referencia https://wiki.python.org/moin/ParallelProcessing El objeto Parallel crea un grupo de multiprocesamiento que procesa al intérprete de Python en varios procesos para ejecutar cada uno de los elementos de la lista. La función retardada es un truco simple para poder crear una tupla (función, args, kwargs) con una sintaxis de llamada de función.

Otra cosa que me gustaría sugerir es que, en lugar de definir explícitamente varios núcleos, podemos generalizar así:

import multiprocessing num_core=multiprocessing.cpu_count()


Entonces, lo que quiere hacer es acumular un conjunto de llamadas a funciones y sus argumentos de tal manera que pueda pasarlas de manera eficiente a un programador / ejecutor. Delayed es un decorator que toma una función y sus argumentos y los envuelve en un objeto que se puede colocar en una lista y se puede desplegar según sea necesario. Dask tiene la misma cosa que utiliza en parte para alimentar su programador gráfico.


Tal vez las cosas se aclaran si observamos lo que sucedería si en lugar de eso simplemente escribiéramos

Parallel(n_jobs=8)(getHog(i) for i in allImages)

De la forma en que funciona Python, getHog(i) for i in allImages crea una lista en la que cada elemento ya está evaluado . Esto significa que todas getHog llamadas a getHog ya han regresado cuando la lista se pasa a su objeto Parallel , ¡y no queda nada para que Parallel ejecute en paralelo! Todo el trabajo ya se ha hecho en el hilo en el que estamos ahora, secuencialmente.

Así que tenemos que retrasar la ejecución conservando a.) La función que queremos llamar y la b.) Los argumentos con los que queremos llamar a la función, pero sin ejecutar la función en realidad.

Esto es lo que delayed convenientemente hace por nosotros con una sintaxis clara. Si queremos "conservar" la llamada foo(2, g=3) para más adelante, simplemente podemos llamar con delayed(foo)(2, g=3) y la tupla (foo, [2], {g: 3}) es devuelto, listo para ser ejecutado por otra persona.

Entonces, en su ejemplo, en pocas palabras, sucede lo siguiente.

  1. Ha creado una lista de delayed(getHog)(i)

  2. Cada uno de esos delayed(getHog)(i) devuelve la tupla (function, args, kwargs) (como leíste en los documentos) que en este caso es la tupla (getHog, [i], {})

  3. Su objeto Parallel creado anteriormente crea un nuevo hilo para cada elemento en la lista y distribuye las tuplas a ellos

  4. En cada uno de esos nuevos hilos, ejecuta uno de los elementos de la lista: llama al primer elemento de la tupla con el segundo y el tercer elemento desempaquetado como argumentos el[0](*el[1], **el[2]) o function(*args, **kwargs) , que en este caso da como resultado la llamada getHog(i) .