2010-06-10 13 views
5

Tuve que hacer operaciones pesadas de E/S encuadernadas, es decir, analizar archivos de gran tamaño y convertir de un formato a otro. ¡Inicialmente solía hacerlo en serie, es decir, analizando uno tras otro ...! El rendimiento fue muy pobre (usó más de 90 segundos). Así que decidí usar threading para mejorar el rendimiento. Creé un hilo para cada archivo. (4 hilos)python threading y rendimiento?

for file in file_list: 
      t=threading.Thread(target = self.convertfile,args = file) 
      t.start() 
      ts.append(t) 
for t in ts: 
      t.join() 

Pero para mi sorpresa, no hay ninguna mejora en el rendimiento absoluto. Ahora también lleva alrededor de 90+ segundos completar la tarea. Como se trata de operaciones de I/O obligado, esperaba mejorar el rendimiento.

Respuesta

10

Bajo el intérprete de Python habitual, el subprocesamiento no asignará más núcleos de CPU a su programa debido al global interpreter lock (también conocido como GIL).

El módulo multiprocessing podría ayudarlo aquí. (Tenga en cuenta que se introdujo en Python 2.6, pero existen backports para Python 2.5.)

Como dice MSalters, si su programa está vinculado a E/S es discutible si esto es útil. Pero podría ser digno de un tiro :)

Para lograr lo que desea el uso de este módulo:

import multiprocessing 

MAX_PARALLEL_TASKS = 8 # I have an Intel Core i7 :) 

pool = multiprocessing.Pool(MAX_PARALLEL_TASKS) 

pool.map_async(convertfile, filelist) 

pool.close() 
pool.join() 

Importante! La función que pase al map_async debe ser seleccionable. En general, los métodos de instancia NO son elegibles a menos que usted los diseñe para que así sea. Tenga en cuenta que convertfile arriba es una función.

Si realmente necesita obtener resultados de convertfile, también hay formas de hacerlo. Los ejemplos en la página de documentación de multiprocesamiento deben aclarar.

+0

Gracias delty..Pero el módulo de multiprocesamiento tiene sus propios problemas. 1) Tengo que refactorizar mi código ya que no puedo usar métodos de instancia ... 2) Tengo un método de instancia que tiene muchos manejadores de archivos ... Estos manejadores de archivos están cerrados en procesos secundarios, lo que no es aceptable. Entonces necesito abrirlos de nuevo. Desafortunadamente no tengo manera de conocerlos, ya que se pasan durante la instanciación – kumar

+0

No tiene que ser la función de conversión en sí que se realiza en un proceso separado. ¿Hay alguna forma de que pueda hacer la parte de creación de instancias en procesos separados? P.ej. escriba una función o incluso una secuencia de comandos separada que realice una sola instanciación y conversión; luego, escriba un "script maestro" que use el módulo de multiprocesamiento para ejecutar estas funciones. Se pueden ejecutar scripts separados utilizando el módulo [subprocess] (http://docs.python.org/library/subprocess.html). Si hay una gran cantidad de datos compartidos, entonces sí, ahí es donde el multiprocesamiento se complica. Pero hay muchas más herramientas en ese módulo :) – detly

2

Threading permite que el sistema operativo asigne más núcleos de CPU a su programa. Si está vinculado a E/S, eso significa que la velocidad estuvo limitada por la velocidad del sistema de E/S en lugar de la velocidad de la CPU. En esos casos, la asignación de más núcleos de CPU no necesariamente ayuda; aún está esperando en el subsistema de E/S.

+0

Pero creo que la conmutación de subprocesos ocurre cuando un subproceso está esperando un subproceso de E/S, ¿no es así? Así que estoy haciendo las cosas en paralelo ahora, lo que significa que puedo esperar alguna mejora en el rendimiento. – kumar

+5

Enhebrar en Python no asigna más núcleos de CPU al programa. – detly

+0

@kumar: como dice la respuesta, si tiene E/S unida (su E/S va tan fuerte como puede), más tiempo de CPU o procesamiento paralelo no hará que la E/S finalice antes. – Josh