0%

DataLoader 参数调优

DataLoader 参数调优

一句话定位:训练/推理慢,很多时候不是 GPU 不够快,而是数据喂不上。DataLoader 调优的目标只有一个——让数据供给速度追上 GPU 消费速度,把 GPU 利用率从锯齿状拉成一条直线。

1. 三个核心参数

1 num_workers:并行加载子进程数

  • 用多个子进程并行做数据读取与前处理(解析、解码、增强),与主进程的 GPU 计算重叠。
  • 0 表示在主进程加载,GPU 会被数据准备完全阻塞。
  • 过高的代价:每个 worker 是独立进程,会抢占 CPU 并各自持有一份内存(数据集对象、缓冲区),导致 CPU 争抢、内存暴涨甚至 OOM;进程间通信与序列化开销也随之上升。
  • 经验取值:与可用 CPU 核数匹配(常见 4~8 或 核数/GPU数),需实测。

2 pin_memory:锁页内存

  • 设为 True 时,DataLoader 把 batch 放入锁页(page-locked / pinned)内存
  • 作用:锁页内存不会被操作系统换出,因此 Host→Device 拷贝可以走异步 DMA,与计算重叠(配合 non_blocking=True.to(device))。非锁页内存的 H2D 拷贝需要先暂存到临时锁页缓冲,多一次拷贝且无法异步。
  • 代价:占用不可换出的物理内存,过量使用会挤压系统内存。

3 prefetch_factor:每 worker 预取批数

  • 每个 worker 提前准备的 batch 数(默认 2),即预取队列深度。
  • 作用:掩盖 I/O 与前处理延迟——GPU 消费当前 batch 时,后续 batch 已在准备好的队列中,避免 GPU 等待(与 1.6 的异步预取是同一思想)。
  • 代价:队列越深,内存占用越高。

2. 判断依据:GPU 利用率呈锯齿状

这是最实用的诊断信号:

  • nvidia-smi(或 dmon / Nsight)观察 GPU 利用率曲线,若呈锯齿状(忙一下→掉到低位→再忙),说明 GPU 周期性空等 → 数据供给不足,瓶颈在 CPU 侧的加载/前处理,而不是 GPU 算力。
  • 此时正确动作是调 num_workers / prefetch_factor / pin_memory、优化前处理与数据格式(如换 Parquet/Arrow 减少解析开销,见 1.7),而不是换更强的卡。
  • 反之若利用率持续接近满载,才应从 kernel/batch/并行策略入手(对应 3.3 瓶颈定位)。

参考:PyTorch 官方文档 torch.utils.data.DataLoader