gpt4 book ai didi

python - python中的多处理模块和修改共享全局变量

转载 作者:太空宇宙 更新时间:2023-11-03 14:20:55 24 4
gpt4 key购买 nike

我编写了一个小型 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如何处理由创建的Processes读取/写入的全局变量的一些引用也会很棒。谢谢!

最佳答案

我认为内存有些困惑。您不使用多线程,而是使用多处理,因此每个工作线程都在单独的进程中运行,拥有自己的虚拟内存空间。因此,每个进程从一开始就有一个自己的 shared_var 副本。这是每次调用 f(x) 时都会修改的内容,而 __main__ 中的实际变量不受影响。

您可以查看the docs有关进程之间共享内存的章节,例如使用multiprocessing.Array

我不是 100% 确定为什么地址保持不变,但我认为由于每个新的子进程都是通过 fork 主进程并复制其内存布局而产生的,因此虚拟内存中的地址对于每个进程都保持相同这些 child 。物理内存地址当然是不同的。这就是为什么您会看到相同的 id,但值不同。

关于python - python中的多处理模块和修改共享全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47952171/

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