返回信息流https://user-images.githubusercontent.com/20760190/45560046-0eade680-b812-11e8-820c-bdaf07cf771e.png
如图,想请教一下各位大神,使用python multiprocessing 提供的Pool()的时候该 如何做到对一个共享的dict进行更新呢?如果直接讲dict作为参数(multi()函数)传入更新函数中, 结果是dict完全没有更新。
我在Stack Overflow上看到有人说可以用manager.dict(), 但是我使用了以后(multi2函数中)得到的结果与我预期不同(正常来说程序结束以后的结果应该是{‘a’:100,'b':100})?
请各位大神帮忙指点一下~
这是一条镜像帖。来源:北邮人论坛 / python / #22866同步于 2018/9/14
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖
【问题】请教一个关于python multiprocessing shared-dict 的问
BruceWayne94
2018/9/14镜像同步15 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
python的processing本身就是两个完全不同的程序,共享内存是比较困难的,以前尝试过传递socket,要用很多底层api才能做到。lz考虑下thread?或者dict写进文件再从另一个process读出来。另外考虑下其他语言如何
谢谢你的建议 我回去试一下![em68]
【 在 Forer 的大作中提到: 】
: python的processing本身就是两个完全不同的程序,共享内存是比较困难的,以前尝试过传递socket,要用很多底层api才能做到。lz考虑下thread?或者dict写进文件再从另一个pro
: .........
发自「贵邮」
半夜没人怒答一发,不知道对不对,烦请指正[ema30]
猜测题主想法应该类似于“无需关心运算的顺序,只要最后加到结果即可”。但是,这个想法忽略了一个问题,即读写安全。在共享的内存中,很有可能上一个进程还未写入,下一个进程就已经读取,从而造成 += 1并非想要的结果。
题主的test函数实际上是一个需要频繁读写的任务。关于各类任务在Python多线程中适用可以参考: https://segmentfault.com/a/1190000007495352 通信开销远大于运算开销,个人看来并不是特别适合用multiprocessing进行处理。
不过既然希望用mp,那也可以通过加锁解决。如下
from multiprocessing import Manager, Pool, Lock
import time
def test(d, l):
l.acquire()
d['a'] += 1
d['b'] += 1
l.release()
def multi():
with Manager() as manager:
dct = manager.dict({'a': 0, 'b': 0})
pool = Pool()
l = manager.Lock()
for i in range(1000):
pool.apply_async(test, args=(dct, l, ))
pool.close()
pool.join()
return dict(dct)
def single():
dct = dict({'a': 0, 'b': 0})
for i in range(1000):
dct['a'] += 1
dct['b'] += 1
return dict(dct)
def buggy():
# where is my 100? :-(
with Manager() as manager:
dct = manager.dict({'a': 0})
pool = Pool()
for i in range(100):
pool.apply_async(test, args=(dct,))
pool.close()
pool.join()
return dict(dct)
if __name__ == '__main__':
t1 = time.time()
a = multi()
print('mp time used: ' + str(time.time() - t1))
print('result is: ', a)
t2 = time.time()
b = single()
print('single time used: ' + str(time.time() - t2))
print('result is: ', b)
运行结果多进程不仅吃满CPU,而且时间远高于单线程执行。对于这个任务来说mp确实不太适合。
之前自己写的代码里用多用threading来处理网络请求,mp来处理高计算量或阻塞时间长的任务(多核不用白不用);需要频繁读写同一块内存的任务,写成顺序执行反而比较方便。另外,用mp时自己常预先申请一大块内存,把每个“进程”的结果分别存到不同的地址,最后再进行汇总,以避免读写的冲突。这样虽然浪费一些内存和时间,但逻辑比较简单,不容易产生与加锁相关的问题。
当然,上述肯定存在诸多不足,还可以参考:https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem 来进一步分析
不知道有没有具有atomic性质的自增能够满足上述需求……还请大佬解答
打这么多字 辛苦了 感谢! 看了大佬的回答,确实感觉不太适合用multiprocessing ,我还是老老实实sequence去处理吧 再次谢谢大佬!
【 在 yo1995 的大作中提到: 】
: 半夜没人怒答一发,不知道对不对,烦请指正[ema30]
:
: 猜测题主想法应该类似于“无需关心运算的顺序,只要最后加到结果即可”。但是,这个想法忽略了一个问题,即读写安全。在共享的内存中,很有可能
: .........
发自「贵邮」