GPU acceleration and device management
3.3.6· AI-ML › Deep Learning Frameworks
Overview
GPU acceleration tensor computations ko CPU se specialized parallel processors (GPUs) par move karta hai jo ek saath hazaron operations perform kar sakte hain. Device management ek practice hai jisme explicitly control kiya jaata hai ki tensors aur models kahan rahenge (CPU vs GPU) aur devices ke beech data kaise move hoga.

Core Concepts
GPUs kyun Jeetते Hain: Physics
Derivation: Speedup Factor
Matrix multiplication compute karne ka time jahan , :
jahan clock frequency (Hz) hai, cores (~16) hai.
GPU ke liye jisme cores (~10,000) hain:
Speedup:
Typical values daalo: GHz, , GHz, :
Lekin: Yeh assume karta hai ki . Agar tum har operation mein data transfer karo, toh speedup collapse ho jaata hai.
PyTorch Device Management: First Principles Se
Tensors Ko Apni Location Kaise Pata Hoti Hai
Har PyTorch tensor ka ek .device property hota hai. Under the hood, yeh memory mein ek pointer hai ya toh:
- CPU DRAM (CPU cores se accessible)
- GPU VRAM (GPU cores se accessible, CPU se isolated)
Movement Tax
Training Loop: Device-Aware Pattern
Standard Recipe
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 1. Move model to device (once)
model = MyModel().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters())
# 2. In training loop, move batches to device
for epoch in range(num_epochs):
for batch_idx, (data, target) in enumerate(train_loader):
# Move batch to GPU
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data) # Computed on GPU
loss = criterion(output, target) # Loss on GPU
loss.backward() # Gradients computed on GPU
optimizer.step() # Parameter update on GPU
# Only move to CPU for logging
if batch_idx % 100 == 0:
print(f'Loss: {loss.item():.4f}') # .item() copies scalar to CPUHar step kyun?
- Model par
.to(device)saare parameters/buffers ko GPU memory mein move karta hai (one-time cost) - Batches ko GPU par move karna: unavoidable hai (data loader disk se padhta hai → CPU RAM → GPU VRAM)
- Logging ke liye
.item(): scalars bahut chote hote hain (~4 bytes), transfer negligible hai - Baaki sab GPU par rehta hai: koi unnecessary round-trips nahi
Multi-GPU: Data Parallelism Derivation
Problem
Ek GPU ki limited memory hoti hai (~24 GB). Bade models ya batches fit nahi hote.
Solution: Batch Split Karo
Common Mistakes
Mixed Precision Training: 2× Speedup Trick
FP16 kyun?
Modern GPUs (Tensor Cores) FP16 matrix multiplies FP32 se 2× FLOPS par kar sakte hain.
Problem yeh hai: FP16 range hai. Gradients ko aksar FP32 precision chahiye hoti hai (tiny values).
Solution hai: Automatic Mixed Precision (AMP)
Memory Management: Hidden Enemy
GPU Memory Lifecycle
Allocate → Use → Free (maybe)
PyTorch ek caching allocator use karta hai:
- Pehla allocation:
cudaMalloc(slow, 1ms) - Baad mein: cached blocks reuse karta hai (fast, 1µs)
.empty_cache()memory CUDA ko return karta hai lekin OS ko free nahi karta
Bade Batches Ke Liye Gradient Accumulation
Jab batch size 512 fit nahi hoti, gradient accumulation use karo:
accumulation_steps = 4 # Effective batch size = 128× 4 = 512
for i, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
output = model(data)
loss = criterion(output, target) / accumulation_steps # Scale loss
loss.backward() # Accumulate gradients
if (i + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()Derivation:
- Normal:
- Accumulated: ✓
Loss divide kyun karo? .backward() gradients sum karta hai. /accumulation_steps ke bina, final gradients 4× zyada bade ho jaate.
Recall 12 Saal Ke Bacche Ko Explain Karo
Socho tumhare paas math homework hai: 1000 multiplication problems. CPU (tumhara brain): Tum unhe ek-ek karke solve karte ho. Tum smart aur fast ho, lekin time lagta hai kyunki tum ek time mein ek kaam karte ho.
GPU (1000 bachchon ki class): Har baccha EK problem solve karta hai. Yeh geniuses nahi hain, lekin milke woh utne hi time mein finish karte hain jitna ek bacche ko ek problem solve karne mein lagta hai!
Neural networks isi homework jaisi hain—lakho simple multiplications. GPUs ke paas hazaron "bacche" (cores) hain jo parallel mein kaam karte hain.
Catch yeh hai: Homework ko tumhare desk (CPU memory) se classroom (GPU memory) mein le jaane mein time lagta hai. Isliye hum saare problems ek saath move karte hain (batches), ek-ek karke nahi.
Mixed precision: Kuch problems simpler math se solve ho sakti hain (FP16 = kam decimal places use karna). Yeh faster hai lekin kabhi kabhi galti karta hai, isliye hum answer ki ek "master copy" high precision mein rakhte hain (FP32).
Connections
- 3.3.05-Computational-graphsand-autograd: GPU computational graph ke through forward aur backward passes dono accelerate karta hai
- 3.2.03-Backpropagation: Gradient computation embarrassingly parallel hai, GPUs ke liye perfect
- 3.4.02-Batch-normalization: Multi-GPU mein all-reduce chahiye (sync mean/variance)
- 4.1.01-CNN-architectures: Convolutions GPU bottleneck hain—kernels optimize karna critical hai
- 3.3.07-Distributed-training-strategies: Multi-node device management ko machines ke across extend karta hai
#flashcards/ai-ml
Deep learning ke liye GPUs CPUs se better kyun perform karte hain? :: GPUs ke paas hazaron cores hain jo parallel arithmetic (low clock speed lekin massive parallelism) ke liye optimized hain, jabki CPUs ke paas ~16 complex cores hote hain sequential tasks ke liye. Neural network operations (matrix multiplies) embarrassingly parallel hain—har element independently compute hota hai—jo GPU architecture ke saath perfectly match karta hai.
GPU memory transfer bottleneck kya hai?
torch.cuda.synchronize() kya karta hai aur yeh kyun zaroori hai?
synchronize() tab tak block karta hai jab tak saare GPU kernels finish nahi ho jaate. Accurate timing ke liye aur jab CPU ko GPU results read karne hon tab zaroori hai. Iske bina, timing compute time nahi balki queue time measure karti hai.Data parallelism ka all-reduce step explain karo :: Har GPU apne batch partition par independently gradients compute karta hai. All-reduce gradients synchronize karta hai: har GPU ko saare GPUs ke average gradient milte hain. Formula: . Ring all-reduce (NCCL library) ke through efficiently implement hota hai, bandwidth cost jahan parameter count hai, GPUs hain.
Mixed precision training loss scaling kyun use karta hai?
Gradient accumulation kya hai aur kab use karna chahiye?
GPU tensors ko list mein append karne se OOM kyun hota hai?
.item() (CPU par Python float ki tarah copy hota hai), ya bade tensors ke liye .detach().cpu(), GPU reference tod deta hai.memory_allocated aur memory_reserved mein kya difference hai? :: memory_allocated(): currently live tensor memory. memory_reserved(): memory jo PyTorch CUDA se hold karta hai (cache bhi shaamil hai). Gap = cached free blocks. del tensor ke baad, memory_allocated girta hai lekin reserved high rehta hai (cache). .empty_cache() reserved memory CUDA ko return karta hai lekin OS ko nahi (CUDA driver ab bhi hold karta hai).