gpt4 book ai didi

python - 我试图了解如何与多处理共享只读对象

转载 作者:行者123 更新时间:2023-11-28 18:33:21 28 4
gpt4 key购买 nike

我正在尝试了解如何与多处理共享只读对象。当它是全局变量时共享 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 之间上下跳跃,而其余进程使用不到 10% 的 CPU。虽然父进程仍使用 0.8% 的内存,但现在所有子进程都使用 1.9% 的内存。

发生了什么事?

最佳答案

当你通过 bigset作为参数,它由父进程 pickle 并由子进程 unplickled。[1][2]

<子>

对大型集合进行 pickling 和 unpickling 需要大量时间。这就解释了为什么你看到很少有进程在做他们的工作:父进程必须 pickle 很多大对象,而子进程必须等待它。父进程是一个瓶颈。

酸洗参数意味着必须将参数发送到进程。将数据从一个进程发送到另一个进程需要系统调用,这就是为什么您没有看到用户空间代码使用 100% CPU 的原因。部分 CPU 时间花费在内核空间上。[3]

Pickling 对象并将它们发送到子进程也意味着: 1. 您需要 pickle 缓冲区的内存; 2. 每个子进程得到一份bigset .这就是您看到内存使用量增加的原因。

相反,当 bigset是一个全局变量,它不会发送到任何地方(除非您使用的是 start method 而不是 fork)。它只是由子进程按原样继承,使用通常的写时复制规则 fork() .


脚注:

  1. 如果您不知道“pickling”是什么意思:pickle是将任意 Python 对象与字节序列相互转换的标准 Python 协议(protocol)之一。

  2. imap() &公司使用 queues在幕后,队列通过 pickling/unpickling 对象来工作。

  3. 我尝试运行您的代码(使用 all(pool.imap(_worker, xrange(100))) 以使过程更快),我得到:2 分钟用户时间,13 秒系统时间。这几乎是系统时间的 10%。

关于python - 我试图了解如何与多处理共享只读对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34880821/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com