模型的训练过程可大概划分为数据处理,模型处理
常用的加载数据采用dataloader函数,常规情况下,直接调用实现即可。在满足GPU内存的情况下,寻求GPU利用率最大化,GPU的利用率受读取速度影响较大,也就是数据在cpu和gpu之间的交互。
- 常规情况下调节num_worker的大小,以启动多进程,加快数据读取。根据torch对多进程读取机制,易发生阻断情况,也就是num_worker并不是越大越好。
数据读取至GPU的过程中需要对进程序列就行匹配,匹配成功后,再读取下一个进程。单个进程的读取速度慢会导致加载数据的间断。采用SSD存储数据,可以一定程度解决该问题。详情可参看https://zhuanlan.zhihu.com/p/91521705 - torch将数据读取至cpu后,并在cpu进行了预处理的过程,该过程也对训练速度产生了影响。可以将预处理过程办到GPU上进行,DALI:https://github.com/NVIDIA/DALI https://github.com/tanglang96/DataLoaders_DALI
具有一定局限性,常规的预处理可以采用该方法。 - 在对图像数据进行操作时,采用opencv一般比PIL快;读取jpeg文件,可以尝试jpeg4py,https://github.com/ajkxyz/jpeg4py 根据git说明,多进程情况下可提升9倍;进行图片存储可采用bmp格式(无损压缩),RLE降低解码时间。
- 对于数据量过大,或者大规模小数据,可以尝试转成单独文件,以加快读取速度,TFRecord,recordIO,h5 ,pth,lmdb,n5。h5在数据调用上比较快,多进程时采用h5进行读写,相对麻烦,不建议。http://docs.h5py.org/en/stable/mpi.html
TFRecord,recordIO分别针对tf和mxnet。torch针对TFRecord https://github.com/vahidk/tfrecord
h5 ,pth,n5这几类意思与json的API,需要将整个文件放入内存,对于大规模数据,不实际。所以采用lmdb情况较多https://github.com/Fangyh09/Image2LMDB - 预读取数据
采用nvidia的Apex ,进行预读取,
class data_prefetcher():
def __init__(self, loader):
self.loader = iter(loader)
self.stream = torch.cuda.Stream()
self.mean = torch.tensor([0.485 * 255, 0.456 * 255, 0.406 * 255]).cuda().