Python中的多处理模块并修改共享的全局变量



我写了一个小的python程序,以查看我是否了解全局变量是如何传输到"儿童"过程的。

import time
import random
shared_var = range(12)
def f(x):
    global shared_var
    time.sleep(1+random.random())
    shared_var[x] = 100
    print x, multiprocessing.current_process(), shared_var
    return x*x
if __name__ == '__main__':
    pool = multiprocessing.Pool(4)
    results = pool.map(f, range(8))
    print results
    print shared_var

当我运行时,我会得到

3 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 4, 5, 6, 7, 8, 9, 10, 11]
0 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
2 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 6, 7, 8, 9, 10, 11]
1 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
4 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 100, 5, 6, 7, 8, 9, 10, 11]
5 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 100, 6, 7, 8, 9, 10, 11]
6 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 100, 7, 8, 9, 10, 11]
7 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 6, 100, 8, 9, 10, 11]
[0, 1, 4, 9, 16, 25, 36, 49]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

这是合乎逻辑的,因为孩子的过程修改了全局变量,因此,在写入机制使孩子的过程修改全局变量时,它会被复制,因此仅在产生的过程中可见任何更改。

我惊讶的是,当我修改代码以打印变量的标识符时:

import multiprocessing
import time
import random
shared_var = range(12)
def f(x):
    global shared_var
    time.sleep(1+random.random())
    shared_var[x] = 100
    print x, multiprocessing.current_process(), shared_var, id(shared_var)
    return x*x
if __name__ == '__main__':
    pool = multiprocessing.Pool(4)
    results = pool.map(f, range(8))
    print results
    print shared_var, id(shared_var)

并得到:

3 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968
0 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968
1 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968
2 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968
6 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 100, 7, 8, 9, 10, 11] 4504973968
7 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 6, 100, 8, 9, 10, 11] 4504973968
4 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 100, 5, 6, 7, 8, 9, 10, 11] 4504973968
5 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 100, 6, 7, 8, 9, 10, 11] 4504973968
[0, 1, 4, 9, 16, 25, 36, 49]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968

所有变量的标识符(在主线程和产卵过程中)是相同的,而我期望每个过程的副本...

有人知道我为什么得到这些结果吗?同样,关于multiprocessing如何处理由创建的Process ES读取/编写的全局变量的一些引用也很棒。谢谢!

我认为记忆有些混乱。您不使用多线程,而是多处理,因此每个工人都在一个单独的过程中运行,具有自己的虚拟内存空间。因此,从一开始,每个过程都有自己的shared_var副本。这就是每个呼叫f(x)的修改的方法,而__main__中的实际变量不受影响。

您可以检查文档中有关在过程之间共享内存的章节,例如使用multiprocessing.Array

我不是100%确定为什么该地址保持不变,但是我认为,由于每个新的子过程都通过分配主过程并复制其内存布局来产生每个新子过程这些孩子。物理内存地址当然是不同的。这就是为什么您会看到相同的id,但值不同。

您可能知道CPYTHON中的id(x)实际上正在访问对象的内存地址。

请求检查https://superuser.com/questions/3477765/is-virtual-memory-recated-to-virtual-dirtual-address-pirtual-address-space-firces-fircess-opocess,为什么在不同的过程中虚拟内存地址相同?。基本上n操作系统将虚拟内存地址安排到该过程的每个过程,该过程对对象的实际(物理)内存地址不了解。

相关内容

  • 没有找到相关文章

最新更新