多处理 - 将工作发送给员工,接收结果,更新员工,重新计算

时间:2017-05-09 21:29:05

标签: python python-multiprocessing

我正在尝试产生工作人员,给他们一些任务,将结果发送回处理结果的主进程,用新信息更新所有工作人员并向他们发送更多任务。我想在结束工人之前做一定数量的迭代。

我的代码似乎工作正常,但并非所有工作人员都在为每次迭代更新。例如。我收到的输出是:

Creating  4  workers
Finished workin 4
Finished workin 6
Finished workin 3
Finished workin 4

根据Pipe Documentation recv()应该阻止,直到有东西要收到。为什么在我的例子中不是这种情况?

from multiprocessing import Process, Queue, JoinableQueue, Pipe, Event, Barrier, Value
import time

def worker(qu_task,qu_results,chi,ev,bar,val):
    ext=False
    dum=0
    while True:
        ev.wait()
        while qu_task.empty() is False:
            a=qu_task.get() # Pop work from queue
            if a is None: #Poison pill
                bar.wait() # Wait for all processes so that they all receive "None"
                ext=True
                qu_task.task_done() #
                print("Finished workin", dum)
                break

            # Do stuff
            time.sleep(.1)
            qu_results.put(111)
            qu_task.task_done()

#        time.sleep(1.0)

        if ext: # Break out if finished
            break

        data1, data2  = chi.recv() # Blocks until there its something to receive
        dum+=data2
        # Do stuff

def main(NProc, NScen, NTime, branch):
    qu_tasks=JoinableQueue() # To use task_done() and join()
    qu_results=Queue()
    workers=[]
    val=Value('i',0)
    conn=[]
    bar=Barrier(NProc)
    ev=Event()
    print("Creating ", NProc, " workers")
    for i in range(NProc):
        par,chi=Pipe()
        workers.append(Process(target=worker,args=(qu_tasks,qu_results,chi,ev,bar,val)))
        conn.append(par)

    for w in workers:
        w.start()

    for t in reversed(range(NTime)):
        for s in range(NScen):
            a=0.0
            for b in branch:
                k=(b,s,t)
                qu_tasks.put(k) # Send work

            ev.set() # Start workers
            qu_tasks.join() # Synchronize workers
            ev.clear() # Reset lock
            for idx,i in enumerate(branch):
                a+=qu_results.get()
            #print(a)

            kk=[1,2,3,5]
            for idx,c in enumerate(conn):
                c.send(([i*(1+idx) for i in kk],1)) # Send more data to workers

    for i in range(NProc): # Kill workers
        qu_tasks.put(None)
    ev.set()
    qu_tasks.join()

    for w in workers: # Wait for them to finish
        w.join()

if __name__=="__main__":
    branch=[i for i in range(1,7)]
    NTime=2
    NScen=3

    main(4,NScen, NTime, branch)

1 个答案:

答案 0 :(得分:0)

Pipe.recv()等待,不要担心。它只是没有被调用6次,因为None因为循环很快就会失效。

请记住异步编程很好,异步,并且当工作人员开始使用" next"批次未达到Pipe.recv()

如果你移动time.sleep(.1),你可以达到"完成工作0"太

此外,如果您放慢(Joinable)Queue.put()循环,您可以在任务队列中途暂时变为空时,比您调度所有任务更快,这样工作人员将到达{{ 1}},但主程序将等待Pipe.recv()

建议:选择管道或(可加入)队列,但不要选择两者。联锁它们很难,也没有任何好处。