【问题标题】:python parallel map (multiprocessing.Pool.map) with global data具有全局数据的python并行映射(multiprocessing.Pool.map)
【发布时间】:2012-04-12 07:11:25
【问题描述】:

我正在尝试在多个进程上调用一个函数。显而易见的解决方案是 python 的 multiprocessing 模块。问题是该功能有副作用。它创建一个临时文件并使用atexit.register 和全局列表注册要在退出时删除的文件。下面应该说明问题(在不同的上下文中)。

import multiprocessing as multi

glob_data=[]
def func(a):
    glob_data.append(a)

map(func,range(10))
print glob_data  #[0,1,2,3,4 ... , 9]  Good.

p=multi.Pool(processes=8)
p.map(func,range(80))

print glob_data  #[0,1,2,3,4, ... , 9] Bad, glob_data wasn't updated.

有没有办法更新全局数据?

请注意,如果您尝试上述脚本,您可能不应该从交互式解释器中尝试它,因为 multiprocessing 要求模块 __main__ 可以被子进程导入。

更新

在 func 中添加 global 关键字没有帮助 - 例如:

def func(a):  #Still doesn't work.
    global glob_data
    glob_data.append(a)

【问题讨论】:

    标签: python parallel-processing


    【解决方案1】:

    您需要列表glob_data 由共享内存支持,Multiprocessing 的管理器为您提供:

    import multiprocessing as multi
    from multiprocessing import Manager
    
    manager = Manager()
    
    glob_data = manager.list([])
    
    def func(a):
        glob_data.append(a)
    
    map(func,range(10))
    print glob_data  # [0,1,2,3,4 ... , 9] Good.
    
    p = multi.Pool(processes=8)
    p.map(func,range(80))
    
    print glob_data # Super Good.
    

    对于一些背景:

    https://docs.python.org/3/library/multiprocessing.html#managers

    【讨论】:

    • 干杯,这对我来说非常有效。我应该在这里提到它有效,因为我附加到 glob_data 的对象是不可变的(示例中的整数,实际应用程序中的字符串)。如果它们被打包到列表中的对象是可变的,那么如果它们被更改,则必须注意将它们重新添加到列表中。
    • @RafaelFerreira 效果很好!但结果并不一致,就像我的情况一样.. 使用 manager.dict(),每次运行代码时值都会发生变化。我看到应该应用锁,但不确定。
    【解决方案2】:

    让 func 返回一个元组,其中包含您想要的处理结果以及您想要附加到 glob_data 的内容。然后,当 p.map 完成后,您可以从返回的元组中的第一个元素中提取结果,然后可以从第二个元素中构建 glob_data。

    【讨论】:

    • 是的,我想到了……但是,我的用例比这要复杂一些。我要删除的临时文件深埋在类中,由于它们只是临时文件,我更喜欢将它们及其名称保留为类 API 的私有部分(实现细节)...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 2021-05-02
    • 1970-01-01
    相关资源
    最近更新 更多