如何在Linux下的Jupyter Notebook间共享大型numpy数组且避免内存重复?
在Linux下的Python进程(含Jupyter Notebook)间共享大型Numpy数组(无内存副本)
以下是几种实用的实现方案,均能避免在内存中保留多份数组副本:
方法1:Python 3.8+ 官方共享内存方案(multiprocessing.shared_memory)
这是跨进程共享内存的首选方案,支持同一机器上的任意Python进程(包括不同Jupyter内核)。
步骤1:创建共享内存并写入数组(进程A,如某Jupyter Notebook)
import numpy as np from multiprocessing import shared_memory # 生成测试用大型数组 big_array = np.random.rand(10000, 10000) # 约800MB # 创建共享内存块,大小匹配数组字节数 shm = shared_memory.SharedMemory(create=True, size=big_array.nbytes) # 绑定共享内存到Numpy数组视图(无数据副本) shared_array = np.ndarray(big_array.shape, dtype=big_array.dtype, buffer=shm.buf) # 仅一次数据复制,将原数组内容写入共享内存 shared_array[:] = big_array[:] # 记录关键参数,供其他进程使用 print(f"共享内存名称: {shm.name}") print(f"数组形状: {big_array.shape}") print(f"数组dtype: {big_array.dtype}") # 注意:进程A不要关闭共享内存,直到所有进程完成访问 # shm.close()
步骤2:在其他进程读取共享数组(如另一Jupyter内核)
import numpy as np from multiprocessing import shared_memory # 填入进程A输出的参数 shm_name = "psm_xxxxxx" # 替换为实际共享内存名称 array_shape = (10000, 10000) array_dtype = np.float64 # 连接到已存在的共享内存 shm = shared_memory.SharedMemory(name=shm_name, create=False) # 创建Numpy视图直接访问共享内存(无数据复制) shared_array = np.ndarray(array_shape, dtype=array_dtype, buffer=shm.buf) # 验证数据一致性 print(shared_array[0, :5]) # 使用完毕后关闭共享内存,最后一个进程调用unlink释放内存 # shm.close() # shm.unlink() # 所有进程不再使用时才执行
注意事项
- 共享内存由操作系统管理,即使创建进程退出,其他进程仍可访问,直到最后一个进程调用
unlink()或系统重启。 - 不同Jupyter内核是独立进程,只需传递共享内存名称、数组形状和dtype即可实现共享。
方法2:内存映射文件(numpy.memmap)
通过磁盘文件作为中介,将数组映射到内存,多个进程共享同一块映射区域,内存中仅保留一份数据。若使用Linux的/dev/shm临时内存文件系统,可避免磁盘IO,接近纯内存共享的速度。
步骤1:创建内存映射文件并写入数组(进程A)
import numpy as np big_array = np.random.rand(10000, 10000) # 使用/dev/shm创建内存映射(文件实际存于内存) memmap_array = np.memmap('/dev/shm/big_array_shm', dtype=big_array.dtype, shape=big_array.shape, mode='w+') # 写入数据 memmap_array[:] = big_array[:] # 刷新确保数据写入 memmap_array.flush() # 关闭映射,文件保留供其他进程访问 del memmap_array
步骤2:在其他进程读取映射数组
import numpy as np # 打开已有的内存映射文件 shared_array = np.memmap('/dev/shm/big_array_shm', dtype=np.float64, shape=(10000, 10000), mode='r') # 直接访问数组,无内存副本 print(shared_array[0, :5]) # 无需持久化时可删除文件 # import os # os.remove('/dev/shm/big_array_shm')
优缺点
- 优点:兼容低版本Python,数据可选持久化到磁盘,重启进程后仍可访问。
- 缺点:首次写入需IO操作(用
/dev/shm可规避)。
方法3:multiprocessing.Array(主-子进程场景)
仅适用于主进程与其直接创建的子进程共享(如Jupyter中用multiprocessing启动子进程),无法跨独立Jupyter内核。
示例代码
import numpy as np from multiprocessing import Process, Array def child_process(arr_shape, arr_dtype, shared_arr): # 将共享数组转为Numpy视图(无副本) np_arr = np.ndarray(arr_shape, dtype=arr_dtype, buffer=shared_arr.get_obj()) print(f"子进程读取的数组前5元素: {np_arr[0, :5]}") if __name__ == "__main__": big_array = np.random.rand(10000, 10000) # 创建共享数组,'d'对应Numpy的float64类型 shared_arr = Array('d', big_array.size) # 绑定为Numpy视图并写入数据 np_shared = np.ndarray(big_array.shape, dtype=np.float64, buffer=shared_arr.get_obj()) np_shared[:] = big_array[:] # 启动子进程 p = Process(target=child_process, args=(big_array.shape, big_array.dtype, shared_arr)) p.start() p.join()
内容的提问来源于stack exchange,提问作者Arco Bast
相关产品推荐
相关产品推荐

