AnyLearn
All lessons
Computer Scienceintermediate

CPU Pipelines: Throughput, Hazards, and Stalls

A processor does not execute one instruction at a time. It overlaps them in a pipeline, which raises throughput without making any single instruction faster. This lesson covers pipeline stages, the three classes of hazard, forwarding, the load-use stall, and why a mispredicted branch is expensive.

Updated · AI-authored, review-gated · how lessons are made

Not signed in: your progress and quiz score won't be saved.
Progress1 / 10

Clock speed stopped being the answer

Two processors at the same clock frequency can differ several-fold in real work done. The reason is that frequency tells you how many cycles per second you get, not how much progress each cycle makes.

The standard accounting is:

time = instructions  x  cycles per instruction  x  seconds per cycle
                          (CPI)                     (1 / frequency)

Compilers attack the first term. Frequency attacks the third, and stopped scaling usefully once power density became the binding constraint. Nearly all of the interesting engineering for the last two decades has gone into the middle term.

CPI below 1 is the goal, and it is achievable because a core works on many instructions at once. Its reciprocal, instructions per cycle or IPC, is the number people usually quote. This cursus is about where IPC comes from and, more often, where it goes.

Full lesson text

All 10 steps on one page, for reading, reference, and search.

Show

1. Clock speed stopped being the answer

Two processors at the same clock frequency can differ several-fold in real work done. The reason is that frequency tells you how many cycles per second you get, not how much progress each cycle makes.

The standard accounting is:

time = instructions  x  cycles per instruction  x  seconds per cycle
                          (CPI)                     (1 / frequency)

Compilers attack the first term. Frequency attacks the third, and stopped scaling usefully once power density became the binding constraint. Nearly all of the interesting engineering for the last two decades has gone into the middle term.

CPI below 1 is the goal, and it is achievable because a core works on many instructions at once. Its reciprocal, instructions per cycle or IPC, is the number people usually quote. This cursus is about where IPC comes from and, more often, where it goes.

2. Pipelining: overlap, not acceleration

Executing an instruction involves several distinct jobs. The classic teaching model, from the RISC designs that Patterson and Hennessy use throughout Computer Organization and Design, splits it into five stages:

  • IF instruction fetch
  • ID instruction decode and register read
  • EX execute or compute an address
  • MEM access data memory
  • WB write back to a register

Run these strictly one after another and each instruction takes five cycles. Pipelining instead keeps all five stages busy on five different instructions at once, the way a laundry keeps the washer and dryer both running.

The critical point, and the one most often stated wrongly: pipelining does not make any single instruction faster. An individual instruction still passes through five stages. What changes is that one instruction can now complete every cycle instead of every fifth cycle. Latency is unchanged, throughput improves fivefold.

3. Five instructions in flight

At steady state every stage holds a different instruction. In the cycle shown, instruction 1 is retiring while instruction 5 is only just being fetched. Five instructions are in flight simultaneously, and from the outside the machine appears to finish one instruction per cycle. Reaching that steady state takes four cycles of fill, and draining it takes four more, which is why very short instruction sequences never see the full benefit.

flowchart LR
  A["Cycle 5"] --> B["IF: instruction 5"]
  A --> C["ID: instruction 4"]
  A --> D["EX: instruction 3"]
  A --> E["MEM: instruction 2"]
  A --> F["WB: instruction 1"]
  F --> G["One completes per cycle"]

4. Hazards: the three ways overlap breaks

Overlap is only safe when the instructions in flight are independent. When they are not, you have a hazard. There are exactly three kinds, and every pipeline complication in this lesson traces back to one of them.

  • Structural hazard. Two instructions need the same hardware in the same cycle. Largely designed away in modern cores by duplicating units, which is why it gets the least attention.
  • Data hazard. An instruction needs a value that an earlier, still-in-flight instruction has not produced yet.
  • Control hazard. The processor does not yet know which instruction comes next, because a branch has not resolved.

Data and control hazards are the interesting two. Data hazards are mostly solved by forwarding, which we will look at next. Control hazards are solved by guessing, which is a much stranger idea and turns out to be the foundation of modern performance.

5. Data hazards and the forwarding shortcut

Consider two dependent instructions:

add  r1, r2, r3    ; r1 = r2 + r3
sub  r4, r1, r5    ; needs r1

The add writes r1 in its WB stage, cycle 5. The sub reads registers in its ID stage, cycle 3. Taken naively the sub would read a stale r1 and produce a wrong answer, so it would have to stall two cycles waiting.

But the value is not actually missing. It exists at the end of the add's EX stage in cycle 3, sitting in a pipeline register. It simply has not been written to the architectural register file yet.

Forwarding, also called bypassing, wires the output of EX directly back to the input of EX for the following instruction. The sub gets its operand from the bypass network rather than the register file, and the stall disappears entirely. This is why back-to-back dependent arithmetic runs at full rate on real hardware despite the textbook dependency.

6. The load-use stall, which forwarding cannot fix

Forwarding solves the arithmetic case because the value exists early enough. One case defeats it:

ld   r1, 0(r2)     ; load r1 from memory
add  r3, r1, r4    ; needs r1 immediately

A load produces its value in the MEM stage, not EX. The dependent add needs it at the start of its EX stage, which is the same cycle. Forwarding cannot send a value backwards in time, so the pipeline must insert one bubble. This is the load-use hazard, and it is the reason compilers work hard to schedule an independent instruction into the slot immediately after a load.

Note the shape of the problem, because it recurs at every level of this cursus: arithmetic is cheap and predictable, memory is neither. Here the penalty is a single cycle, and only because we assumed the load hit in the fastest cache. Lesson three is about what happens when it does not.

7. Control hazards: the machine does not know what comes next

A conditional branch is a genuine problem for a pipeline. The condition is evaluated somewhere in the middle of the pipeline, but the very next instruction must be fetched on the cycle after the branch. The fetch stage needs an answer that does not exist yet.

Three responses are possible. Stall until the branch resolves, which costs the full distance from fetch to resolution on every branch. Execute both paths and discard one, which wastes half the work and does not compose with further branches. Or guess, proceed, and undo if wrong.

Every high-performance processor guesses. This is not a shortcut, it is structural: with branches occurring every handful of instructions in typical code, a pipeline that stalled on each one could never keep its stages full. The correctness requirement is that speculative work must be invisible until confirmed, which is why results are held back and only committed once the branch is known to have gone the predicted way.

8. What a wrong guess costs

When a prediction is wrong, everything fetched after the branch is bogus and must be discarded, and the pipeline refills from the correct address. The cost is roughly the depth of the pipeline, which is why deeper pipelines are not automatically better.

Agner Fog's measured figures, from The Microarchitecture of Intel, AMD and VIA CPUs (last updated May 2026), give the real numbers:

MicroarchitectureMeasured misprediction penalty
Intel Haswell, Broadwell, Skylake and later Lakes15 to 20 clock cycles
AMD Zen 1 to 3about 18 clock cycles on average
AMD Zen 415 to 18 clock cycles
AMD Zen 515 to 25 clock cycles

Fog notes for the Intel figure that the penalty "varies a lot". Treat these as the right order of magnitude rather than constants.

Put that in context. A correctly predicted branch is effectively free. A mispredicted one costs roughly what fifteen to twenty-five simple instructions would have. Prediction accuracy, not branch count, is what matters.

9. Worked example: what mispredictions do to CPI

Take a loop with an ideal CPI of 1.0, where 20% of instructions are branches, and assume a 17-cycle misprediction penalty.

prediction accuracy 99%:
  mispredict rate = 0.20 x 0.01 = 0.002 per instruction
  added CPI       = 0.002 x 17 = 0.034
  effective CPI   = 1.034          (3.4% slower)

prediction accuracy 95%:
  mispredict rate = 0.20 x 0.05 = 0.010 per instruction
  added CPI       = 0.010 x 17 = 0.170
  effective CPI   = 1.170          (17% slower)

prediction accuracy 80%:
  mispredict rate = 0.20 x 0.20 = 0.040 per instruction
  added CPI       = 0.040 x 17 = 0.680
  effective CPI   = 1.680          (68% slower)

The lesson is how fast this degrades. Dropping from 99% to 95% accuracy sounds minor, but the penalty grows from 0.034 to 0.170 CPI, a factor of five, and at 80% it is twenty times the original. This is why an unpredictable branch on a hot path, a comparison against random data for instance, can be worth restructuring into branchless arithmetic even at the cost of more instructions.

10. What pipelining costs, and what comes next

Pipelining is not free, and the tradeoffs explain a lot of processor history.

  • Deeper is not better. More stages allow a higher clock but raise the misprediction penalty proportionally. Intel's Pentium 4 pushed this hardest, and Fog records recovery there as "rarely less than 24 clock cycles" and potentially over 100. The industry retreated to moderate depths.
  • Forwarding costs wires. The bypass network grows roughly with the square of the number of execution units, and it sits on the critical path.
  • Speculation costs energy. Work that is discarded still consumed power. On mobile parts this is a real constraint, not an accounting detail.
  • Speculation costs more than energy. Because speculative execution leaves traces in the cache even when discarded, it became a security problem as well. That is a topic in its own right, not a footnote here.

We have assumed one instruction issued per cycle throughout, so CPI bottoms out at 1.0. Real cores do considerably better than that, and the next lesson is how: issuing several instructions per cycle and executing them out of order.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. What does pipelining actually improve?
    • The latency of each individual instruction
    • The clock frequency the chip can reach
    • Instruction throughput, while single-instruction latency is unchanged
    • The number of registers available to the compiler
  2. Why can forwarding eliminate the stall after an arithmetic instruction but not after a load?
    • Loads write to memory rather than registers, so there is nothing to forward
    • A load's value is only available in MEM, one stage too late for the next instruction's EX
    • Loads bypass the register file entirely and cannot be intercepted
    • Forwarding only works between instructions of the same type
  3. A processor has a 17-cycle misprediction penalty, 20% of instructions are branches, and prediction accuracy drops from 99% to 95%. Roughly what happens to CPI?
    • It rises from about 1.03 to about 1.17
    • It rises from about 1.03 to about 1.06
    • It is unaffected, since branches are only 20% of instructions
    • It roughly doubles, from 1.03 to about 2.06
  4. Which hazard type has largely been engineered away in modern high-performance cores?
    • Control hazards, thanks to accurate branch prediction
    • Data hazards, thanks to forwarding
    • Structural hazards, by duplicating functional units
    • Load-use hazards, by making caches faster
  5. Why did the industry move away from very deep pipelines such as the Pentium 4's?
    • Deep pipelines require too many architectural registers
    • Forwarding becomes impossible beyond a certain depth
    • Deeper pipelines cannot support out-of-order execution
    • The misprediction penalty grows with pipeline depth, offsetting the higher clock

Related lessons

Computer Science
intermediate

Why Most Code Is Memory Bound: The Roofline Model

Most real code never approaches a processor's arithmetic peak because it cannot be fed fast enough. The roofline model makes that concrete: plot operational intensity against achievable performance and the binding constraint becomes visible. This lesson covers the model, bandwidth versus latency, and the layout changes that follow.

9 steps·~14 min
AI
advanced

Finding the Next One: Fusion Beyond Attention

The pattern that made attention slow recurs across the stack, and once you know what to look for it is easy to find. This lesson applies the diagnosis to normalisation layers, optimizer steps, loss functions and inference decoding, covers why fused attention silently stops applying when a model deviates slightly from standard, and gives the profiling routine that decides where to look first.

10 steps·~15 min
AI
advanced

Writing Fused Kernels Without Writing CUDA

The reason most teams never fuse anything is that CUDA asks you to manage threads, shared memory and synchronisation by hand. Triton moves the unit of programming from a thread to a block and hands the rest to a compiler. This lesson covers what that buys, what it still asks of you, how to decide a kernel is worth writing, and how to be sure it is correct.

10 steps·~15 min
AI
advanced

Attention Is Memory-Bound, and Nobody Noticed for Five Years

For years attention was optimised by reducing FLOPs, and approximate methods that cut FLOPs kept failing to run faster. The reason is that attention was never compute-bound: it spends its time moving a matrix between GPU memory tiers. This lesson establishes that hierarchy, counts the traffic a standard implementation generates, and shows why an exact algorithm beat every approximation.

10 steps·~15 min