PyTorch训练神经网络时numpy memmap高效使用方案咨询
性能无差异的核心原因
- numpy memmap是懒加载机制:调用
numpy.load(..., mmap_mode=xxx)时,并不会将整个npy文件加载到内存,仅会创建一个轻量的文件描述符和虚拟地址映射关系,单个memmap对象的创建开销极低,即便每次读取都创建新对象,累计开销也可以忽略。 - 操作系统页缓存兜底:首次访问某块裁剪区域时,操作系统会将对应的磁盘页加载到内存缓存中,后续不管是复用旧的memmap对象还是新创建的memmap对象访问同一块区域,都会直接命中内存缓存,不会产生磁盘IO,因此两种方式的读取效率一致。
- 多进程场景下预加载反而可能有额外开销:如果使用PyTorch多进程DataLoader(
num_workers>0),__init__中预加载的所有memmap对象会在每个worker进程fork时被复制,虽然不会复制实际数据,但大量对象的复制也会产生微小的额外开销,抵消预加载带来的收益。
该场景下的numpy memmap使用最佳实践
- 按需选择加载时机:如果数据集规模较小(千级以内),可以在
__init__中预加载所有memmap对象,代码实现更简洁;如果数据集规模较大(万级以上)且使用多进程加载,建议每次读取图像时再创建memmap对象,避免多进程复制大量对象的开销。 - 固定使用只读模式:mmap_mode统一设置为
'r',既可以避免误修改源npy文件,也能让操作系统采用更高效的只读缓存策略,提升访问效率。 - 保持裁剪访问的连续性:目前使用的
image_mmap[y1:y2, x1:x2]行优先切片方式刚好匹配numpy数组的存储顺序,是最优的访问方式,不需要调整;避免跨不连续地址的随机访问,否则会产生更多缺页中断。 - 可选优化:如果单图npy文件数量过多,可以将多张图像拼接为一个大的npy文件存储,减少频繁创建文件描述符的开销,该优化在超大规模数据集下会有可感知的性能提升。
内容的提问来源于stack exchange,提问作者Nagabhushan S N
相关产品推荐
相关产品推荐

