[英]What objects and variables are copied to child processes (by pickling) when I use Python 3 multiprocessing.pool?
在 Python 3 中创建多处理池时,我正在努力寻找有关将哪些对象和变量复制到子进程的答案。
换句话说,假设我有一个巨大的列表(~230000000 个元素)存储在一个类中,该类实现了一个使用四个子进程池的函数。 如果...,此列表是否会被复制到所有四个子进程?
注意:这个答案是部分的,因为我也无法(还)找到关于这个的书面证据和文件,但如果你愿意,下面给出了一些经验数据。
以下代码用于演示如何使用Pool
将数据传递/复制到子进程(实际列表l
不是故意在map
中使用以允许干净的打印):
from multiprocessing import Pool
import os
def process(x):
print(os.getpid(), __name__, 'l' in globals())
# A - l = list(range(100000))
if __name__ == "__main__":
# B - l = list(range(100000))
with Pool() as pool:
pool.map(process, [1,2,3,4])
print(os.getpid(), __name__, 'l' in globals())
取消注释A
时,打印输出类似于:
19604 __mp_main__ True
6392 __mp_main__ True
19604 __mp_main__ True
7048 __mp_main__ True
6568 __main__ True
将会给予。 这是因为列表是在__name__
保护之外定义的,并且由于 Windows 中的进程基本上import
py 文件,它们都定义了自己的l
版本。
取消注释B
时,打印输出类似于:
7248 __mp_main__ False
22644 __mp_main__ False
22676 __mp_main__ False
16520 __mp_main__ False
19736 __main__ True
将会给予。 即,由于列表是在__name__
守卫内定义的,因此只有__main__
进程定义了它,并且它通过map
将参数传递给不同的进程。
取消注释任何评论将给出类似于以下内容的打印输出:
25261 __main__ True
25262 __main__ True
25263 __main__ True
25264 __main__ True
25260 __main__ True
我猜这是因为 Linux 使用fork
来创建生成的进程,其中进程正在被“克隆” ,因此列表将以任何一种方式定义。
具体回答关于“spawn”使用的原始问题(正如OP所说,他们熟悉“fork”)
当创建一个进程对象时,它在main
中构造,然后使用命令行 args 执行一个新的 python 进程,以共享一对用于通信的文件句柄以及一个代码存根。
该“引导”代码将尝试import
主文件,这既是您需要防止导入时出现意外副作用的原因( if __name__ == "__main__":
),以及为什么该保护之外的任何内容都是“可用的”给孩子。 这主要是为了确保定义主文件中的函数,但也定义了在模块级别定义的任何变量。 这对于常量很有用,只要您有效地重新计算值并为每个进程制作一份副本并不重要。 对于大型数据集,这是非常低效的。
引导代码还将读取文件句柄之一,并尝试unpickle
父进程发送给它的进程对象。 该过程的目标通常是您定义的函数,但必须注意它在导入时可以在“主”命名空间中访问(没有 lambda,没有实例方法等)。 Python 不会使用 pickle 序列化代码对象,而是中继如何正确导入函数,这对于导入时没有具体命名空间的对象会变得很冒险(侧边栏,第 3 方multiprocess
库尝试通过使用dill
来解决这个问题pickle
一般都取得了很好的成功)。 当您对Process
类进行子类化并将其他数据附加到流程实例时,也会考虑到这一点; 这一切都必须是可腌制的。
一旦子进程成功地取消了进程对象,就会调用run
方法。 这通常是代码的入口点。 使用Pool
,有一个大类存在于主进程中,并使用预定义的函数启动“工作”进程,该函数接受“作业”并返回结果,直到被告知退出。 数据(由要执行的函数和该函数的参数组成的任务项)通过Queue
发送到工作人员和从工作人员发送,这与发送原始Process
对象的工作方式几乎相同:您放入队列的内容被腌制,发送通过文件句柄,并在孩子中未腌制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.