Python 我试图了解如何通过多处理共享只读对象
我试图了解如何通过多处理共享只读对象。当它是全局变量时,共享Python 我试图了解如何通过多处理共享只读对象,python,python-2.7,shared-memory,python-multiprocessing,copy-on-write,Python,Python 2.7,Shared Memory,Python Multiprocessing,Copy On Write,我试图了解如何通过多处理共享只读对象。当它是全局变量时,共享bigset可以正常工作: from multiprocessing import Pool bigset = set(xrange(pow(10, 7))) def worker(x): return x in bigset def main(): pool = Pool(5) print all(pool.imap(worker, xrange(pow(10, 6)))) pool.close() pool
bigset
可以正常工作:
from multiprocessing import Pool
bigset = set(xrange(pow(10, 7)))
def worker(x):
return x in bigset
def main():
pool = Pool(5)
print all(pool.imap(worker, xrange(pow(10, 6))))
pool.close()
pool.join()
if __name__ == '__main__':
main()
htop
显示父进程使用100%的CPU和0.8%的内存,而工作负载在五个子进程之间均匀分布:每个子进程使用10%的CPU和0.8%的内存。一切都很好
但是如果我把bigset
移到main
里面,数字就开始疯狂了:
from multiprocessing import Pool
from functools import partial
def worker(x, l):
return x in l
def main():
bigset = set(xrange(pow(10, 7)))
_worker = partial(worker, l=bigset)
pool = Pool(5)
print all(pool.imap(_worker, xrange(pow(10, 6))))
pool.close()
pool.join()
if __name__ == '__main__':
main()
现在htop
显示2或3个进程在50%到80%的CPU之间上下跳跃,而其余进程使用的CPU不到10%。虽然父进程仍然使用0.8%的内存,但现在所有子进程都使用1.9%的内存
发生了什么?当您将
bigset
作为参数传递时,它会被父进程pickle,并被子进程取消pickle。[1][2]
酸洗和拆开一大套需要很多时间。这就解释了为什么很少有进程在执行它们的工作:父进程必须pickle很多大对象,子进程必须等待。父进程是一个瓶颈
酸洗参数意味着必须将参数发送到进程。从一个进程向另一个进程发送数据需要系统调用,这就是为什么用户空间代码没有看到100%的CPU使用率。部分CPU时间花在内核空间上。[3]
酸洗对象并将其发送到子流程也意味着:1。需要为pickle缓冲区提供内存;2.每个子流程都获得一个bigset
的副本。这就是为什么您会看到内存使用量的增加
相反,当bigset
是一个全局变量时,它不会发送到任何地方(除非您使用的是非fork变量)。它就像子进程一样被继承,使用fork()
的常规写时复制规则
脚注:
imap()
&co.在后台使用,队列通过酸洗/解酸洗对象来工作all(pool.imap(_worker,xrange(100)))
以加快进程),结果得到:用户时间2分钟,系统时间13秒。这几乎是10%的系统时间