2012-04-04 10 views
11

Tenemos alrededor de 500 GB de imágenes en varios directorios que debemos procesar. Cada imagen tiene un tamaño de aproximadamente 4 MB y tenemos un script de Python para procesar cada imagen de una en una (lee los metadatos y los almacena en una base de datos). Cada directorio puede tardar de 1 a 4 horas en procesarse dependiendo del tamaño.La forma más rápida de procesar archivos de gran tamaño en Python

Tenemos a nuestra disposición un procesador de cuádruple núcleo de 2.2Ghz y 16 GB de RAM en un sistema operativo GNU/Linux. El script actual está utilizando solo un procesador. ¿Cuál es la mejor manera de aprovechar los otros núcleos y RAM para procesar imágenes más rápido? ¿Comenzará con múltiples procesos de Python para ejecutar el script aprovechando los otros núcleos?

Otra opción es usar algo como Gearman o Beanstalk para cultivar el trabajo en otras máquinas. He echado un vistazo a la biblioteca de multiprocesamiento pero no estoy seguro de cómo puedo utilizarla.

+0

posible duplicado de [¿Cómo utilizar todos los núcleos en Windows 7?] (Http://stackoverflow.com/questions/3055696/how-to-use-all-the-cores-in-windows-7) –

+1

Si ya tiene un script en funcionamiento que puede señalar los archivos/directorios que desee, considere escribir un script de shell para activar tantas instancias como necesite. –

+4

Comenzaría mirando dónde están los cuellos de botella. Si gasta la mayor parte de su tiempo realizando IO, entonces no podrá ir mucho más rápido. Por ejemplo, si un solo proceso logra cargar datos del disco a una cierta velocidad, es muy poco probable que pueda mantener esa velocidad cuando varios procesos mastican el disco. –

Respuesta

6

¿Comenzará con múltiples procesos Python para ejecutar el script aprovechando los otros núcleos?

Sí, lo hará, si la tarea está vinculada a la CPU. Esta es probablemente la opción más fácil. Sin embargo, no genere un solo proceso por archivo o por directorio; considere usar una herramienta como parallel(1) y deje que surja algo así como dos procesos por núcleo.

Otra opción es usar algo como Gearman o Beanstalk para cultivar el trabajo en otras máquinas.

Eso podría funcionar. Además, eche un vistazo a Python binding for ZeroMQ, hace que el procesamiento distribuido sea bastante fácil.

Eché un vistazo a la biblioteca de multiprocesamiento pero no estoy seguro de cómo puedo utilizarla.

definir una función, dicen process, que lee las imágenes en un solo directorio, se conecta a la base de datos y almacena los metadatos. Deje que devuelva un booleano que indique éxito o error. Deje directories ser la lista de directorios para procesar. Luego

import multiprocessing 
pool = multiprocessing.Pool(multiprocessing.cpu_count()) 
success = all(pool.imap_unordered(process, directories)) 

procesará todos los directorios en paralelo. También puede hacer el paralelismo en el nivel de archivo si lo desea; eso necesita retocarse un poco más.

Tenga en cuenta que esto se detendrá en la primera falla; hacerlo tolerante a las fallas requiere un poco más de trabajo.

4

Iniciar procesos independientes de Python es ideal. No habrá contenciones de bloqueo entre los procesos, y el sistema operativo los programará para que se ejecuten al mismo tiempo.

Es posible que desee experimentar para ver cuál es el número ideal de instancias: puede ser más o menos que el número de núcleos. Habrá contención para el disco y la memoria caché, pero por otro lado puede obtener un proceso para ejecutar mientras otro está esperando E/S.

2

Ver el answer a este question.

Si la aplicación puede procesar rangos de datos de entrada, entonces se puede lanzar 4 instancias de la aplicación con diferentes rangos de datos de entrada para procesar y combinar los resultados después de que todos se hacen.

Aunque esta pregunta parece ser específica de Windows, se aplica a los programas de un solo hilo en todos los sistemas operativos.

ADVERTENCIA: Tenga en cuenta que este proceso será el acceso simultáneo de E/S de la envolvente y el exceso en el disco duro va a causar realmente los procesos como un grupo para ejecutar lento de procesamiento secuencial debido a la pelea por el I/O recurso.

4

Puede usar el grupo de multiproceso para crear procesos para aumentar el rendimiento. Digamos que tienes una función handle_file que sirve para procesar imágenes. Si usa la iteración, solo puede usar como máximo el 100% de uno de sus núcleos. Para utilizar múltiples núcleos, el multiprocesamiento de grupo crea subprocesos para usted y les distribuye su tarea. Aquí hay un ejemplo:

import os 
import multiprocessing 

def handle_file(path): 
    print 'Do something to handle file ...', path 

def run_multiprocess(): 
    tasks = [] 

    for filename in os.listdir('.'): 
     tasks.append(filename) 
     print 'Create task', filename 

    pool = multiprocessing.Pool(8) 
    result = all(list(pool.imap_unordered(handle_file, tasks))) 
    print 'Finished, result=', result 

def run_one_process(): 
    for filename in os.listdir('.'): 
     handle_file(filename) 

if __name__ == '__main__': 
    run_one_process 
    run_multiprocess() 

run_one_process es una forma única de procesar datos, simple pero lenta. Por otro lado, run_multiprocess crea 8 procesos de trabajo y les distribuye tareas. Sería unas 8 veces más rápido si tienes 8 núcleos. Le sugiero que configure el número de trabajador en el doble de sus núcleos o exactamente el número de sus núcleos. Puedes probarlo y ver qué configuración es más rápida.

Para la informática distribuida avanzada, puede usar ZeroMQ como mencionó larsmans. Es difícil de entender al principio. Pero una vez que lo comprende, puede diseñar un sistema distribuido muy eficiente para procesar sus datos. En su caso, creo que un REQ con múltiples REP sería lo suficientemente bueno.

enter image description here

Hope esto sería útil.

0

Si está leyendo una gran cantidad de archivos y guardando metadatos en una base de datos, su programa no necesita más núcleos.

Su proceso es probable que IO no esté enlazado a la CPU. El uso de retorcidos con devoluciones y devoluciones de llamada correctas probablemente superará cualquier solución que buscara alistar 4 núcleos.

0

Creo que en este escenario tendría mucho sentido usar Celery.

Cuestiones relacionadas