【问题标题】:Python multiprocessing: object passed by value?Python多处理:按值传递的对象?
【发布时间】:2015-03-08 05:40:22
【问题描述】:

我一直在尝试以下方法:

from multiprocessing import Pool

def f(some_list):
    some_list.append(4)
    print 'Child process: new list = ' + str(some_list)
    return True

if __name__ == '__main__':

    my_list = [1, 2, 3]
    pool = Pool(processes=4)
    result = pool.apply_async(f, [my_list])
    result.get()

    print 'Parent process: new list = ' + str(my_list)

我得到的是:

Child process: new list = [1, 2, 3, 4]
Parent process: new list = [1, 2, 3]

因此,这意味着 my_list 是按值传递的,因为它没有发生变异。 那么,传递给另一个进程的时候,是不是真的是按值传递的规则呢? 谢谢。

【问题讨论】:

    标签: python threadpool pass-by-reference pass-by-value python-multiprocessing


    【解决方案1】:

    multiprocessing 库使用pickle 序列化对象以在进程之间传递它们。

    这确保了安全的进程间通信,两个进程可以使用“相同”的对象而不使用共享内存。

    【讨论】:

    • 你应该用“进程”替换上面的每个“线程”实例。
    【解决方案2】:

    正如 André Laszlo 所说,multiprocessing 库需要腌制所有传递给 multiprocessing.Pool 方法的对象,以便将它们传递给工作进程。酸洗过程会导致在工作进程中创建一个不同的对象,因此对工作进程中的对象所做的更改不会影响父进程中的对象。在 Linux 上,对象有时会通过fork 继承(例如multiprocessing.Process(target=func, args=(my_list,)))传递给子进程,但在这种情况下,您最终会在子进程中获得对象的写时复制版本,所以您仍然结束当您尝试在任一进程中对其进行修改时,都会生成不同的副本。

    如果您确实想在进程之间共享一个对象,您可以使用multiprocessing.Manager

    from multiprocessing import Pool, Manager
    
    def f(some_list):
        some_list.append(4)
        print 'Child process: new list = ' + str(some_list)
        return True
    
    if __name__ == '__main__':
    
        my_list = [1, 2, 3]
        m = Manager()
        my_shared_list = m.list(my_list)
        pool = Pool(processes=4)
        result = pool.apply_async(f, [my_shared_list])
        result.get()
    
        print 'Parent process: new list = ' + str(my_shared_list)
    

    输出:

    Child process: new list = [1, 2, 3, 4]
    Parent process: new list = [1, 2, 3, 4]
    

    【讨论】:

    • 谢谢。如果我只是让我的 f 函数返回修改后的对象怎么办?与使用 Manager 相比,我会在效率上损失很多吗?
    • @jazzblue 如果您的用例允许您只修改子列表并将其返回给父列表,请使用它而不是Manager。使用Manager 对象,每次访问共享列表时,实际上都是在对Manager 进程进行IPC 调用。这比本地访问列表要慢很多。通过将对象返回给父级,您确实可以在进程之间将列表对象传回的一次性 IPC 命中,但除非您正在处理一个 huge 列表,否则这可能不会超过共享列表所需的所有 IPC 的成本。
    猜你喜欢
    • 2016-07-22
    • 2014-08-25
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 2013-05-18
    • 2018-07-20
    • 2011-11-24
    • 1970-01-01
    相关资源
    最近更新 更多