如何在3个连续执行的Python脚本中高效加载同一个大体积NumPy数组
大体积NumPy数组/Pandas DataFrame重复加载优化方案
以下是3种可落地的优化方案,均无需合并三个独立Python脚本,可适配不同的业务场景:
方案1:只读内存映射加载(改动最小,优先推荐)
如果你的数据在三个脚本中仅做只读操作,直接使用NumPy内置的内存映射模式加载即可,该模式不会将全量数据读入内存,仅在需要访问对应位置数据时做磁盘IO,首次初始化开销远小于全量加载,后续脚本重复初始化的开销几乎可忽略。
仅需修改三个Python脚本中加载数据的一行代码:
# 原代码 # arr = np.load('array.npy') # 修改为 arr = np.load('array.npy', mmap_mode='r')
如果是Pandas DataFrame,可将数据转存为HDF5格式,使用只读模式加载:
df = pd.read_hdf('data.h5', key='df', mode='r')
该方案无需修改bash脚本,仅需调整Python加载逻辑,无额外依赖,适配90%以上的只读场景
方案2:Python主进程调度(性能最优)
如果需要在脚本中修改数据,可将三个Python脚本的核心逻辑封装为可导入的函数,用一个主Python脚本统一调度:
- 调整三个Python脚本结构,以
code1.py为例:
import numpy as np def main1(arr): # 此处放入原code1.py的所有核心逻辑,直接使用传入的arr参数即可 ... # 保留原有直接执行的逻辑,不影响单脚本调试 if __name__ == "__main__": arr = np.load('array.npy') main1(arr)
code2.py、code3.py同理封装为main2()、main3()函数。
2. 编写主调度脚本run_all.py:
import subprocess import numpy as np from code1 import main1 from code2 import main2 from code3 import main3 # 全量数据仅加载一次 arr = np.load('array.npy') # 执行第一个脚本逻辑 main1(arr) # 执行原bash中第一个中间操作 subprocess.run("你的第一组bash命令", shell=True, check=True) # 执行第二个脚本逻辑 main2(arr) # 执行原bash中第二个中间操作 subprocess.run("你的第二组bash命令", shell=True, check=True) # 执行第三个脚本逻辑 main3(arr)
- 将原
code.sh的内容替换为:
#!/bin/bash python run_all.py
该方案数据仅加载一次,全程在内存中传输,性能最高,适配中间bash操作不复杂的场景
方案3:共享内存存储(适配必须保留原bash调度逻辑的场景)
如果中间的bash操作非常复杂,无法迁移到Python中执行,必须保留原有的多Python进程+bash调度的结构,可使用共享内存存储全量数据,三个Python进程直接从共享内存读取数据,无需重复读磁盘。
以Apache Arrow实现共享内存为例:
- 编写数据加载到共享内存的脚本
load_to_shm.py:
import pyarrow as pa import numpy as np arr = np.load('array.npy') # 申请共享内存并写入数据 serialized_data = pa.serialize(arr) shm = pa.SharedMemoryBuffer.create(size=serialized_data.size, name='large_arr_shm') serialized_data.write_to(shm) shm.close()
- 修改三个Python脚本的加载逻辑:
import pyarrow as pa import numpy as np # 直接从共享内存读取数据,无需读磁盘 shm = pa.SharedMemoryBuffer.open('large_arr_shm') arr = pa.deserialize(shm) # 后续逻辑不变 ...
- 调整原
code.sh内容:
#!/bin/bash # 仅加载一次数据到共享内存 python load_to_shm.py python code1.py # some code python code2.py # some code python code3.py # 执行完成后删除共享内存,避免内存泄漏 python -c "import pyarrow as pa; pa.SharedMemoryBuffer.unlink('large_arr_shm')"
该方案完全保留原有的bash调度逻辑,仅需修改数据加载部分代码,注意运行结束后必须手动释放共享内存
内容的提问来源于stack exchange,提问作者RANIT DAS
相关产品推荐
相关产品推荐

