You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 12:24:55