繁体   English   中英

Python多重处理-共享ID的单独进程中的全局变量?

[英]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]

我应该如何解释xid在所有进程中共享但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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM