El día 4 de marzo de 2014, 10:00, Daπid <[email protected]> escribió:
> 2014-03-03 22:19 GMT+01:00 Chema Cortes <[email protected]>:
>>
>>
>> OK. Creo que has hecho un planteamiento demasiado optimista. El
>> proceso "saver" entra a funcionar antes de los jobs generadores, por
>> lo que es posible que termine sin haber procesado todos los datos,
>> bloqueándose el hilo principal por quedar datos en la cola.
>
>
> El proceso real crea el fichero en el que va a guardar los datos, y no
> termina hasta que recibe un None, en cuyo caso sólo tiene que cerrar el
> archivo y terminar casi inmediatamente.
>
>> Por otro lado, estás usando una librería externa para HDF5 que podría
>> estar descontrolando el GIL del intérprete. Prueba a usar el backend
>> "threading" a ver si mejora.
>>
>> https://pythonhosted.org/joblib/parallel.html#using-the-threading-backend
>
>
> En mi caso, eso no es una opción. El cálculo tira mucho de CPU, y necesito
> hacer uso de los ocho núcleos que tengo. Cierto es que la parte "dura" del
> cálculo está en Cython y podía ejecutarla con nogil. Lo que estoy haciendo
> ahora es simplemente poner los resultados en memoria y guardarlos todos
> seguidos al final. Por otro lado, convertir el proceso "saver" en un thread
> es probablemente una buena idea.
>
> Lo sospechoso es que en la mayoría de los casos, funciona. Si estuviera
> haciendo algo mal, debería fallar siempre; no funcionar para ciertos
> conjuntos de datos y fallar para otros muy similares. Huele a bug en Python,
> pero no estoy seguro.

Python está bien para muchas cosas, pero no está preparado para multiproceso.

No te creas que por usar el módulo "multiprocessing" tu código va a
ser mucho más rápido que usando "multihilo" sobre un sólo core, del
mismo modo que un hipotético intérprete sin-GIL no va a ser más rápido
que uno con-GIL.

Para poder tener multiproceso, de tu proceso padre se lanzan varios
fork, estableciéndose un conjunto de dispatchers que
serializan/deserializan todos tus datos compartidos. Cuantos más
cambios se hagan en estos datos, peor rendimiento tienes, y más
probabilidades de que se queden bloqueados los procesos. Así mismo,
los datos se duplican para cada proceso, con el conocido problema (en
concurrencia) de que queden en estado inconsistente y que haga que los
GCs de cada proceso no terminen por liberar la memoria.

Es fundamental tener un diseño bien pensado. No basta con hacer que
funcione con "multiprocessing": hay que granular con cuidado quiénes
van a ver qué parte de los datos y quiénes podrán modificarlos. A
veces es mejor tener un sólo proceso que pueda modificar y que el
resto se comunique con él para que haga los cambios, nada de memoria
compartida por todos. Mejor aún, que cada proceso tenga su datos
privados y que se comuniquen mediante mensajes siguiendo el patrón
"Actor".

Mi consejo es que intentes usar el backend "threading" a ver si
funciona sin problemas. Lo que vaya sin GIL, como las librerías para
HDF5 o lo que quieras calculas con Cython-nogil, intenta que pase los
datos a través de un mecanismo que no comparta memoria con python.

Así mismo, es importante revisar todo el código. Cualquier variable
global puede ser importante. Nada debería haber suelto por el módulo.
Es complejo dar con un problema de concurrencia sin ver el código
completo.

No sé si te sirve de algo lo que te he dicho, pero hace tiempo que me
pasé a scala para el multiproceso. Aquí te pongo un artículo que lo
explica bastante bien:

  http://www.chrisstucchio.com/blog/2013/why_not_python.html


-- 
Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales":
http://ch3m4.org/blog
Buscador Python Hispano: http://ch3m4.org/python-es
_______________________________________________
Python-es mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/

Responder a