【问题标题】:Why Python shared memory requires a copy?为什么 Python 共享内存需要一个副本?
【发布时间】:2021-02-02 03:17:21
【问题描述】:

我试图通过修改一个共享的 numpy 数组来构建一个新的 Python SharedMemory 类的简单示例。我在网上看到了一些例子:

Shared memory in multiprocessing

Is shared readonly data copied to different processes for multiprocessing?

但是,由于某种原因,它们都更改了__main__ 块内的共享数组,然后将其打印出来。但是,我想从函数中返回一个共享数组并在以后重用它。这是我的尝试:

from multiprocessing import shared_memory
import numpy as np


def create_shared_array():
    # instantiate array
    np_array = np.ones((5, 2, 2))
    # instantiate shared array
    shm = shared_memory.SharedMemory(size=np_array.nbytes, create=True)
    # copy data from original array into shared array
    array_shared = np.ndarray(np_array.shape, dtype=np_array.dtype, buffer=shm.buf)
    array_shared[:] = np_array[:]
    return shm


def change_and_return(name):
    existing_shm = shared_memory.SharedMemory(name=name, create=False)
    array_shared = np.ndarray((5, 2, 2), dtype=np.float64, buffer=existing_shm.buf)
    # change shared array
    array_shared[0] = 888
    return array_shared


shm = create_shared_array()
result = change_and_return(shm.name)
print(result)

由于某种原因,此代码在我的 Windows 机器上返回 "The instruction at <memory address> referenced memory at <another address>. The memory could not be read."

但是,如果我只是替换它

return array_shared

有了这个

return array_shared.copy()

然后它就可以正常工作了。

我的想法:

由于change_and_return 没有返回existing_shm,所以它会被垃圾回收,array_shared 也会被销毁。但是,我确实确保不要杀死 shm,所以引用应该仍然存在?

问题:为什么需要额外的副本以及避免制作额外副本的正确方法是什么?

更新:让我在这里澄清一下 - 我想更改共享内存中的数组值,但之后我想以非共享方式使用它.就像一个普通的 numpy 数组。所以问题基本上是是否可以在不复制的情况下将共享数组转回非共享数组?

【问题讨论】:

  • "那么它工作得很好。" - 不,它没有。该副本不受共享内存的支持。
  • 在这种情况下,该代码对我有用 - 它对你来说会破坏吗?
  • 它运行时不会引发异常,但它实际上并没有工作——它默默地失败了,做的事情与你的意图完全不同。同样,副本不受共享内存的支持。
  • “没有例外”和“作品”是完全不同的东西。

标签: python numpy shared-memory


【解决方案1】:

副本错误。它创建了一个由非共享内存支持的数组,完全违背了你正在做的事情的意义。

你这么说

但是,我确保不要杀死shm

但事实并非如此。你没有做任何事情来保持shm 活着。它死了,它的__del__ method 调用close,内存不再可访问。

您需要保留对shm 的引用,以确保内存仍然可以访问。此外,为了进行适当的清理,每个进程都应该在不再需要使用共享内存之后调用shm.close(),而单个进程应该在所有进程都调用close 之后调用shm.unlink()。否则,即使在程序终止后,您也可能会泄漏内存。 (在 Unix 上,Python 会产生一个 server process 来尝试防止这种情况发生,但它并不完全可靠,即使它工作,它也会延迟执行清理。)

【讨论】:

  • 对不起,但如果我在调用这两个函数后执行 shm.close(), existing_shm.close() 也会发生内存错误。使用array_shared而不是每次都与相应的SharedMemory类实例配对的正确方法是什么?
  • @Kreol:在您不再需要共享内存之后,您需要调用它。当你仍然需要内存时,你就调用它。
  • "使用array_shared而不是每次都与相应的SharedMemory类实例配对的正确方法是什么?" - 没有正确的方法可以做到这一点。您需要保留 SharedMemory 对象。
  • 在其他进程中对它进行转换后,我不需要“共享”array_shared。我只想在我的主进程中继续使用这个 numpy 数组。我想你的意思是,在这种情况下我必须制作另一个副本?
  • @Kreol:那就继续做一个非共享副本,但记得清理共享内存。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2018-08-04
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多