【问题标题】:Multiprocessing doesn't recreate object多处理不会重新创建对象
【发布时间】:2016-05-04 21:37:51
【问题描述】:

我创建了一个小代码 sn-p(原始代码要大得多),它调用一个创建对象的函数,但在一个进程池中:

import multiprocessing


class TestClass(object):
    pass


def func():
    obj = TestClass()
    cpname = multiprocessing.current_process().name
    print "{0}, Address: {1}".format(cpname, str(obj))


pool = multiprocessing.Pool(2)
results = [pool.apply_async(func) for _ in range(2)]

for res in results:
    res.get()

pool.close()
pool.join()

当我运行这段代码时,我得到以下输出:

PoolWorker-1, Address: <__main__.TestClass object at 0x7f05d3fdad50>
PoolWorker-2, Address: <__main__.TestClass object at 0x7f05d3fdad50>
  1. 我不明白的是,为什么这些对象具有相同的地址,即使它们位于不同的进程中?

  2. 如何确保每个进程都创建自己的对象?

非常感谢您的帮助。

【问题讨论】:

    标签: python multiprocessing


    【解决方案1】:

    当您fork() 进行多处理时,它会复制您的进程。父进程中的内存分配器和所有地址都会被复制到子进程中。这样一来,下一次分配的地址很可能是相同的。

    您可以像这样验证它们实际上是独立的对象:

    import time
    
    def func():
        obj = TestClass()
        obj.name = multiprocessing.current_process().name
        print obj.name, str(obj)
        time.sleep(1)
        print obj.name, str(obj)
    

    【讨论】:

    • 我已经运行了你的代码。结果让我有点困惑,因为地址仍然相同(或者是预期的):` PoolWorker-1 <__main__.testclass object at> PoolWorker-2 <__main__.testclass object at> PoolWorker-1 <__main__ .testclass> PoolWorker-2 <__main__.testclass> `
    • 由于虚拟寻址,地址应该相同。当您克隆一个程序以进行多处理时,虚拟地址不会改变,但底层物理内存会改变。
    【解决方案2】:

    对象不同,不同进程使用不同的virtual address space,不同进程中相同的地址指向不同的内存区域。

    如果你稍微改变你的例子,你会发现返回的对象是不同的:

    import multiprocessing
    
    class TestClass(object):
        pass
    
    def func():
        obj = TestClass()
        cpname = multiprocessing.current_process().name
        print "{0}, Address: {1}".format(cpname, str(obj))
        return obj
    
    pool = multiprocessing.Pool(2)
    results = [pool.apply_async(func) for _ in range(2)]
    
    results = [res.get() for res in results]
    
    pool.close()
    pool.join()
    
    print results
    

    【讨论】:

      【解决方案3】:

      您似乎正在使用类似 Linux 的系统,其中新进程是通过 fork() 创建的。在这种情况下,您应该预计地址之间有大量重叠。这并不意味着您的 obj 实例占用相同的物理内存 - 只是它们共享相同的虚拟(进程本地)地址。

      更多:

      What happens to address's, values, and pointers after a fork()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-17
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        相关资源
        最近更新 更多