Python multiprocessing.Queue deadlocks on put and get

Tengo problemas de interlocking con este código:

def _entropy_split_parallel(data_train, answers_train, weights): CPUS = 1 #multiprocessing.cpu_count() NUMBER_TASKS = len(data_train[0]) processes = [] multi_list = zip(data_train, answers_train, weights) task_queue = multiprocessing.Queue() done_queue = multiprocessing.Queue() for feature_index in xrange(NUMBER_TASKS): task_queue.put(feature_index) for i in xrange(CPUS): process = multiprocessing.Process(target=_worker, args=(multi_list, task_queue, done_queue)) processes.append(process) process.start() min_entropy = None best_feature = None best_split = None for i in xrange(NUMBER_TASKS): entropy, feature, split = done_queue.get() if (entropy < min_entropy or min_entropy == None) and entropy != None: best_feature = feature best_split = split for i in xrange(CPUS): task_queue.put('STOP') for process in processes: process.join() return best_feature, best_split def _worker(multi_list, task_queue, done_queue): feature_index = task_queue.get() while feature_index != 'STOP': result = _entropy_split3(multi_list, feature_index) done_queue.put(result) feature_index = task_queue.get() 

Cuando ejecuto mi progtwig, funciona bien para varias ejecuciones a través de _entropy_split_parallel , pero eventualmente puntos muertos. El proceso principal está bloqueando en done_queue.get() , y el proceso de trabajo está bloqueando en done_queue.put() . Dado que la cola siempre está vacía cuando esto sucede, se espera que se bloquee al get . Lo que no entiendo es por qué el trabajador está bloqueando, porque la cola obviamente no está llena (¡está vacía!). He probado los argumentos de palabras clave de block y timeout , pero obtuve el mismo resultado.

Estoy usando el backport de multiprocesamiento, ya que estoy atascado con Python 2.5.


EDITAR: Parece que también estoy teniendo problemas de interlocking con uno de los ejemplos provistos con el módulo de multiprocesamiento. Es el tercer ejemplo de la parte inferior aquí. El interlocking solo parece ocurrir si llamo al método de prueba muchas veces. Por ejemplo, cambiando la parte inferior de la secuencia de comandos a esto:

 if __name__ == '__main__': freeze_support() for x in xrange(1000): test() 

EDIT: Sé que esta es una pregunta antigua, pero las pruebas muestran que esto ya no es un problema en Windows con Python 2.7. Voy a tratar de Linux y el informe de nuevo.

Creo que el problema es que el subproceso principal se une a un subproceso secundario al que ha pasado una cola. Esto se discute en la sección de pautas de progtwigción del módulo multiprocesamiento.

En cualquier caso, me encontré con el mismo síntoma que describe, y cuando reformulé mi lógica para que el hilo maestro no se uniera a los hilos secundarios, no había ningún punto muerto. Mi lógica refactorizada incluía saber la cantidad de elementos que debería obtener de los resultados o de la cola “hecho” (que se puede predecir en función de la cantidad de subprocesos secundarios o la cantidad de elementos en la cola de trabajo, etc.) y el bucle Infinitamente hasta que todos estos fueron recogidos.

“Juguete” ilustración de la lógica:

 num_items_expected = figure_it_out(work_queue, num_threads) items_received = [] while len(items_received) < num_items_expected: items_received.append(done_queue.get()) time.sleep(5) 

La lógica anterior evita la necesidad de que el subproceso primario se una al subproceso secundario, pero permite que el subproceso primario se bloquee hasta que todos los secundarios estén listos. Este enfoque evitó mis problemas de punto muerto.

Este problema desapareció con las nuevas versiones de Python, así que asumo que fue un problema con el backport. De todos modos, ya no es un problema.