我正在尝试产生工作人员,给他们一些任务,将结果发送回处理结果的主进程,用新信息更新所有工作人员并向他们发送更多任务。我想在结束工人之前做一定数量的迭代。
我的代码似乎工作正常,但并非所有工作人员都在为每次迭代更新。例如。我收到的输出是:
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)
答案 0 :(得分:0)
Pipe.recv()
等待,不要担心。它只是没有被调用6次,因为None
因为循环很快就会失效。
请记住异步编程很好,异步,并且当工作人员开始使用" next"批次未达到Pipe.recv()
如果你移动time.sleep(.1)
,你可以达到"完成工作0"太
此外,如果您放慢(Joinable)Queue.put()
循环,您可以在任务队列中途暂时变为空时,比您调度所有任务更快,这样工作人员将到达{{ 1}},但主程序将等待Pipe.recv()
建议:选择管道或(可加入)队列,但不要选择两者。联锁它们很难,也没有任何好处。