Python 带while循环的基本多处理
我是python中的Python 带while循环的基本多处理,python,python-2.7,while-loop,multiprocessing,python-multiprocessing,Python,Python 2.7,While Loop,Multiprocessing,Python Multiprocessing,我是python中的多处理包的新手,我的困惑可能很容易被了解更多的人弄清楚。我一直在阅读有关并发性的文章,并搜索了其他类似的问题,但没有找到任何结果。(仅供参考,我不想使用多线程,因为GIL会大大降低我的应用程序的速度。) 我在事件的框架中思考。我想让多个进程运行,等待事件发生。如果事件发生,它将被分配给一个特定的进程,该进程将运行,然后返回到空闲状态。也许有更好的方法可以做到这一点,但我的理由是,我应该一次生成所有进程,并让它们无限期地打开,而不是每次事件发生时创建然后关闭一个进程。速度对我来
多处理
包的新手,我的困惑可能很容易被了解更多的人弄清楚。我一直在阅读有关并发性的文章,并搜索了其他类似的问题,但没有找到任何结果。(仅供参考,我不想使用多线程
,因为GIL会大大降低我的应用程序的速度。)
我在事件的框架中思考。我想让多个进程运行,等待事件发生。如果事件发生,它将被分配给一个特定的进程,该进程将运行,然后返回到空闲状态。也许有更好的方法可以做到这一点,但我的理由是,我应该一次生成所有进程,并让它们无限期地打开,而不是每次事件发生时创建然后关闭一个进程。速度对我来说是个问题,我的事件每秒可能发生数千次
我提出了下面的玩具示例,它意味着向一个进程发送偶数,向另一个进程发送奇数。这两个过程是相同的,它们只是将数字附加到列表中
from multiprocessing import Process, Queue, Pipe
slist=['even','odd']
Q={}
Q['even'] = Queue()
Q['odd'] = Queue()
ev,od = [],[]
Q['even'].put(ev)
Q['odd'].put(od)
P={}
P['even'] = Pipe()
P['odd'] = Pipe()
def add_num(s):
""" The worker function, invoked in a process. The results are placed in
a list that's pushed to a queue."""
# while True :
if not P[s][1].recv():
print s,'- do nothing'
else:
d = Q[s].get()
print d
d.append(P[s][1].recv())
Q[s].put(d)
print Q[s].get()
P[s][0].send(False)
print 'ya'
def piper(s,n):
P[s][0].send(n)
for k in [S for S in slist if S != s]:
P[k][0].send(False)
add_num(s)
procs = [ Process (
target=add_num,
args=(i,)
)
for i in ['even','odd']]
for s in slist:
P[s][0].send(False)
for p in procs:
p.start()
p.join()
for i in range(10):
print i
if i%2==0:
s = 'even'
else:
s = 'odd'
piper(s,i)
print 'results:', Q['odd'].get(),Q['even'].get()
此代码生成以下内容:
偶数-什么也不做
如果智者能洞察这个问题,如果我的代码或推理有不足之处,我们将不胜感激 以下是一种我已经使用过好几次并取得成功的方法:
import multiprocessing
POISON_PILL = "STOP"
def process_odds(in_queue, shared_list):
while True:
# block until something is placed on the queue
new_value = in_queue.get()
# check to see if we just got the poison pill
if new_value == POISON_PILL:
break
# we didn't, so do the processing and put the result in the
# shared data structure
shared_list.append(new_value/2)
return
def process_evens(in_queue, shared_list):
while True:
new_value = in_queue.get()
if new_value == POISON_PILL:
break
shared_list.append(new_value/-2)
return
def main():
# create a manager - it lets us share native Python object types like
# lists and dictionaries without worrying about synchronization -
# the manager will take care of it
manager = multiprocessing.Manager()
# now using the manager, create our shared data structures
odd_queue = manager.Queue()
even_queue = manager.Queue()
shared_list = manager.list()
# lastly, create our pool of workers - this spawns the processes,
# but they don't start actually doing anything yet
pool = multiprocessing.Pool()
# now we'll assign two functions to the pool for them to run -
# one to handle even numbers, one to handle odd numbers
odd_result = pool.apply_async(process_odds, (odd_queue, shared_list))
even_result = pool.apply_async(process_evens, (even_queue, shared_list))
# this code doesn't do anything with the odd_result and even_result
# variables, but you have the flexibility to check exit codes
# and other such things if you want - see docs for AsyncResult objects
# now that the processes are running and waiting for their queues
# to have something, lets give them some work to do by iterating
# over our data, deciding who should process it, and putting it in
# their queue
for i in range(6):
if (i % 2) == 0: # use mod operator to see if "i" is even
even_queue.put(i)
else:
odd_queue.put(i)
# now we've finished giving the processes their work, so send the
# poison pill to tell them to exit
even_queue.put(POISON_PILL)
odd_queue.put(POISON_PILL)
# wait for them to exit
pool.close()
pool.join()
# now we can check the results
print(shared_list)
# ...and exit!
return
if __name__ == "__main__":
main()
输出
此代码生成以下输出:
[0.5,-0.0,1.5,-1.0,2.5,-2.0]
请注意,结果的顺序是不可预测的,因为我们无法保证函数能够以什么顺序从其队列中获取项目并将结果放入列表。但是你当然可以选择任何你需要的后处理,包括排序
根本原因
我认为这将是一个很好的解决方案,因为:
apply\u async
apply\u async
,以使多个工人在同一队列上工作。只要确保你给排队的人足够的毒药,这样所有的工人都能得到一片可能还有其他限制,但我想不出还有其他限制 如果您想要一个单元素元组,那么需要在末尾加一个逗号,就像这样
args=(i,)
谢谢。这确实消除了我的错误。但由于某些原因,代码仍然不起作用。我已经编辑了上面的问题,以反映新的状态,并让它在我继续处理时保持打开状态。add_num
函数中的print d
语句应引发异常。True。我已经修复并再次更新。我现在需要停止这方面的工作,也许是最好的,因为它完全让我迷惑。@Wapiti你能解释一下你在这里到底想做什么吗?对每一个使用队列
和管道
,都会造成混乱。您还将调用queue.get
,queue.put
,然后再调用queue.get
,所有这些都在辅助函数内。为什么呢?第一个get
调用如果碰到它,总是会导致死锁,因为您从来不会从父级向队列中放入任何内容。另外,您正在将False
加载到两个管道中,启动子管道,当它们调用if not P[s][1]时,会看到False