paralelismo multitarea multiprocesamiento hilos python multiprocessing gevent

python - multitarea - Gevent monkeypatching rompiendo multiprocesamiento



paralelismo python (5)

Escribió un complemento Nose Multiprocess de reemplazo: este debería jugar bien con todo tipo de parches basados ​​en Gevent.

https://pypi.python.org/pypi/nose-gevented-multiprocess/

https://github.com/dvdotsenko/nose_gevent_multiprocess

  • Cambia de multiprocess.fork a plain subprocess.popen para procesos de trabajo (soluciona los problemas de objetos compartidos erróneamente a nivel de módulo para mí)
  • Se cambió de multiprocesamiento. La cotización a JSON-RPC a través de HTTP para RPC maestro a clientes
  • Esto puede ahora teóricamente permitir que las pruebas se distribuyan a múltiples máquinas

Estoy intentando usar el grupo de multiprocesamiento para ejecutar un grupo de procesos, cada uno de los cuales ejecutará un grupo de Greenlets de gevent. La razón de esto es que hay mucha actividad en la red, pero también mucha actividad de la CPU, así que para maximizar mi ancho de banda y todos mis núcleos de la CPU, necesito múltiples procesos Y el parche async monkey de gevent. Estoy utilizando el administrador de multiprocesamiento para crear una cola a la que los procesos accederán para obtener datos para procesar.

Aquí hay un fragmento simplificado del código:

import multiprocessing from gevent import monkey monkey.patch_all(thread=False) manager = multiprocessing.Manager() q = manager.Queue()

Aquí está la excepción que produce:

Traceback (most recent call last): File "multimonkeytest.py", line 7, in <module> q = manager.Queue() File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 667, in temp token, exp = self._create(typeid, *args, **kwds) File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 565, in _create conn = self._Client(self._address, authkey=self._authkey) File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 175, in Client answer_challenge(c, authkey) File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 409, in answer_challenge message = connection.recv_bytes(256) # reject large message IOError: [Errno 35] Resource temporarily unavailable

Creo que esto se debe a alguna diferencia entre el comportamiento del módulo de socket normal y el módulo de socket de gevent.

Si hago Monkeypatch dentro del subproceso, la cola se crea correctamente, pero cuando el subproceso intenta obtener () de la cola, se produce una excepción muy similar. El zócalo no necesita ser pareado debido a que realiza un gran número de solicitudes de red en los subprocesos.

Mi versión de gevent, que creo que es la última:

>>> gevent.version_info (1, 0, 0, ''alpha'', 3)

¿Algunas ideas?


Lamentablemente, se sabe que la aplicación del multiprocesamiento en el contexto de gevent plantea problemas. Sin embargo, su razonamiento es razonable ("mucha actividad de red, pero también mucha actividad de CPU"). Si lo desea, eche un vistazo a http://gehrcke.de/gipc . Esto está diseñado principalmente para su caso de uso. Con gipc, puede generar fácilmente algunos procesos secundarios totalmente conscientes de Gevent y dejar que hablen de forma cooperativa entre ellos y / o con el padre a través de canalizaciones.

Si tiene preguntas específicas, le invitamos a que me contacte.


Si utilizará la Cola original, el código funcionará normalmente incluso con el zócalo parcheado mono.

import multiprocessing from gevent import monkey monkey.patch_all(thread=False) q= multiprocessing.Queue()


Su código proporcionado funciona para mí en Windows 7.

EDITAR:

Se eliminó la respuesta anterior, porque probé su código en Ubuntu 11.10 VPS y obtengo el mismo error.

Parece que Eventlet tiene este problema también


use monkey.patch_all(thread=False, socket=False)

Me he encontrado con el mismo problema en una situación similar y lo he rastreado hasta la línea 115 en gevent/monkey.py bajo la función patch_socket() : _socket.socket = socket.socket . Comentando esta línea hacia fuera previene la rotura.

Aquí es donde gevent reemplaza la biblioteca de socket stdlib con la suya propia. multiprocessing.connection usa la biblioteca de socket bastante y, aparentemente, no es tolerante a este cambio.

Específicamente, verá esto en cualquier escenario en el que un módulo que importe realice una llamada gevent.monkey.patch_all() sin configurar socket=False . En mi caso, fueron las grequests que hicieron esto, y tuve que anular el parcheo del módulo de socket para corregir este error.