首页 > 解决方案 > 多处理池中的全局变量

问题描述

我知道这个问题之前已经在这里讨论过,但我找不到任何有效的方法。我想在我的多处理进程之间共享一个全局变量,而不需要任何进程更改它,即它们只需要读取访问权限。作为一个简单的例子,采取:

    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 是一个非常大的数组,这非常浪费。如何在进程之间轻松共享此全局变量,同时将其副本存储在内存中?我想重申,进程只需要读取这个全局变量而不改变它。

标签: pythonwindowsmultiprocessingpool

解决方案


由于您希望共享的变量是只读的并且是一个“简单”整数,因此您只需通过在全局范围内声明它来使其对多处理池中的子进程可见:

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)

推荐阅读