Handbooks  /  GPU Fundamentals
AI Engineering~12 min readIntermediate
Deep Dive

GPUs: the bottleneck is never where you think.

Every AI engineer eventually has the conversation: "just get a bigger GPU." Sometimes right, often expensively wrong — because GPU performance isn't one number, it's a race between arithmetic and memory, and most workloads lose on the memory side. This is the mental model that tells you which wall you're hitting, why FlashAttention was inevitable, and when the bigger GPU genuinely helps.

01

Throughput machines, not fast machines

A CPU is a latency processor: a few heroic cores with deep caches and branch predictors, built to finish one thread as fast as possible. A GPU is a throughput processor: ~100+ streaming multiprocessors (SMs) hosting tens of thousands of lightweight threads, built to finish all the work per second — no single thread is fast, the swarm is.

The execution model is SIMT — single instruction, multiple threads: threads run in lockstep groups of 32 called warps, one instruction driving 32 data elements. This is why GPUs devour uniform work (every element gets the same treatment — exactly what a matmul is) and why branch divergence hurts: if half a warp takes the if and half takes the else, the hardware runs both paths serially. Deep learning happens to be the most uniform large-scale workload ever invented — the marriage wasn't luck, it was fit.

02

The memory hierarchy is the whole game

Fast is small, big is slow (H100-class numbers)
Registersper-thread, ~instant — where actual arithmetic operands live.
Shared memory / L1~200 KB per SM of on-chip SRAM, ~19 TB/s class — the programmable scratchpad tiles live in.
L2 cache~50 MB shared across the chip.
HBM ("VRAM")80 GB at ~3.35 TB/s — huge, and the slowest thing on the die by an order of magnitude.

The compute units can chew through data far faster than HBM can deliver it. So the central discipline of GPU performance is arithmetic intensity: FLOPs per byte moved. Each GPU has a break-even ratio (peak FLOPs ÷ bandwidth ≈ ~300 FLOPs/byte on H100 BF16). Above it, you're compute-bound — the cores are the wall. Below it, memory-bound — the cores idle while bytes crawl. That one ratio — the roofline — explains most "why is this slow" mysteries in AI.

03

Where LLMs land on the roofline

WorkloadBound bySo the fix is…
Training / prefillcompute — big matmuls, high intensitytensor cores, lower precision (BF16→FP8), better MFU
Decode (one token)bandwidth — every weight read for little mathquantize (fewer bytes), batch (share the read), speculative decoding
Attention (naive)bandwidth — the N×N matrix commutes to HBMfuse it: FlashAttention
Elementwise opsbandwidth — one FLOP per bytekernel fusion, so bytes are read once for many ops

Tensor cores are why the compute side got so tall: dedicated units performing small matrix multiply-accumulates in hardware, with throughput that roughly doubles each precision step down (BF16 → FP8 → FP4 on the newest parts) — the hardware reason low-precision training and serving keep winning. And MFU (model FLOPs utilization) is the honesty metric: real training jobs hitting 35-45% of peak is good; the marketing number assumes a workload nobody runs.

→ The FlashAttention lesson

Same math, tiled so the N×N scores live in on-chip SRAM and never touch HBM: the operation was bandwidth-bound, so moving fewer bytes made it directly faster. Memorize the shape of that win — the modern optimization is almost never "compute less," it's "move less."

04

The kernel stack: who writes the fast code

A kernel is a function launched across a grid of thread-blocks — the unit of GPU work. Almost nobody hand-writes them anymore; the stack has layers:

From metal to model
CUDA C++raw kernels, full control — vendor libraries and kernel specialists live here.
cuBLAS / cuDNN / CUTLASSNVIDIA's tuned matmul & conv kernels — what your framework actually calls.
Tritonwrite fused custom kernels in Python; the compiler handles the thread-level pain. Where FlashAttention-style wins get democratized.
torch.compiletraces your model and auto-fuses/generates kernels — the free ~1.3-2× most people skip.

The practical division of labor: use the framework; take the torch.compile win; profile before believing anything; and reach for Triton only when the profiler shows a genuinely unfused hot spot. Writing CUDA is a specialization — reading a profile is table stakes.

05

Many GPUs: the interconnect becomes the memory wall

Models outgrew single GPUs, so the memory-hierarchy story repeats one level up: NVLink (~900 GB/s GPU-to-GPU inside a node) and InfiniBand (~400 Gb/s between nodes) are to the cluster what HBM is to the chip — the slow layer everything must be tiled around. The primitive is the collective: all-reduce (sum gradients everywhere), all-gather, reduce-scatter, moved by NCCL and overlapped with compute so communication hides behind math.

The three parallelism strategies in one line each: data parallel (copy the model, split the batch, all-reduce gradients), tensor parallel (split individual matrices across GPUs — needs NVLink-class bandwidth), pipeline parallel (split layers into stages — cheap on bandwidth, pays a bubble). Real frontier runs compose all three; that composition is its own handbook, coming next.

06

The working checklist

QuestionHow to answer it
Compute- or memory-bound?arithmetic intensity vs the GPU's ratio; profiler confirms
Is the GPU even busy?MFU / SM occupancy — data loading and CPU stalls fake "slow GPU" constantly
Decode too slow?bandwidth ÷ model bytes first; quantize or batch before shopping
Training too slow?step-time breakdown: compute vs communication vs dataloader
Custom kernel worth it?only if the profiler shows unfused memory-bound ops on the hot path
Frequently asked

Quick answers

Why are GPUs good at deep learning?

SIMT throughput machines + tensor cores meet the most uniform workload ever: giant matmuls. No single thread is fast; the swarm is.

What is arithmetic intensity?

FLOPs per byte moved. Above the GPU's ratio (~300 on H100 BF16) you're compute-bound; below it, memory-bound — and most inference is below it.

Why is FlashAttention faster?

Same math, tiled into on-chip SRAM so the N×N scores never touch HBM. Bandwidth-bound op + fewer bytes = directly faster.

Must I learn CUDA?

Learn the model and the profiler; use torch.compile; reach for Triton on proven hot spots. Hand-written CUDA is a specialization.

GPU Fundamentals · AI Engineering · Vibe Engines · 2026
Finished this one? 0 / 49 Handbooks done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.