跳转至

深度学习并行加载数据

问题应该已经解决了

背景

一次训练任务(比如人脸识别训练、语音识别训练)所需要的数据是庞大的,我们暂且假定这个数据在 1T-10T 的量级;这些数据一般存储在DISK上(速度为 200MB/s-1GB/s)。在计算机中做GPU运算时,GPU总是从RAM中取数据,这时RAM会从DISK中加载一次数据。注意这里假设GPU的算力足够;RAM的速度(20GB/s)远超DISK的读取速度。

一般我们进行深度学习训练的过程如下:

for epoch in 0 ... epoch_num {
    for batch in all_data {
        model.train(use: batch)
    }
}
  • epoch - 训练轮数 相当于整个数据过多少遍
  • all_data - 所有的训练数据
  • batch - 一个批量 一般会将所有的训练数据分成 batch_sizebatch 去更新梯度(train()

具体一点:

let all_files = [1.file, 2.file, ... n.file] // 有n个图片或者n段音频
for epoch in 0 ... epoch_num {
    let file_batches = all_files.shuffle() // 将n份文件分成batch_size份
    for file_batch in file_batches {
        let files = load(file_batch.paths) // 读取当前batch中 n/batch_size 个文件
        files.train() // 使用从文件中读取的数据进行训练
    }
}

问题:从DISK加载到RAM的速度优化

由于每一次epoch都需要读取一遍数据集

  • RAM=256G DATA=200G 时:在第一个epoch时 OS会将DATA完全加载到RAM中 PyTorch从RAM中取数据训练;之后的epoch 由于数据还在RAM中 因此PyTorch可以直接从RAM中读取数据。这没什么问题
  • RAM=256G DATA=2T 时:不论是哪一个epoch 在一个epoch内 都需要将完整的DATA加载一遍:最开始的256G会直接加载到RAM 但是后面随着数据加载到RAM 之前加载好的数据又会被从RAM中移出。于是就会发现 每一个epoch都需要将2T的DATA从DISK读一遍到RAM中 这很花时间

实践

RAM=256G DATA=2T 这种情况下,我们可以直接加内存到T的级别,也可以提高DISK的读取速度。但其实更好的是改变读取顺序的策略,不让RAM频繁从DISK中读取数据。

References

  1. wenet/UIO.md at main · wenet-e2e/wenet (github.com)
  2. wenet/dataset.py at main · wenet-e2e/wenet (github.com)
  3. Distributed Training with Uneven Inputs Using the Join Context Manager — PyTorch Tutorials 1.10.1+cu102 documentation
  4. webdataset/webdataset: A high-performance Python-based I/O system for large (and small) deep learning problems, with strong support for PyTorch. (github.com)