BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #22866同步于 2018/9/14
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

【问题】请教一个关于python multiprocessing shared-dict 的问

BruceWayne94
2018/9/14镜像同步15 回复
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})? 请各位大神帮忙指点一下~
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
BruceWayne94机器人#1 · 2018/9/14
自己bd一下
BruceWayne94机器人#2 · 2018/9/14
bd 发自「贵邮」
BruceWayne94机器人#3 · 2018/9/14
bd 发自「贵邮」
fuxuemingzhu机器人#4 · 2018/9/14
马克,以前遇到过这个问题,我也没找到解决办法
Forer机器人#5 · 2018/9/14
python的processing本身就是两个完全不同的程序,共享内存是比较困难的,以前尝试过传递socket,要用很多底层api才能做到。lz考虑下thread?或者dict写进文件再从另一个process读出来。另外考虑下其他语言如何
BruceWayne94机器人#6 · 2018/9/14
谢谢你的建议 我回去试一下![em68] 【 在 Forer 的大作中提到: 】 : python的processing本身就是两个完全不同的程序,共享内存是比较困难的,以前尝试过传递socket,要用很多底层api才能做到。lz考虑下thread?或者dict写进文件再从另一个pro : ......... 发自「贵邮」
yo1995机器人#7 · 2018/9/14
半夜没人怒答一发,不知道对不对,烦请指正[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时自己常预先申请一大块内存,把每个“进程”的结果分别存到不同的地址,最后再进行汇总,以避免读写的冲突。这样虽然浪费一些内存和时间,但逻辑比较简单,不容易产生与加锁相关的问题。
yo1995机器人#8 · 2018/9/14
当然,上述肯定存在诸多不足,还可以参考:https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem 来进一步分析 不知道有没有具有atomic性质的自增能够满足上述需求……还请大佬解答
BruceWayne94机器人#9 · 2018/9/15
打这么多字 辛苦了 感谢! 看了大佬的回答,确实感觉不太适合用multiprocessing ,我还是老老实实sequence去处理吧 再次谢谢大佬! 【 在 yo1995 的大作中提到: 】 : 半夜没人怒答一发,不知道对不对,烦请指正[ema30] : : 猜测题主想法应该类似于“无需关心运算的顺序,只要最后加到结果即可”。但是,这个想法忽略了一个问题,即读写安全。在共享的内存中,很有可能 : ......... 发自「贵邮」