首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当我使用Python3 multiprocessing.pool时,哪些对象和变量被复制到子进程(通过腌制)?

当我使用Python3 multiprocessing.pool时,哪些对象和变量被复制到子进程(通过腌制)?
EN

Stack Overflow用户
提问于 2022-07-21 09:55:04
回答 2查看 108关注 0票数 0

在Python 3中创建多处理池时,我很难找到将哪些对象和变量复制到子进程的答案。

换句话说,假设我有一个巨大的列表(~230000000个元素)存储在一个类中,该类实现了一个使用四个子进程池的函数。然后将此列表复制到所有四个子进程中,如果。

  1. 子进程不从列表读取?
  2. 从列表读取的子进程(但是,列表没有修改)?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-21 10:28:48

Note:这个答案是部分的,因为我也找不到关于这方面的书面证据和文档,但如果你愿意的话,下面给出一些经验性的数据。

下面的代码用于演示如何使用Pool将数据传递/复制到子进程(实际列表lmap中不用于允许干净的打印):

代码语言:javascript
复制
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())

在Windows上

当取消注释A时,打印输出类似于:

代码语言:javascript
复制
19604 __mp_main__ True
6392 __mp_main__ True
19604 __mp_main__ True
7048 __mp_main__ True
6568 __main__ True

将被给予。这是因为列表是在之外定义的-- __name__保护,而作为Windows中的进程--基本上是py文件--它们都定义了自己的l版本。

当取消注释B时,打印输出类似于:

代码语言:javascript
复制
7248 __mp_main__ False
22644 __mp_main__ False
22676 __mp_main__ False
16520 __mp_main__ False
19736 __main__ True

将被给予。也就是说,由于列表是在__name__保护中定义的,只有__main__进程才定义了它,并且它将参数通过map传递给不同的进程。

在Linux上

取消对任何评论的注释将提供类似于以下内容的打印输出:

代码语言:javascript
复制
25261 __main__ True
25262 __main__ True
25263 __main__ True
25264 __main__ True
25260 __main__ True

我猜想这是因为Linux使用fork来创建生成的进程,其中进程被“克隆”,因此列表将被定义为任意一种方式。

票数 1
EN

Stack Overflow用户

发布于 2022-07-21 14:56:50

具体地回答原来的问题,特别是关于“产卵”的用法(正如OP所提到的,他们熟悉“叉子”)

当创建流程对象时,它是用main构造的,然后使用命令行args执行一个新的process,以共享一对用于通信的文件句柄以及一个代码存根。

“引导”代码将尝试对主文件进行import,这就是为什么您需要对导入的意外副作用(if __name__ == "__main__":)进行保护,以及为什么在该保护之外的任何内容对子文件都是“可用的”。这主要是为了确保主文件中的函数是定义的,但是在模块级别上定义的任何变量也都是定义的。这对于常量非常有用,只要您有效地重新计算值并为每个进程创建一个副本并不重要。对于大型数据集,这是非常低效率的。

引导代码还将读取其中一个文件句柄,并尝试unpickle父程序发送给它的进程对象。流程的目标通常是您定义的函数,但是必须注意在导入的"main“命名空间中可以访问它(没有lambda,没有实例方法等等)。Python不使用泡菜序列化代码对象,而是传递如何正确导入函数,该函数与导入中没有具体命名空间的对象(侧栏,第三方multiprocess库试图通过使用dill而不是pickle来解决这个问题以获得普遍的成功)有风险。在子类Process类并将其他数据附加到流程实例时,也会考虑到这一点;这些数据都必须是可选择的。

一旦进程对象未被子进程成功地选中,就会调用run方法。这通常是代码的切入点。对于Pool,有一个大型类驻留在主进程上,并启动带有预定义函数的"worker“进程,该函数接收”作业“并返回结果,直到被告知退出为止。数据(由要执行的函数和该功能的args组成的任务项)通过Queue发送到和从工作人员那里发送,这与发送原始Process对象几乎一样:您放入队列中的东西被腌制、通过文件句柄发送,并且在子队列中没有被腌制。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73064110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档