During deep learning training in PyTorch 2.x, my script crashed midway through an epoch with the error:
RuntimeError: CUDA out of memory. Tried to allocate 512.00 MiB (GPU 0; 23.69 GiB total capacity; 18.21 GiB already allocated; 312.50 MiB free; 4.80 GiB reserved in total by PyTorch)I added torch.cuda.empty_cache() inside the training loop, but memory usage barely dropped, and the out-of-memory crash persists while training speed slowed down drastically. Why does empty_cache() fail to resolve CUDA OOM, and what is the proper engineering fix for memory fragmentation?
Direct Technical Solution:
torch.cuda.empty_cache()releases only cached (unallocated) blocks back to the CUDA driver; it never frees memory occupied by active tensors (weights, optimizer states, computation graph nodes). Calling it inside your training loop hurts performance because CUDA must constantly re-allocate OS memory via costly system calls.1. Root Cause: PyTorch Allocator Memory Fragmentation
Look closely at your error message:
18.21 GiB allocated+4.80 GiB reserved. PyTorch had nearly 5 GB of memory held in its internal caching allocator, but it was split into scattered, non-contiguous memory chunks. When a tensor required 512 MiB of contiguous VRAM, the allocator failed to find a single chunk large enough.2. The Modern Fix: Expandable Segments (PyTorch 2.0+)
The definitive solution in modern PyTorch is activating virtual memory management via the
expandable_segmentsflag. This instructs CUDA to map physical memory pages to a contiguous virtual memory space, virtually eliminating memory fragmentation:3. The 4 Golden Rules to Prevent CUDA OOM
total_loss += lossretains the entire backward computation graph in VRAM! Always usetotal_loss += loss.item().optimizer.zero_grad(set_to_none=True)deallocates memory instead of zeroing tensors with zeros of equal size.