在这种情况下,多处理过程是否会复制对象?

import multiprocessing
import numpy as np
import multiprocessing as mp
import ctypes

class Test():
    def __init__(self):
        shared_array_base = multiprocessing.Array(ctypes.c_double,100,lock=False)
        self.a = shared_array = np.ctypeslib.as_array(shared_array_base)

    def my_fun(self,i):
        self.a[i] = 1

if __name__ == "__main__":
    num_cores = multiprocessing.cpu_count()

    t = Test()

    def my_fun_wrapper(i):
        t.my_fun(i)

    with mp.Pool(num_cores) as p:
        p.map(my_fun_wrapper,np.arange(100))

    print(t.a)

在上面的代码中,我试图使用 multiprocessing 编写代码以修改数组。在每个过程中执行的函数 my_fun() 应该修改索引 a[:] i 的值/ strong>作为参数传递给my_fun()。关于上面的代码,我想知道正在复制什么。

1)每个进程都在复制代码中的任何内容吗?我认为对象可能是,但理想情况下什么也不是。

2)有没有一种方法可以对对象使用包装函数my_fun()

humingming001 回答:在这种情况下,多处理过程是否会复制对象?

除了用multiprocessing.Array分配的共享内存外,几乎所有代码都将被复制。 multiprocessing充满了不直观的隐式副本。


当您在multiprocessing中生成新流程时,新流程几乎需要原始流程中所有内容的版本。根据平台和设置的不同,处理方式也有所不同,但是我们可以告诉您使用的是“ fork”模式,因为您的代码无法在“ spawn”或“ forkserver”模式下工作-您会收到有关错误的错误信息能够找到my_fun_wrapper。 (Windows仅支持“ spawn”,因此我们可以告诉您不在Windows上。)

在“分叉”模式下,此初始副本是通过使用fork系统调用来要求操作系统本质上复制整个过程以及内部所有内容的。由multiprocessing.Array分配的内存属于“外部”内存,不会被复制,但是大多数其他东西都是。 (还有写时复制优化,但是写时复制仍然像复制所有内容一样工作,并且由于引用计数更新,该优化在Python中效果不佳。)

将任务分派到工作进程时,multiprocessing需要制作更多副本。任何参数以及任务本身的可调用对象都是主流程中的对象,而对象固有地仅存在于一个流程中。工人无法访问任何一个。他们需要自己的版本。 multiprocessing通过腌制可调用对象和参数,通过进程间通信发送序列化的字节并在工作人员中腌制腌菜来处理第二轮副本。


当主泡菜my_fun_wrapper时,泡菜只会说“在my_fun_wrapper模块中寻找__main__函数,而工作人员会查询他们的my_fun_wrapper版本解开它。 my_fun_wrapper寻找全局t,在工作进程中,t由fork产生,而fork产生t,其数组由共享内存支持您分配了原始multiprocessing.Array通话。

另一方面,如果您尝试将t.my_fun传递给p.map,则multiprocessing必须腌制和释放方法对象。所得的pickle不会说“查找t全局变量并获取其my_fun方法”。泡菜说要构建一个 new Test实例并获取 its my_fun方法。泡菜没有任何有关使用分配的共享内存的说明,并且生成的Test实例及其数组与您要修改的原始数组无关。


我知道没有什么好方法可以避免需要某种包装函数。

本文链接:https://www.f2er.com/3098370.html

大家都在问