JSTAcademy
0 XP
Dashboard
CS Foundations
Computer Architecture
16 min
PhD+175 XP
CS Foundations · PhD

Computer Architecture

CPU pipelines, memory hierarchies, caches — what happens below the code
16 min read+175 XP on completionCert: Computer Science Foundations
Tap any word in the text below to start reading from there.

Computer Architecture

Every line of code you write eventually becomes electrical signals in silicon. The path from high-level language to executed instruction involves compilers, instruction set architectures, and microarchitectural mechanisms that are invisible but determinative — the difference between code that runs in 10ms and code that runs in 10 seconds.

Instruction Set Architecture (ISA)

The ISA is the contract between software and hardware: the set of instructions, registers, and memory model that a CPU supports. Programs compiled for x86-64 run on any chip implementing that ISA, regardless of internal microarchitecture.

RISC vs CISC: Reduced Instruction Set Computing (ARM, RISC-V) uses simple, fixed-length instructions that execute in one cycle, relying on compilers to combine them. Complex Instruction Set Computing (x86) has hundreds of complex, variable-length instructions. Modern x86 processors internally translate CISC instructions into RISC-like micro-operations (μops), combining the software ecosystem of CISC with the microarchitectural advantages of RISC.

Registers are the CPU's fastest storage — 16-32 general-purpose registers, each holding 64 bits. Accessing a register is a single cycle. The goal of compiler register allocation is keeping frequently used values in registers rather than memory.

The Pipeline

A modern CPU executes instructions in stages: Fetch (read instruction from memory/cache), Decode (parse opcode and operands), Execute (perform arithmetic/logic in ALU), Memory (read/write data memory if needed), Writeback (store result in register).

Pipelining overlaps these stages — while instruction 5 executes, instruction 6 decodes and instruction 7 fetches. A 5-stage pipeline can theoretically execute 5 instructions per cycle (CPI of 1). Modern out-of-order superscalar CPUs handle 4-8 instructions per cycle by executing independent instructions simultaneously.

Hazards disrupt the pipeline. Data hazards: instruction B needs a result instruction A hasn't produced yet — solved by forwarding (passing results directly between stages) or stalling. Control hazards: branch instructions don't know the next PC until execution — solved by branch prediction. Structural hazards: two instructions need the same hardware unit simultaneously — solved by duplicating functional units.

Branch Prediction

Modern CPUs are deeply pipelined (10-20+ stages). A branch misprediction means flushing all in-flight instructions and restarting — a 15-20 cycle penalty. With branch prediction, the CPU guesses the branch outcome and continues filling the pipeline speculatively.

Modern predictors (tournament, TAGE) achieve >99% accuracy on typical workloads. The remaining 1% of mispredictions still dominate runtime in branch-heavy code. This is why sorting data before searching can speed up code: predictable branch patterns reduce mispredictions (the "branch prediction warm-up" effect in benchmarks).

Spectre and Meltdown (2018) demonstrated that speculative execution of mispredicted branches can access and leak privileged memory through cache side channels — the most severe hardware security vulnerabilities in decades.

Memory Hierarchy

The gap between CPU speed and DRAM latency is enormous: a register read takes 0 cycles; an L1 cache hit takes 4 cycles; L2 takes 12 cycles; L3 takes 40-50 cycles; DRAM takes 200-300 cycles. A cache miss to DRAM costs 200x more than an L1 hit.

Caches exploit locality. Temporal locality: recently accessed data will be accessed again. Spatial locality: nearby data will be accessed soon. Caches are organized into cache lines (64 bytes on x86) — the unit of transfer. Accessing any byte in a cache line loads the whole line.

Cache associativity balances simplicity and hit rate. Direct-mapped caches map each address to one cache slot — fast but prone to conflict misses. Fully associative caches allow any address in any slot — optimal hit rate but expensive. N-way set-associative (4-way, 8-way) balances both.

Cache coherence in multi-core systems ensures all cores see a consistent memory state. The MESI protocol assigns states to cache lines: Modified (dirty, exclusive), Exclusive (clean, exclusive), Shared (clean, multiple caches have it), Invalid (stale). When one core writes a Shared line, it sends an invalidation to other cores — a cache-to-cache transfer that takes ~50 cycles but is far faster than going to DRAM.

Writing Cache-Friendly Code

The fastest code manipulates data in patterns that maximize cache hits. Key techniques:

Sequential access: iterate through arrays element by element, not with large strides. A stride of 64 (skipping every cache line) reduces effective bandwidth by 64x.

Structure of Arrays vs Array of Structures: for processing one field across many objects, Structure of Arrays (separate arrays per field) has better cache behavior than Array of Structures (objects with all fields together).

Cache blocking (tiling): matrix multiplication naively has poor cache behavior. Tiling the computation into blocks that fit in cache can improve performance 10x.

SIMD and Parallelism

Modern CPUs support SIMD instructions: AVX-512 on x86 can add 16 float-32s in a single instruction. Compilers auto-vectorize simple loops; critical inner loops may need manual SIMD intrinsics or libraries that use them. NumPy, OpenBLAS, and deep learning frameworks are largely SIMD-optimized C/C++ libraries.

Hardware threads (SMT): Intel Hyper-Threading lets one physical core appear as two logical cores, interleaving two threads' instructions to hide memory latency. This improves throughput for memory-bound code but not for compute-bound code (both threads share the same execution units).

0%