[英]Python multiprocessing--global variables in separate processes sharing id?
从这个问题中我了解到:
当您使用多重处理打开第二个进程时,将创建一个具有自己全局状态的Python全新实例。 该全局状态不会共享,因此子进程对全局变量所做的更改对于父进程将是不可见的。
为了验证此行为,我做了一个测试脚本:
import time
import multiprocessing as mp
from multiprocessing import Pool
x = [0] # global
def worker(c):
if c == 1: # wait for proc 2 to finish; is global x overwritten by now?
time.sleep(2)
print('enter: x =', x, 'with id', id(x), 'in proc', mp.current_process())
x[0] = c
print('exit: x =', x, 'with id', id(x), 'in proc', mp.current_process())
return x[0]
pool = Pool(processes=2)
x_vals = pool.map(worker, [1, 2])
print('parent: x =', x, 'with id', id(x), 'in proc', mp.current_process())
print('final output', x_vals)
输出(在CPython上)类似于
enter: x = [0] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-2, started daemon)>
exit: x = [2] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-2, started daemon)>
enter: x = [0] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-1, started daemon)>
exit: x = [1] with id 140138406834504 in proc <ForkProcess(ForkPoolWorker-1, started daemon)>
parent: x = [0] with id 140138406834504 in proc <_MainProcess(MainProcess, started)>
final output [1, 2]
我应该如何解释x
的id
在所有进程中共享但x
取不同值的事实? 从概念上讲, id
不是Python对象的内存地址吗? 我想如果在子进程中克隆内存空间,这是可能的。 那有什么我可以用来获取Python对象的实际物理内存地址的东西吗?
共享状态
当您使用多重处理打开第二个进程时,将创建一个具有自己全局状态的Python全新实例。 该全局状态不会共享,因此子进程对全局变量所做的更改对于父进程将是不可见的。
这里的关键点似乎是:
这种全球状态不会共享...”
... 指的是子进程的全局状态。 但这并不意味着父级的全局状态的一部分不能与子进程共享,只要子进程不尝试写入该部分。 发生这种情况时,将复制并更改此部分获取,并且父级将看不到该部分。
背景:
在Unix上, “ fork”是启动子进程的默认方式:
父进程使用os.fork()派生Python解释器。 子进程开始时实际上与父进程相同。 父进程的所有资源均由子进程继承。 请注意,安全地分叉多线程进程是有问题的。
仅在Unix上可用。 Unix上的默认值。
Fork是使用写时复制实现的,因此除非您为x
分配新对象,否则不会进行复制,并且子进程与其父进程共享相同的列表。
内存地址
我应该如何解释x的ID在所有进程中共享但x取不同值的事实?
Fork创建一个子进程,其中虚拟地址空间与父进程的虚拟地址空间相同。 虚拟地址将全部映射到相同的物理地址,直到发生写时复制。
现代操作系统使用虚拟寻址。 基本上,您在程序内部看到的地址值(指针)不是实际的物理内存位置,而是指向索引表(虚拟地址)的指针,而索引表又包含指向实际的物理内存位置的指针。 由于这种间接方式,如果虚拟地址属于不同进程的索引表,则可以将同一虚拟地址指向不同的物理地址。 链接
那有什么我可以用来获取Python对象的实际物理内存地址的东西吗?
似乎没有办法获取实际的物理内存地址( link )。 id
返回虚拟 (逻辑)内存地址(CPython)。 从虚拟内存到物理内存地址的实际转换属于MMU 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.