If your GPU is below 80% utilization, the pipeline is the bottleneck
A perfectly-fed GPU sits near 100% during training. Anything less and your data pipeline is leaving compute on the floor. The DataLoader has the knobs to fix this — most of them you set once and forget.
The settings that matter
num_workers— number of subprocesses for parallel__getitem__. Start with the number of CPU cores; tune down if memory is tight (each worker copies the dataset). 0 = main-process loading (slow but easy to debug).pin_memory=True— allocate batches in non-pageable CPU memory. Combined withx.to(device, non_blocking=True), enables CPU↔GPU overlap.prefetch_factor— batches each worker prefetches ahead. Default 2; raise to 4 if your GPU is finishing batches faster than they arrive.persistent_workers=True— keep workers alive across epochs. The first epoch pays the worker-startup tax; persistent workers pay it once for the whole training run.drop_last=True— discard the trailing partial batch. Useful for consistent batch shapes (BatchNorm stats, distributed training).
Diagnosing the bottleneck
- nvidia-smi shows GPU at 30%? Pipeline is the bottleneck.
- nvidia-smi shows GPU at 95%? Pipeline is fine; speedup must come from compute (compile, AMP, bigger batch).
- htop shows one CPU core at 100% and others idle? num_workers is too low.
- Memory pressure during multi-worker loading? Each worker copies the dataset; lower num_workers or use IterableDataset.