使用joblib并行加载同一份numpy npy文件时出现偶发错误如何解决?
并行加载npy文件报错解决方案
你遇到的两类报错本质都是多进程/多线程同时操作同一个npy文件触发的竞态条件:
- 最初的
cannot reshape array of size 0 into shape (12345,)报错:多个并行任务同时读取同一个文件时,部分任务会读取到被其他进程占用、尚未完全写入/读取的不完整文件,numpy解析到的文件内容长度为0,因此报reshape失败。调试时所有并行进程都会暂停,不存在文件占用冲突,所以手动读取可以正常执行。 - 后续的
Cannot load file containing pickled data when allow_pickle=False报错:同样是并发读取导致文件内容被截断或错乱,numpy无法识别合法的npy格式,误以为内容是pickle序列化数据,因此触发了权限报错。非并行模式下没有读写冲突,所以可以正常运行。
推荐按优先级选择以下解决方案:
- 优先选择预加载公共数据:在启动并行任务之前,先把所有需要共享的npy文件一次性加载到内存,直接将数组对象传递给每个并行任务,不要让每个子任务单独读取磁盘文件。这个方案既彻底解决了IO冲突,也能大幅降低重复读盘带来的性能损耗,是最优解。
- 若必须让子任务各自读文件,可添加文件锁:用文件锁保证同一时间只有一个任务在读取目标文件,避免并发冲突。可以使用
filelock库实现,修改读取逻辑如下:
from filelock import FileLock lock_path = Path(dprm, fn + ".lock") with FileLock(lock_path): train = np.load(Path(dprm,fn))
- 如果npy文件过大无法全部加载到内存,可使用只读内存映射加载:调用
np.load时传入mmap_mode='r'参数,多个进程可以共享同一块只读内存映射,不会触发读写冲突,也不需要把整个数组加载到内存。 - 临时修复pickle报错:如果确认你的npy文件不存在安全风险,可以在
np.load时显式添加allow_pickle=True参数,能临时解决pickle权限报错,但这个方案无法解决文件不完整读取的问题,需要配合文件锁使用。
内容的提问来源于stack exchange,提问作者Maxime Beau
相关产品推荐
相关产品推荐

