GPU programming ও CUDA ধারণা
এই পাঠে যা শিখবেন
- CPU vs GPU — architectural পার্থক্য কেন matter
- CUDA programming model — kernel, thread, block, grid
- Memory hierarchy — global, shared, register
- PyTorch GPU usage — device, transfer, AMP
- Multi-GPU training — DDP, FSDP
- Common pitfalls — host-device transfer overhead
১ · GPU কেন এত আলাদা
CPU — few powerful cores (৮-১৬), each handle complex branching, large cache। Optimized for sequential work।
GPU — thousands of simpler cores। Same operation simultaneously on different data। Ideal for matrix multiplication, image processing — DL-এর মূল operation।
একটি ৭৬৮×৭৬৮ matrix multiplication — CPU-তে ~১০০ ms, NVIDIA A100-এ ~০.৫ ms। ২০০x faster। Deep learning সম্ভব হয়েছে এই difference-এর কারণে।
GPU-এর core paradigm — একই instruction হাজার thread-এ একসাথে execute, কিন্তু প্রতিটি thread আলাদা data-তে। Image-এর প্রতিটি pixel-এ একই brightness adjust — perfect SIMT match।
২ · CUDA programming model
NVIDIA-এর CUDA (Compute Unified Device Architecture) — GPU-তে general-purpose computing। C-extension।
- Kernel: GPU-তে চলা function।
__global__keyword। - Thread: single execution unit। Each thread একটি element-এ কাজ করে।
- Block: thread group (e.g., ২৫৬ thread)। Same SM-এ চলে, shared memory access।
- Grid: all blocks। Total workload।
- Warp: ৩২ thread একসাথে SIMT — hardware-level।
Thread index dimensions: threadIdx.x, blockIdx.x, blockDim.x। Combined position:
$$\text{global\_id} = \text{blockIdx.x} \times \text{blockDim.x} + \text{threadIdx.x}$$
৩ · Simple CUDA kernel — vector add
__global__ void vec_add(float* a, float* b, float* c, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n) {
c[i] = a[i] + b[i];
}
}
// Launch from host:
int n = 1000000;
int threads = 256;
int blocks = (n + threads - 1) / threads;
vec_add<<<blocks, threads>>>(d_a, d_b, d_c, n);
১M element add — CPU ~১ ms, GPU ~১০ μs। Massively parallel।
৪ · Memory hierarchy
GPU-এর performance memory access pattern-এর উপর hugely depend।
- Register (per thread): fastest, ছোট। Local variables।
- Shared memory (per block): ফাস্ট, ১০০ KB। Block-এর thread-গুলো cooperate।
- L1/L2 cache: hardware-managed।
- Global memory: GPU's main DRAM — VRAM, ১০-৮০ GB। Slow।
- Host memory (CPU RAM): GPU access slow — PCIe transfer।
Coalesced access — adjacent thread adjacent memory address access করলে — single transaction। Misaligned-এ ১০x slow।
৫ · PyTorch — GPU ব্যবহার
import torch
# Check GPU availability
print(torch.cuda.is_available()) # True if NVIDIA GPU
print(torch.cuda.device_count()) # number of GPUs
print(torch.cuda.get_device_name(0)) # e.g., 'NVIDIA A100'
# Tensor on GPU
x = torch.randn(1000, 1000, device='cuda')
y = torch.randn(1000, 1000).cuda() # alternative
z = x @ y # GPU matmul
# Bring back to CPU
z_cpu = z.cpu()
print(z_cpu.shape)
# Best practice — single device variable
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = MyModel().to(device)
data = data.to(device)
৬ · Mixed precision training (AMP)
FP32 (32-bit float) — default। FP16 (16-bit) — 2x faster, half memory। কিন্তু gradient overflow risk।
AMP (Automatic Mixed Precision): forward FP16, optimizer FP32 — best of both। Gradient scaling overflow rod।
import torch
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
model = MyModel().cuda()
optimizer = torch.optim.Adam(model.parameters())
for x, y in loader:
x, y = x.cuda(), y.cuda()
optimizer.zero_grad()
with autocast(): # FP16 forward
pred = model(x)
loss = criterion(pred, y)
scaler.scale(loss).backward() # scaled gradient
scaler.step(optimizer) # unscale + step
scaler.update()
Modern alternative — BF16 (bfloat16) — Ampere+ GPU-তে। Same range FP32, half memory। No scaling needed।
৭ · Multi-GPU training
- DataParallel (DP): simple, single-process। Slow due to GIL।
- DistributedDataParallel (DDP): recommended। Each GPU separate process। Gradient AllReduce sync।
- FSDP (Fully Sharded Data Parallel): very large model — parameter shard across GPU। LLaMA 70B-এর জন্য essential।
- Pipeline parallel: different layer different GPU। Latency hide।
- Tensor parallel: single layer split। Megatron-LM-এ।
৮ · Common pitfalls
- CPU↔GPU transfer overhead: Inner loop-এ
.cpu()avoid। - Synchronous timing:
torch.cuda.synchronize()before timing — async kernel। - Memory leak: training loop-এ retained reference — OOM।
- Batch size — too small: GPU underutilized। Large batch + gradient accumulation।
- Mixed-device tensors: "Expected all tensors on same device" — common error।
- Pinned memory:
pin_memory=Truein DataLoader — faster H2D transfer।
৯ · Hardware landscape
- NVIDIA H100 (২০২২): ৮০GB HBM, FP16 ~১৯৮৯ TFLOPS — modern LLM training।
- A100: ৪০/৮০GB, ৩১২ TFLOPS — most cloud GPU।
- RTX 4090: ২৪GB, consumer ~৮২ TFLOPS — fine-tuning workhorse।
- AMD MI300, Google TPU: alternative — software stack different।
- Apple M-series: Metal backend, PyTorch MPS support।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ "GPU faster than CPU" — সব workload-এ সত্যি না। কোথায় CPU বেশি ভালো? কোথায় GPU?
GPU vs CPU — workload-এর nature-এর উপর depend।
GPU-favored workload:
- Matrix multiplication — DL-এর core।
- Image/video processing — pixel-parallel।
- Monte Carlo simulation — independent samples।
- Cryptocurrency mining — hash parallel।
- Scientific computing — vector operations।
CPU-favored workload:
- Sequential algorithm — no parallelism।
- Branch-heavy code — divergent control flow।
- Small workload — kernel launch overhead dominate।
- Database query — random memory access।
- Web server — many small request।
GPU overhead sources:
- Kernel launch — ~10 μs overhead।
- CPU↔GPU memory transfer — PCIe slow।
- Synchronization — async by default।
- Initialization cost।
When CPU win:
- Small tensor operation।
- Sparse data — irregular access।
- Tree algorithms — hard to parallel।
- Sequential RNN inference (small batch)।
Empirical thresholds:
- Matrix size > ১০০×১০০ — GPU usually win।
- Element-wise op on >1M element — GPU।
- Convolution on >32×32 image — GPU।
- Below threshold — CPU comparable।
Branch divergence:
- Warp-এর thread-গুলো diverge করলে — serial execution।
- If-else heavy → GPU efficiency drop।
- SIMT model penalty।
Memory access pattern:
- Random access — GPU slow।
- Coalesced access — GPU optimal।
- Cache hierarchy difference।
Modern architecture:
- CPU SIMD (AVX-512) — narrow gap।
- Apple M-series — unified memory।
- NVIDIA Grace Hopper — CPU+GPU integrate।
- Heterogeneous compute future।
DL-specific:
- Training — GPU dominant।
- Inference small batch — CPU competitive।
- Edge deployment — mobile NPU।
- ONNX runtime — multi-platform।
Cost consideration:
- GPU $/hour high — only when compute bound।
- CPU sufficient — cheaper for small models।
- Cloud spot instance — GPU cost dynamic।
Bangladesh context:
- GPU access limited — cloud + Colab।
- CPU servers cheaper local।
- Inference often CPU OK।
- Training cloud-heavy।
মূল উপলব্ধি: GPU = parallel compute hammer। সব problem nail নয়। Sequential, branch-heavy, small-workload — CPU win। DL training mostly GPU। Inference workload-dependent। Hardware choice = problem-aware।
প্র ০২ FP16 mixed precision-এ "gradient scaling" কেন দরকার? FP16 যথেষ্ট না কেন pure?
Mixed precision — DL training-এর critical optimization। Gradient scaling crucial detail।
FP16 limitation:
- Range $\sim 6 \times 10^{-5}$ to $65504$।
- Small gradient — underflow zero।
- Precision $\sim 0.1\%$।
Gradient distribution:
- Late training — gradient magnitude small।
- $10^{-7}$ to $10^{-3}$ common।
- Below FP16 minimum — flush to zero।
- Training breaks।
Gradient scaling fix:
- Loss multiply by scale $S$ (e.g., $2^{15}$)।
- Gradient automatically scaled by $S$।
- FP16 representable now।
- Optimizer step — unscale by $S$।
Dynamic scaling:
- Start small scale।
- Overflow detected — halve scale, skip step।
- No overflow N steps — double scale।
- Adaptive optimal।
Alternative — BF16:
- Range same FP32 ($10^{-38}$ to $10^{38}$)।
- Precision lower (8-bit mantissa)।
- No scaling needed।
- Ampere+ GPU support।
BF16 vs FP16 trade-off:
FP16:
- Higher precision (10-bit mantissa)।
- Range issue — scaling needed।
- Older hardware support।
BF16:
- Better range।
- Lower precision।
- Simpler code।
- Modern preferred।
Mixed precision details:
- Forward FP16/BF16 — fast tensor core।
- Master weight FP32।
- Optimizer state FP32।
- Gradient compute mixed।
Memory savings:
- Activation 2x reduction।
- Weight 2x (master keep FP32)।
- Total memory ~50% reduce।
- Larger batch possible।
Speed gains:
- Tensor core utilization।
- FP16 ~2x throughput FP32 (V100+)।
- BF16 same as FP16।
- Training 1.5-2x faster।
Numerical stability concern:
- BatchNorm স্টatistics — FP32 keep।
- Loss FP32 computation।
- Softmax — careful।
- Edge cases handled by AMP।
Modern best practice:
- BF16 if hardware support।
- FP16 + AMP otherwise।
- FP32 master weight always।
- Gradient checkpointing complement।
মূল উপলব্ধি: FP16 range insufficient — gradient underflow। Scaling — math trick to representable range। BF16 modern alternative — no scaling। Mixed precision — speed + memory + accuracy balance। Production training standard।
প্র ০৩ DDP (DistributedDataParallel) "AllReduce" — কী এবং কেন slow networking-এ DDP scale ভাল না?
AllReduce — distributed training-এর fundamental operation। Network bottleneck-এর key reason।
AllReduce mechanics:
- Each GPU compute gradient।
- Sum gradient across all GPU।
- Result distribute back all GPU।
- Each GPU same gradient।
- Identical model update।
Algorithms:
Ring AllReduce:
- GPU ring topology।
- Bandwidth-optimal।
- $2(N-1)/N$ bandwidth utilized।
- NCCL implementation।
Tree AllReduce:
- Latency-optimal।
- $\log N$ steps।
- Smaller data better।
Network bottleneck:
- Gradient size = model size (bytes)।
- LLaMA-7B: ১৪GB FP16 gradient।
- Per step communicate this volume।
- Network bandwidth critical।
Bandwidth requirement:
- NVLink (intra-node): ৬০০ GB/s।
- InfiniBand: ৫০ GB/s।
- Ethernet 10G: ১.২৫ GB/s।
- Ethernet 1G: ০.১২৫ GB/s।
Slow network impact:
- Ethernet 1G — ১৪GB transfer ~১১২ second per step।
- Compute time only seconds।
- Network dominate — GPU idle।
- Effective parallelism কম।
Optimization techniques:
(১) Gradient compression:
- Quantize gradient to INT8।
- 4x bandwidth reduction।
- Slight accuracy loss।
(২) Gradient overlap:
- Compute backward during AllReduce।
- Hide communication latency।
- PyTorch DDP default।
(৩) Bucket size tuning:
- Small bucket — more concurrent communication।
- Large bucket — less overhead।
- Trade-off।
(৪) Local steps:
- Multiple steps before sync।
- Federated learning approach।
- Asynchronous training।
- Convergence trade-off।
FSDP advantage slow network:
- Parameter shard — each GPU holds part।
- Communicate parameter chunk during use।
- Memory savings significant।
- Communication amortized।
Network topology:
- Single node multi-GPU — NVLink fast।
- Multi-node — InfiniBand essential।
- Cloud — high bandwidth instances।
- Bangladesh — limited high-bandwidth infrastructure।
Bandwidth-aware training:
- Local development — single GPU।
- Scale up — same node initially।
- Multi-node — careful infrastructure।
- Cloud GPU instance carefully selected।
Modern alternatives:
- Pipeline parallelism — less communication।
- Tensor parallelism — intra-node।
- Hybrid — Megatron-LM style।
- 3D parallelism — DeepSpeed।
Bangladesh practical:
- Single GPU — most common।
- Multi-GPU rare — research lab।
- Cloud A100 ($1-2/hour) — short bursts।
- Pretrained model fine-tune — manageable।
মূল উপলব্ধি: AllReduce — gradient sync mechanism। Bandwidth-bound — slow network problem। Ring algorithm optimal usually। Compression, overlap, FSDP — mitigation। Bandwidth = scale limit। Hardware investment critical for scale।
প্র ০৪ Bangladesh-এর একটি team ML model train করতে চাচ্ছে কিন্তু GPU access সীমিত। কী options + cost-effective strategy?
Practical Bangladesh ML reality — GPU access constraint। Strategy critical।
GPU access options:
(১) Free tier:
- Google Colab: Tesla T4, 12hr session।
- Kaggle: 30hr/week T4/P100।
- Paperspace: limited free GPU।
- Hugging Face Spaces: CPU + occasional GPU।
(২) Cloud paid:
- Google Colab Pro: $10/month, A100 access।
- AWS: spot p3 ~$1-3/hour।
- GCP: A100 ~$3/hour।
- Lambda Labs: A100 ~$1.10/hour।
- Vast.ai: GPU rental marketplace।
- RunPod: spot GPU cheap।
(৩) Local hardware:
- RTX 4090 — $1500-2000।
- RTX 3090 — $700-1000।
- Used Tesla cards — $200-500।
- Bangladesh import duty consideration।
(৪) Academic:
- BUET, NSU GPU labs।
- Google Research Cloud credits।
- Microsoft AI for Good।
- Apply — academic discount।
Cost-effective strategy:
Phase 1 — Prototype (Colab free):
- Architecture design।
- Small data experiments।
- Hyperparameter exploration।
- Bug debugging।
Phase 2 — Develop (Colab Pro):
- Medium scale training।
- Validation runs।
- $10/month sustainable।
Phase 3 — Production (Cloud spot):
- Final training runs।
- A100 Lambda/RunPod ~$1/hour।
- Burst usage।
Phase 4 — Inference (CPU/edge):
- Quantized model।
- CPU inference acceptable।
- Production serving।
Compute optimization techniques:
- Mixed precision — 2x speed।
- Gradient checkpointing — memory save।
- LoRA fine-tuning — small parameter।
- QLoRA — 4-bit quantized।
- Flash attention — memory efficient।
Pretrained model leverage:
- Start from BERT, LLaMA, ResNet।
- Fine-tune small data।
- Avoid from-scratch training।
- HuggingFace ecosystem।
Bangla-specific resources:
- BanglaBERT pretrained।
- BUET datasets।
- Bangla NLP corpus।
- Google's AI4Bharat।
Smart workflow:
# Tier-based training
# 1. Local CPU debug
model = MyModel()
loss = train_step(model, sample_batch)
# 2. Colab GPU prototype
# Same code, different runtime
model = model.cuda()
train_full(model, small_data)
# 3. Lambda A100 production
# Distributed if needed
model = model.cuda()
train_full(model, full_data, distributed=True)
Inference deployment:
- ONNX export — universal format।
- TensorRT optimization।
- Docker containerize।
- Cloud GPU API service।
Cost monitoring:
- Set spending alerts।
- Spot instance for non-critical।
- Auto-shutdown idle GPU।
- Profile before scaling।
Community resources:
- Bangladesh AI/ML Facebook groups।
- Local meetups — knowledge share।
- BUET, NSU collaborations।
- Industry-academia bridges।
Long-term strategy:
- Local GPU investment — RTX 3090/4090।
- Scale to cloud bursts।
- Pretrained model focus।
- Domain expertise + AI।
মূল উপলব্ধি: Bangladesh GPU constraint — multi-tier strategy। Free → Colab Pro → Spot cloud → Edge। Pretrained model leverage critical। Optimization (LoRA, quantization) essential। Cost-conscious — production ML viable। Bangladesh AI ecosystem growing।
অনুশীলন
-
Benchmark: CPU vs GPU matmul ১০০০×১০০০ — speedup measure (Colab GPU)।
import torch, time N = 1000 # CPU a = torch.randn(N, N); b = torch.randn(N, N) t0 = time.time(); c = a @ b; t_cpu = time.time() - t0 # GPU a, b = a.cuda(), b.cuda() torch.cuda.synchronize() t0 = time.time(); c = a @ b; torch.cuda.synchronize() t_gpu = time.time() - t0 print(f"CPU: {t_cpu*1000:.1f} ms") print(f"GPU: {t_gpu*1000:.1f} ms") print(f"Speedup: {t_cpu/t_gpu:.1f}x")Typical Colab T4: ~৫০ ms CPU, ~১ ms GPU → ৫০x speedup।
-
AMP integration: Existing training loop-এ
autocast+GradScaleradd।from torch.cuda.amp import autocast, GradScaler scaler = GradScaler() for x, y in loader: x, y = x.cuda(), y.cuda() optimizer.zero_grad() with autocast(): pred = model(x) loss = criterion(pred, y) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update() -
চিন্তা: Why
torch.cuda.synchronize()দরকার GPU benchmarking-এ?CUDA kernel launch asynchronous — kernel-launch return immediately, GPU work later। Without sync — timing measure শুধু kernel launch overhead, actual computation নয়।
torch.cuda.synchronize()— host wait until all queued GPU work complete। Accurate timing নিশ্চিত। Production training-এ এটা avoid (slow), benchmark-এ দরকার।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ৩৯ · প্রজেক্ট: MNIST classifier পরবর্তী পাঠ এই পুরো কোর্সের knowledge হাতে-কলমে — full pipeline।
- পাঠ ৩৭ · Diffusion model আগের পাঠ GPU-heavy modern generative AI।
- MLOps Track production GPU deployment, scaling, monitoring।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।