我试图构建一个新 Python 的简单示例 SharedMemory通过修改共享 numpy 数组来创建类。我在网上看到了一些例子:
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)
出于某种原因,此代码返回 "The instruction at <memory address> referenced memory at <another address>. The memory could not be read."
在我的 Windows 机器上。
但是,如果我只是替换它
return array_shared
有了这个
return array_shared.copy()
然后就可以正常工作了。
我的想法:
自 change_and_return
不返回existing_shm
然后它被垃圾收集并 array_shared
也被摧毁了。不过,我确实确保不杀死shm
所以引用应该仍然存在?
问题:为什么需要额外的副本以及避免制作额外副本的正确方法是什么?
更新:让我在这里说清楚 - 我想更改共享内存中的数组值,但之后我想以非共享方式使用它。就像常规的 numpy 数组一样。所以问题基本上是是否可以在不复制的情况下将共享数组转回非共享数组?
最佳答案
文案错误。它创建了一个由非共享内存支持的数组,完全违背了您正在做的事情的意义。
你说的是
However, I do make sure not to kill
shm
但事实并非如此。您无需采取任何措施来保持 shm
的存活。它死了,它的__del__
method调用close
,并且内存不再可访问。
您需要保留对shm
的引用以确保内存仍然可以访问。此外,为了正确清理,每个进程都应在不再需要使用共享内存后调用 shm.close()
,并且单个进程应调用 shm.unlink()
> 在所有进程调用close
之后。否则,即使程序终止也会面临内存泄漏的风险。 (在 Unix 上,Python 生成 server process 来尝试防止这种情况,但它并不完全可靠,即使它有效,它也会在晚些时候执行清理。)
关于python - 为什么Python共享内存需要副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66003184/