Visual walkthrough — Warps and warp scheduling
This page rebuilds the parent result — Warps and warp scheduling's latency-hiding formula — from absolutely nothing. We will earn every symbol with a picture before we use it. By the end you will understand, in your bones, why a GPU keeps dozens of warps around when only one runs at a time.
The single equation we are marching toward is:
Right now that is just squiggles. Let us make it obvious.
Step 1 — What a warp actually is (the marching band)
WHAT: A warp is a bundle of 32 threads. A thread is one worker doing one copy of your program. One instruction is fetched once and executed by all 32 at once.
WHY this grouping: Fetching and decoding an instruction is expensive. If you do it once and 32 workers obey it, you split that cost 32 ways. That is the whole trick behind GPU throughput (contrast this with SIMT-vs-SIMD).
PICTURE: The row of 32 boxes below is one warp. The red box is thread 0; every box moves on the same tick.

Step 2 — What "one instruction" costs vs. what a memory read costs
WHAT: Most instructions (add, multiply, compare) finish in roughly one tick — one cycle. A cycle is the GPU's heartbeat, one tick of its clock. But a memory read — asking distant DRAM for a value — takes hundreds of ticks to come back.
WHY this matters: If a warp asks for memory and then just waits, it sits frozen for hundreds of cycles. During those cycles its execution unit does nothing. That idle time is the enemy. Everything on this page exists to fill it.
PICTURE: Below, a cheap instruction is a tiny bar (1 cycle). The memory read is a long red bar ( cycles). Look how much bigger red is.

Step 3 — One warp alone wastes almost all its time
WHAT: Follow a single warp through a loop: it does a little work, then reads memory, then waits, then repeats.
WHY show this first: To feel the problem before the fix. We need to measure exactly how much time is wasted so the cure has a number.
Let be the number of useful instructions a warp runs between memory reads. (One instruction ≈ one cycle, so is also roughly the busy-cycles per read.)
PICTURE: Warp 0's life. Short black = cycles of real work. Long red = cycles of pure waiting. The red dwarfs the black.

Step 4 — The idea: stack another warp into the gap
WHAT: When warp 0 fires its memory read and stalls, the warp scheduler (hardware inside the SM) instantly switches to warp 1 and runs its work.
WHY it costs nothing to switch: Each warp keeps its own registers and its own program counter (a program counter is just a pointer to "which instruction am I on"). Switching = updating one pointer. No saving, no restoring. This is zero-overhead switching. (Contrast the CPU, which must save/restore state — see Register-Pressure for the register-partition cost.)
PICTURE: Warp 0's red waiting-bar now has warp 1's black work-bar tucked inside it. The idle hole is being filled.

Step 5 — How many warps does it take to fill the hole completely?
WHAT: Each warp we bring in contributes cycles of work into the -cycle hole. We keep adding warps until their combined work covers the whole hole.
WHY division: "How many chunks of size fit inside a gap of size ?" is literally the question answers. Division is the tool because we are packing equal-sized work blocks () into a fixed span ().
PICTURE: Warp 0's red hole, now tiled by -sized black blocks from warps 1, 2, 3, … Count how many blocks it takes to reach the right edge.

Step 6 — Why the ceiling, not plain division
WHAT: can come out fractional — say . You cannot schedule a third of a warp.
WHY round up (ceiling): If you round down to 13 warps, their work is cycles — that leaves a 10-cycle gap where the machine idles again. Any leftover hole means wasted throughput, so we must round up to 14. The ceiling means "smallest whole number " — it exists precisely to guarantee we never leave a gap.
PICTURE: 13 blocks fall short (a thin red sliver survives). 14 blocks (round up) cover it fully — a tiny overshoot, which is fine; overshoot wastes nothing, undershoot wastes cycles.

Step 7 — The degenerate cases (never leave the reader stranded)
Case A — no memory reads (): extra warps needed. A warp that never waits needs no one to cover for it. ✔ (Compute-bound kernel.)
Case B — all work, tiny gaps ( huge): a small number, ceiling gives 1. One warp nearly hides its own latency through instruction-level parallelism. ✔
Case C — no work between reads (): division by zero — is undefined, and it should be: a warp doing zero work between reads can never self-cover; you would need infinitely many warps. In practice the hardware caps at ~64 resident warps, so you simply saturate the limit and still stall. ✔ This is the memory-bound wall.
PICTURE: Three mini-timelines side by side: (all black, no red), huge (one warp, red mostly filled by its own black), (endless red, no black can ever fill it).

The one-picture summary
Everything above in a single frame: warp 0's -cycle red hole, exactly black work-blocks from other warps tiling it edge-to-edge, and the formula stamped beneath.

Recall Feynman retelling — say it back in plain words
A warp is 32 workers who must take every step together. Cheap steps take one tick; asking distant memory for a number takes a huge stall of ticks. If one warp just waited out that stall, the machine would sit idle ~98% of the time — a disaster.
So the scheduler does something clever: the instant a warp stalls, it slides a different warp into the idle gap and runs its work — for free, because every warp keeps its own registers and its own bookmark, so switching is one pointer update.
Each substitute warp fills ticks of the -tick hole. "How many -chunks fill an -hole?" is just divided by . Because a leftover sliver means idle time, we round up — the ceiling. That is the whole story: Edge checks: no memory reads → need nobody; huge work per read → need one; zero work per read → no number of warps can save you (memory-bound). More compute per read means fewer warps needed — which is why chasing pure occupancy can mislead you.
Recall Quick self-test
What does measure? ::: Cycles waited for one memory read (latency), ~400. What does measure? ::: Useful work-cycles a warp runs between memory reads. Why ceiling and not floor? ::: Rounding down leaves an idle sliver; ceiling guarantees the hole is fully covered. With , how many warps? ::: . Why is switching warps free? ::: Each warp owns its registers + program counter, so a switch is one pointer update (zero-overhead). What happens when ? ::: Undefined / infinite — a warp with no compute between reads can never self-cover; you become memory-bound.