我知道这个问题以前在这里讨论过,但我找不到任何有效的方法。我想在多处理进程之间共享一个全局变量,而不需要任何进程更改它,即它们只需要读取访问权限。举个简单的例子:
def f(x):
return x**GlobalVar
if __name__ == '__main__':
GlobalVar = 6
pool = multiprocessing.Pool()
res= pool.map(f,[1,2,3,4])
print(res)
现在,这显然不起作用,因为进程将无法访问GlobalVar。所以为了让它发挥作用,我会在每个单独的过程中评估GlobalVar,或者从文件中导入它。在我的应用程序中,GlobalVar是一个非常大的数组,这是非常浪费的。如何在进程之间轻松共享此全局变量,同时只将其一个副本存储在内存中?我想重申,过程只需要读取这个全局变量,而不需要更改它
非常简单的方法是将其作为参数传递给在每个进程中执行的f
。但是,如果全局变量太大,并且您不希望在每个进程中都有它的副本,并且您只想执行读取操作,那么您可以使用共享内存。
示例(联机文档(
from multiprocessing import Pool
from multiprocessing import shared_memory
import numpy as np
def f(x):
# Attach to the existing shared memory
existing_shm = shared_memory.SharedMemory(name='abc123')
# Read from the shared memory (we know the size is 1)
c = np.ndarray((1,), dtype=np.int64, buffer=existing_shm.buf)
return x*c[0]
if __name__ == '__main__':
a = np.array([6])
# Creates shared memory with name abc123
shm = shared_memory.SharedMemory(create=True, size=a.nbytes, name="abc123")
# Create numpy array backed by shared memory
b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
# copy the data into shared memory
b[:] = a[:]
with Pool(5) as p:
print(p.map(f, [1, 2, 3]))
输出:
[6, 12, 18]
在此处查找官方文档。
由于要共享的变量是只读的;简单的";integer,您只需要通过在全局范围内声明它来使它对多处理池中的子进程可见:
import multiprocessing
GlobalVar = 6
def f(x):
return x**GlobalVar
if __name__ == '__main__':
pool = multiprocessing.Pool()
res= pool.map(f,[1,2,3,4])
print(res)
打印:
[1, 64, 729, 4096]
讨论
当讨论Python和多处理时,它总是相关的,您在哪个平台上运行,我已经更新了您的标记以添加Windows
(尽管(现在编写的代码也可以在Linux上工作。
在Windows上,当创建新进程(或创建进程池时的进程(时,将使用spawn
。这意味着新进程不会继承主进程建立的变量,而是为每个新进程启动一个新的Python解释器,并从程序的顶部开始执行。这就是为什么必须将启动新进程的代码包含在if __name__ == '__main__':
块中,否则将进入递归循环。但由于这个原因,您必须将GlobalVar
的声明移动到全局范围,否则将不会为新创建的进程定义该变量。
初始化池中每个子进程的全局变量的另一种方法是使用池初始化器函数,它使您能够做比下面演示的更详细的事情:
import multiprocessing
def init_pool(the_int):
global GlobalVar
GlobalVar = the_int
def f(x):
return x**GlobalVar
if __name__ == '__main__':
GlobalVar = 6
pool = multiprocessing.Pool(initializer=init_pool, initargs=(GlobalVar,))
res= pool.map(f,[1,2,3,4])
print(res)