2012-02-07 18 views
7

Estoy escribiendo un descompresor multiproceso en python. Cada hilo necesita acceder a un fragmento diferente del archivo de entrada.Lectura de un único archivo de varios subprocesos en python

Nota 1: no es posible cargar todo el archivo, ya que oscila entre 15 Gb y 200 Gb; No estoy usando multihebra para acelerar la lectura de datos, pero la descompresión de datos, solo quiero asegurarme de que la lectura de datos no desacelere la descompresión.

Nota 2: el GIL no es un problema, ya que la función descompresora principal es una extensión C y llama a Py_ALLOW_THREADS, por lo que se libera el GIL durante la descompresión. La descompresión de la segunda etapa usa numpy, que también está libre de GIL.

1) que supone que no funcionaría para compartir simplemente un objeto descompresor (que básicamente se ajusta un objeto de archivo), ya que si el subproceso A llama al siguiente:

decompressor.seek(x) 
decompressor.read(1024) 

e hilo B hace lo mismo, hilo A podría terminar leyendo desde el desplazamiento del hilo B. ¿Es esto correcto?

2) En este momento simplemente estoy haciendo que cada hilo cree su propia instancia de descompresor y parece que funciona, pero no estoy seguro de que sea el mejor enfoque. que considera estas posibilidades:

  • añadir algo como

    seekandread(from_where, length) 
    

    a la clase descompresor, que adquiere un bloqueo, busca, lee y libera el bloqueo;

  • Crea un hilo que espera solicitudes de lectura y las ejecuta en el orden correcto.

Entonces, ¿me falta una solución obvia? ¿Hay una diferencia de rendimiento significativa entre estos métodos?

Gracias

+5

Leer un archivo de manera multiproceso realmente ralentiza el proceso cuando tiene un disco duro. La aguja tiene que saltar de un lugar a otro en lugar de trabajar de forma iterativa. Debe cargar el archivo antes de procesarlo. –

+0

No es posible cargar todo el archivo, ya que oscila entre 15 Gb y 200 Gb; No estoy usando multihebra para acelerar la lectura de datos, pero la descompresión de datos, solo quería asegurarme de que la lectura de datos no desacelere la descompresión. – Alberto

+0

Por supuesto, esto puede o no aplicarse a las SSD. Aunque no tengo ni idea sobre el tema. No debe retransmitir en el hardware para hacerlo. Una vez que las SSD son lo suficientemente comunes, realizar E/S de manera multiproceso puede ser eficiente. –

Respuesta

2

Puede usar mmap. Ver mmap() vs. reading blocks

Como señala Tim Cooper, mmap es una buena idea cuando tienes acceso aleatorio (varios hilos podrían hacer que parezca que tienes esto), y podrían compartir las mismas páginas físicas.

+0

¡Esto parece excelente! Miré la documentación de Python para mmap, pero no pude encontrar una referencia sobre seguridad de hilos. Si 2 hilos hacen algo como a = mappedfile [x: y] al mismo tiempo, ¿funcionará como se espera? – Alberto

+0

Para responderme a mí mismo, parece que la notación de división python mmap es realmente segura para los hilos. Creé un programa de prueba que accede a diferentes partes de un archivo mmapped desde diferentes subprocesos y comprueba el resultado. Pasa la prueba si uso notación de división, falla si uso seek/read. Todavía tengo que verificar el rendimiento, sin embargo. – Alberto

+1

@Alberto: Me parece que cualquier segmento dado que ya está siendo procesado debe estar protegido por al menos un mutex, si no un semáforo condicional de lanzamiento. Por un semáforo condicional arrojado me refiero a un semáforo que no espera si la condición previa a la entrada no se cumple hasta que es, sino que arroja una excepción. Es un híbrido entre un semáforo y un gaurd. Es posible que desee lanzar solo cuando la condición B no se cumple y esperar si se cumple la condición A. –

2

Es posible que desee utilizar el patrón Leader/Follower si usted no está haciendo ya.
El subproceso Leader sabrá qué segmentos ya se están manejando y cuáles no y se asignará con el siguiente segmento sin procesar y luego se convertirá en seguidor, dejando el liderazgo al siguiente subproceso disponible en el grupo.

+0

Gracias, investigaré eso. – Alberto

1

CPython tiene GIL por lo que varios subprocesos no aumentan el rendimiento para las tareas vinculadas a la CPU.

Si el problema no está vinculado a IO (el disco proporciona/almacena datos más rápido que la descompresión de la CPU) puede usar multiprocessing module: cada proceso abre el archivo y descomprime un rango dado de bytes.

+1

La función descompresora principal es una extensión C y llama a Py_ALLOW_THREADS, de modo que el GIL se libera durante la descompresión. La descompresión de la segunda etapa usa numpy, que también está libre de gil. Ya he medido una buena aceleración. – Alberto

+0

(tal vez esta aclaración - acerca de que usted había "cuidado" de GIL - también podría entrar en el cuerpo principal de la pregunta) – jsbueno

+0

Tiene razón, hecho – Alberto

Cuestiones relacionadas