能否跨进程共享非空NumPy数组?如何保留其共享前的预赋值?
问题根因
这是代码逻辑导致的正常结果,不属于SharedMemory模块的异常。核心原因是编写的代码从未将预先赋值的数组内容写入共享内存:
- 主进程中提前创建的数组
a,存储在主进程的私有堆内存中,和后续新开辟的共享内存块没有任何内存层面的关联 - 调用
SharedMemory(create=True)时,操作系统会开辟一块全新的、默认全零初始化的共享内存,这块内存从创建开始就没有存储你给a['value']设置的100值 - 将共享内存缓冲区绑定为ndarray对象
c后,全程没有执行数据拷贝操作,共享内存从始至终都是全零状态,子进程挂载这块共享内存时自然只能读到0值。
修复方法
只需要在主进程绑定好共享内存对应的ndarray后,将预赋值完成的源数组内容拷贝进共享内存即可。另外原代码中将普通数组a作为进程入参是多余操作:跨进程传参时,框架会将该数组序列化后深拷贝到子进程的私有内存中,既不参与共享,还会产生重复的内存开销,可直接移除。
修复后的完整可运行代码
from multiprocessing import Process, shared_memory import numpy as np import time dtype_eV = np.dtype({ 'names': ['idx', 'value', 'size'], 'formats': ['int32', 'float64', 'float64'] }) def worker_writer(shm_name): exst_shm = shared_memory.SharedMemory(name=shm_name) b = np.ndarray((5,), dtype=dtype_eV, buffer=exst_shm.buf) for i in range(5): time.sleep(0.5) b['idx'][i] = i def worker_reader(shm_name): exst_shm = shared_memory.SharedMemory(name=shm_name) b = np.ndarray((5,), dtype=dtype_eV, buffer=exst_shm.buf) for i in range(5): time.sleep(1) print(b['idx'][i], b['value'][i]) if __name__ == "__main__": # 先在普通内存中完成所有预赋值操作 a = np.zeros(5, dtype=dtype_eV) a['value'] = 100 # 创建和目标数组大小匹配的共享内存块 shm = shared_memory.SharedMemory(create=True, size=a.nbytes) # 将共享内存缓冲区绑定为ndarray对象 c = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf) # 核心缺失步骤:将预赋值的数组内容全部拷贝到共享内存 c[:] = a th1 = Process(target=worker_writer, args=(shm.name,)) th2 = Process(target=worker_reader, args=(shm.name,)) th1.start() th2.start() th1.join() th2.join() # 清理共享内存,避免系统资源泄漏 shm.close() shm.unlink()
修复后的运行结果
0 100.0 1 100.0 2 100.0 3 100.0 4 100.0
关键注意点
SharedMemory模块仅负责开辟跨进程可访问的内存块,不会自动关联主进程中其他位置的数组数据,所有初始的非空值必须主动拷贝到共享内存的缓冲区中- 跨进程传递共享内存时,只需要传递共享内存的唯一名即可,不要将ndarray对象本身作为参数传递,否则会触发深拷贝,失去内存共享的意义
- 共享内存使用完成后,必须执行
close和unlink操作释放系统资源,否则对应的共享内存块会一直残留占用内存。
内容的提问来源于stack exchange,提问作者maynull
相关产品推荐
相关产品推荐

