2014-10-21 9 views
0

Итак, я думал, что, наконец, опубликую; Каким образом можно управлять Process работниками? Я попытался использовать Pool, но я заметил, что не смог получить возвращаемое значение каждого завершенного процесса. Я попытался использовать обратный вызов, но это тоже не сработало. Должен ли я сам управлять ими с помощью active_children()? КодУправление процессами из модуля многопроцессорности Python

Мой бассейн:

from multiprocessing import *                      
import time 
import random 

SOME_LIST = [] 

def myfunc(): 
    a = random.randint(0,3) 
    time.sleep(a) 
    return a 

def cb(retval): 
    SOME_LIST.append(retval) 

print("Starting...") 

p = Pool(processes=8) 
p.apply_async(myfunc, callback=cb) 
p.close() 
p.join() 

print("Stopping...") 
print(SOME_LIST) 

Я ожидаю, что список значений; но все это я получаю последний элемент в работе работника для завершения:

$ python multi.py 
Starting... 
Stopping... 
[3] 

Примечания: Ответ не должен использовать threading модуль; вот причина, почему:

В CPython, из-за глобальным интерпретатор блокировку, только один поток может выполнить код Python сразу (даже если некоторые ориентированные на показатели эффективности библиотек могут преодолеть это ограничение). Если вы хотите, чтобы ваше приложение использовало вычислительные ресурсы многоядерных машин , рекомендуется использовать многопроцессорную обработку.

+0

Использование пула - правильный путь. Вы также должны получить возвращаемое значение для каждого завершенного рабочего процесса: 'return_value = pool.apply (func, args = (arg1, arg2)'. Можете ли вы поделиться кодом, который вы пытаетесь использовать, что isn 't working? – dano

+0

Я не уверен, что это то, что вы имеете в виду, но это тоже прекрасно работает: 'return_value = pool.apply (func)'. Где 'func' является' def func(): return 12345'. 'return_value' будет присваиваться' 12345', возвращенному 'func'. – dano

+0

Я в замешательстве. Почему вы ожидаете список результатов из приведенного выше примера? Вы просто вызываете' apply_async' один раз, что означает, re, просто вызывающий 'myfunc' один раз в одном из рабочих процессов. Что вы ожидаете? – dano

ответ

4

Вы неправильно понимаете, как работает apply_async. Он не вызывает функцию, которую вы передаете ей в каждом процессе в Pool. Он просто вызывает функцию один раз в одном из рабочих процессов. Таким образом, результаты, которые вы видите, следует ожидать. У вас есть несколько вариантов, чтобы получить требуемое поведение:

from multiprocessing import Pool                     
import time 
import random 

SOME_LIST = [] 

def myfunc(): 
    a = random.randint(0,3) 
    time.sleep(a) 
    return a 

def cb(retval): 
    SOME_LIST.append(retval) 

print("Starting...") 

p = Pool(processes=8) 
for _ in range(p._processes): 
    p.apply_async(myfunc, callback=cb) 
p.close() 
p.join() 

print("Stopping...") 
print(SOME_LIST) 

Или

from multiprocessing import Pool                      
import time 
import random 


def myfunc(): 
    a = random.randint(0,3) 
    time.sleep(a) 
    return a 

print("Starting...") 

p = Pool(processes=8) 
SOME_LIST = p.map(myfunc, range(p._processes)) 
p.close() 
p.join() 

print("Stopping...") 
print(SOME_LIST) 

Заметьте, что вы также можете позвонить apply_async или map для дополнительной чем количество процессов в пуле. Идея Pool заключается в том, что она гарантирует ровно num_processes процессы будут работать в течение всего срока службы Pool, независимо от того, сколько задач вы отправляете. Поэтому, если вы создадите Pool(8) и позвоните по телефону apply_async, один из ваших восьми рабочих получит задание, а остальные семь будут бездействовать. Если вы создадите Pool(8) и вызовите apply_async 80 раз, 80 задач будут распределены между вашими восемью рабочими, причем не более восьми из фактически обрабатываемых задач.

Смежные вопросы