恐怕这里实际上没有什么能像您 希望的那样 起作用:-(
首先请注意, 不同过程
id()产生 的 相同值 不会
告诉您对象是否真的是同一对象。每个进程都有自己的虚拟地址空间,由操作系统分配。两个进程中的相同虚拟地址可以引用完全不同的 物理
内存位置。您的代码是否产生相同的
id()输出几乎完全是偶然的。在多次运行中,有时我会
id()在您的
Process部分中看到不同的输出,并在您的部分中看到重复的
id()输出,
Pool反之亦然,或两者兼而有之。
其次,
Manager提供 语义 共享而不提供 物理 共享。您
numeri实例的数据 仅存
在于管理器进程中。您的所有辅助进程均查看(副本)代理对象。这些是精简包装,用于转发要由管理器进程执行的所有操作。这涉及许多进程间通信以及管理器进程内部的序列化。这是编写速度很慢的代码的好方法;-)是的,只有一个
numeri数据副本,但是对数据的所有工作都由一个进程(管理器进程)完成。
为了更清楚地看到这一点,建议进行@martineau的更改,并更改
get_list_id()为:
def get_list_id(self): # added method import os print("get_list_id() running in process", os.getpid()) return id(self.nl)这是示例输出:
41543664------------ Processproducing 42262032get_list_id() running in process 5856with list_id 44544608producing 46268496get_list_id() running in process 5856with list_id 44544608producing 42262032get_list_id() running in process 5856with list_id 44544608producing 44153904get_list_id() running in process 5856with list_id 44544608producing 42262032get_list_id() running in process 5856with list_id 44544608--------------- Poolproducing 41639248get_list_id() running in process 5856with list_id 44544608producing 41777200get_list_id() running in process 5856with list_id 44544608producing 41776816get_list_id() running in process 5856with list_id 44544608producing 41777168get_list_id() running in process 5856with list_id 44544608producing 41777136get_list_id() running in process 5856with list_id 44544608
明确?每次获得相同列表ID的原因 不是 因为每个工作进程 都具有 相同的
self.nl成员,而是因为所有
numeri方法
都在 单个进程(管理器进程)中运行。这就是列表ID始终相同的原因。
如果您在Linux-
y系统(支持的操作系统
fork())上运行,那么更好的主意是,
Manager在启动任何工作进程之前,请忘记所有这些东西,并在模块级别创建复杂的对象。然后,工作人员将继承您的复杂对象(地址空间副本)。通常的写时复制
fork()语义将使内存效率尽可能高。如果不需要将突变折叠到复杂对象的主程序副本中,这就足够了。如果确实需要将变异折回,那么您又需要进行大量的进程间通信,并且
multiprocessing相应地吸引力也就降低了。
这里没有简单的答案。不要开枪;-)



