← tonia.ai
Computer Architecture

Many hands, one job

The main ways computers do several things at once, from a single instruction acting on many numbers to many cores sharing one memory. The page covers how a multicore chip keeps its caches consistent and why adding processors stops paying off. Three tools let you trace cache coherence, test scaling laws and design a multicore chip.

Part A

Models of parallel processing

Why parallelism

Until the mid-2000s, each new chip generation ran faster mostly because its clock did. When Dennard scaling ended, raising the clock further made chips too hot to cool, and extracting more instruction-level parallelism from one thread hit diminishing returns. Since then, performance growth has come mainly from doing more work in parallel: more data per instruction, more threads per core, more cores per chip and more chips per system.

LevelWhat runs in parallelWho finds itExample
Instruction-levelIndependent instructions from one threadHardware and compilerPipelining, superscalar issue
Data-levelThe same operation on many data elementsCompiler or programmerSIMD instructions, GPUs
Thread-levelSeparate instruction streams sharing memoryProgrammer or runtimeMulticore processors, multithreading
Request-levelIndependent jobs or requestsOperating system, schedulerWeb servers, cloud data centers

Flynn's taxonomy

Michael Flynn classified computers in 1966 by how many instruction streams and data streams they process at once. The four classes are still the common vocabulary.

Single data streamMultiple data streams
Single instruction streamSISD
A classic uniprocessor executing one instruction on one piece of data at a time
SIMD
One instruction applied to many data elements: vector units, packed SIMD extensions, GPU warps
Multiple instruction streamsMISD
Several operations on one data stream. Rare; sometimes used to describe systolic pipelines or redundant fault-tolerant systems
MIMD
Independent processors each running their own program on their own data: multicore chips, clusters, supercomputers
SIMD Instruction stream PEPEPEPE a[0]a[1]a[2]a[3] Every element gets the same operation in the same step MIMD prog Aprog Bprog Cprog D CoreCoreCoreCore Shared memory or network Each core follows its own program on its own data

SIMD and vectors

A SIMD instruction operates on a whole register of elements at once. One AVX instruction adds eight 32-bit floats; one AVX-512 instruction adds sixteen. Because only one instruction is fetched and decoded for many operations, SIMD is very energy efficient for regular, data-parallel work such as image processing, audio, linear algebra and machine learning.

Scalar loop
for (int i = 0; i < n; i++)
    c[i] = a[i] + b[i];
AVX: eight floats per instruction
for (int i = 0; i < n; i += 8) {
    __m256 va = _mm256_loadu_ps(&a[i]);
    __m256 vb = _mm256_loadu_ps(&b[i]);
    _mm256_storeu_ps(&c[i], _mm256_add_ps(va, vb));
}

The AVX version assumes n is a multiple of 8. Compilers usually produce code like this automatically from the scalar loop.

SIMD comes in two styles. Packed SIMD (SSE, AVX, Arm NEON) fixes the register width in the instruction set, so each wider generation needs new instructions. Vector architectures, from the Cray-1 to today's Arm SVE and RISC-V V, let the hardware choose the vector length and handle loop remainders with a vector-length register or masks, so one binary runs on any width. Branches inside a SIMD loop are handled with masks: every lane computes, and a mask decides which results are kept.

GPUs and SIMT

A GPU runs thousands of lightweight threads. Hardware groups them, 32 at a time on NVIDIA GPUs, into a warp that executes one instruction across all its threads: SIMD hardware presented to the programmer as independent threads, a model NVIDIA calls SIMT (single instruction, multiple threads). When threads in a warp take different branches, the warp runs each path in turn with the inactive threads masked off, so divergent code loses efficiency.

GPUs hide memory latency by switching among many warps rather than by large caches and out-of-order execution. They suit problems with massive, regular parallelism, which is why they dominate machine-learning training and most of the world's fastest supercomputers.

MIMD

Shared memoryDistributed memory
HardwareMulticore chips and multi-socket servers; one address spaceClusters of separate computers linked by a network
Memory accessUMA (uniform access, as in a single chip) or NUMA (faster to local memory than to another socket's)Each node reaches only its own memory directly
CommunicationLoads and stores to shared variablesExplicit messages
ProgrammingThreads, OpenMPMPI
Main challengesCoherence, synchronization, racesCommunication cost, data distribution
ScaleUp to hundreds of coresUp to millions of cores

Shared-memory parallelism can be very concise. OpenMP splits this loop across all cores and combines each core's partial sum:

#pragma omp parallel for reduction(+:sum)
for (long i = 0; i < n; i++)
    sum += a[i];

Other models

ModelIdeaWhere it appears
SPMDSingle program, multiple data: every processor runs the same program on its own part of the dataMost MPI and GPU programs; a programming style on MIMD hardware
MultithreadingOne core interleaves several threads to fill idle cycles: fine-grained (switch every cycle), coarse-grained (switch on long stalls) or simultaneous (SMT: issue from several threads in the same cycle)Intel Hyper-Threading, AMD SMT, IBM POWER (up to 8 threads per core)
Systolic arraysA grid of simple cells, each passing data to its neighbors in rhythm, so each value is reused many times without returning to memory (Kung)Google TPU matrix units, signal processing
DataflowAn instruction runs as soon as its inputs arrive, with no program counterResearch machines; the idea lives on inside out-of-order cores and some accelerators
HeterogeneousDifferent kinds of cores on one chip, each suited to part of the workPhone and laptop chips with performance and efficiency cores, GPUs and neural engines
Part B

Multicore processors

Inside a multicore chip

Olukotun and colleagues argued in 1996 that several simple cores on one chip would beat one ever more complex core, and by the mid-2000s every major vendor had followed. A typical multicore processor has:

CoresEach with its own pipeline, often 2-way SMT; possibly two kinds, for performance and for efficiency
Private cachesL1 instruction and data caches per core, usually a private L2
Shared last-level cacheSplit into slices, one per core or cluster
CoherenceHardware that keeps every core's view of memory consistent
On-chip interconnectA ring, mesh or crossbar linking cores, cache slices, memory controllers and I/O
Memory controllers and I/ODRAM channels, PCIe and chip-to-chip links for multi-socket systems

Key design choices include how many cores to build and how large to make each one, how much cache to share, the interconnect topology, and whether to split the design into chiplets: several smaller dies in one package, which improves manufacturing yield at the cost of slower links between dies.

Cache coherence

When two cores cache the same memory block, a write by one must not leave the other reading a stale copy. A coherence protocol guarantees that every core sees writes to the same location in a single order, and eventually sees the latest value. Most protocols are write-invalidate: before a core writes, every other copy is invalidated.

Small systems use snooping: every cache watches a shared bus or broadcast network for other cores' requests. Large systems use a directory (Censier and Feautrier) that records which caches hold each block, so requests go only to those caches instead of to everyone.

MESI stateMeaningCan readCan write without a bus request
M ModifiedOnly copy, and dirty: memory is out of dateYesYes
E ExclusiveOnly copy, cleanYesYes, silently becoming M
S SharedOne of possibly several clean copiesYesNo: must invalidate the others first
I InvalidNo valid copyNo: must fetchNo: must fetch and invalidate

The Exclusive state, from Papamarcos and Patel's protocol, saves a bus transaction in the common case of reading private data and then writing it.

MESI simulator

Follow one memory block through a snooping MESI protocol. Enter operations as R (read), W (write) or E (evict) followed by a core number, such as R0 W1 E0.

Things to try. "Read sharing" needs one bus request per core and then runs without traffic. In "Read, then write", core 0's second write is free because Exclusive upgrades silently. "Two cores writing in turn" generates a bus transaction and a transfer of the whole block on every single write, even if the cores write different variables that happen to share a block.

False sharing

Coherence works on whole blocks, not variables. If two threads update different variables that sit in the same 64-byte block, the block bounces between their caches exactly as in the ping-pong example above, even though the threads never share data. Torrellas, Lam and Hennessy measured how often this happens and how block size affects it. Padding each thread's data to its own block removes the problem:

Counters share blocks
struct { long count; } counters[NTHREADS];
One block per counter
struct { alignas(64) long count; } counters[NTHREADS];

Memory consistency

Coherence is about one location. Consistency is about the order in which a core's accesses to different locations become visible to other cores. Lamport defined sequential consistency: the result is as if all operations ran in some single interleaving that respects each program's order. Real hardware relaxes this for speed, mainly by letting stores wait in a store buffer while later loads go ahead.

Core 0Core 1Can both r1 and r2 be 0?
x = 1
r1 = y
y = 1
r2 = x
Sequential consistency: no. x86 (TSO), Arm, RISC-V: yes, because each core's store can still be in its store buffer when its load reads memory. A fence between the store and the load forbids it.

x and y start at 0. Adve and Gharachorloo's tutorial explains the common models; tools like herd7 enumerate exactly which outcomes each model allows.

Interconnects

TopologyAverage distance (p nodes)Bandwidth as p growsCostUsed for
Shared bus1 hopFixed: every node shares one busLowestEarly multiprocessors, a few cores
RingAbout p/4 hops (bidirectional)Grows slowlyLowClient CPUs with roughly 4–12 cores or slices
2D meshAbout 2√p/3 hopsGrows with √pModerateServer CPUs with dozens of cores
Crossbar1 hopGrows with pGrows with p², so only for small pConnecting a few clusters or cache banks
Part C

Scalability and performance

Scaling laws

Amdahl: S(p) = 1 / ((1 − f) + f / p)  ·  Gustafson: S(p) = (1 − f) + f · p

Amdahl's law assumes a fixed problem: if a fraction f of the work runs in parallel, the serial remainder caps the speedup at 1 / (1 − f), however many processors are added. With f = 0.95, 1,024 cores give only about 20×. Measuring this way is called strong scaling.

Gustafson's law assumes the problem grows with the machine, as with a bigger simulation mesh on a bigger computer, so the parallel part grows while the serial part does not. Measuring this way is called weak scaling, and it explains why supercomputers with millions of cores are useful. Neither law is wrong; they answer different questions.

Parallel efficiency is speedup divided by processor count. The Karp–Flatt metric works backward from a measured speedup S on p processors to the experimentally determined serial fraction e = (1/S − 1/p) / (1 − 1/p). If e grows as p grows, overhead rather than inherent serial work is limiting scaling.

Scalability explorer

Compare the two laws with a more realistic model that adds a coordination cost growing with the logarithm of the processor count, as tree-structured synchronization and reductions do.

AmdahlGustafsonAmdahl with overheadIdeal

What limits scaling

LimitWhy it grows with processorsMitigation
Serial codeIts share of run time rises as the parallel part shrinksParallelize more; grow the problem (weak scaling)
SynchronizationLocks and barriers make cores wait for the slowestFiner-grained or lock-free algorithms; fewer barriers
CommunicationMore boundaries between pieces of the problem; longer distancesPartition to keep data local; overlap communication with computation
Load imbalanceSmaller pieces vary more in costDynamic scheduling, work stealing
Memory bandwidthCores multiply, but DRAM channels do not keep paceCache blocking; more data reuse per byte (the roofline model)
Coherence trafficMore sharers, more invalidations, false sharingAvoid sharing writable data; padding
PowerNot every core can run at full speed at once ("dark silicon")Specialized and heterogeneous cores; lower clock under heavy load

Designing the chip

Hill and Marty applied Amdahl's law to a fixed chip budget of n "base core equivalents" (BCEs). Combining r BCEs makes one bigger core with performance √r, following Pollack's rule that performance grows roughly with the square root of core area. Three organizations follow:

  • Symmetric: n/r identical cores of size r. Big cores speed up serial code but leave fewer cores for parallel code.
  • Asymmetric: one big core of size r plus n − r small cores. The big core runs serial code; all cores share the parallel part.
  • Dynamic: resources that act as one big core for serial code and as n small cores for parallel code. An idealized upper bound.

Multicore design calculator

SymmetricAsymmetricDynamic

Things to try. With the defaults, the best symmetric chip uses cores of about 8 BCEs and reaches about 51×; the best asymmetric chip pairs one 64-BCE core with 192 small ones for about 125×. Lower f to 0.9 and the best designs shift to much bigger cores; raise it to 0.999 and many small cores win. That is the case for heterogeneous chips: a few big cores for serial code, many small ones for parallel throughput.

Comparing techniques

TechniqueGranularityScales toCommunication costEnergy efficiencyProgramming effortBest for
SIMD unitsSingle instructions4–64 lanesNone: registersVery highLow with auto-vectorization; higher with intrinsicsRegular loops over arrays
GPU (SIMT)Thousands of threadsTens of thousands of lanes per GPULow on-chip; high to the hostHigh for regular workModerate to highMassive, regular data parallelism
SMTThreads on one core2–8 threads per coreNone: shared cachesHigh when threads stall oftenNone beyond threadingLatency-bound, mixed workloads
Shared-memory multicoreThreadsUp to hundreds of coresCoherence trafficModerateModerate; races and locks are hardGeneral-purpose parallel programs
Distributed clusterProcessesMillions of coresHigh: network messagesDepends on localityHigh: explicit data distributionVery large problems, weak scaling

Real systems combine all of them: a supercomputer node runs MPI processes across nodes, threads across cores, SIMD within each core and GPU kernels on accelerators. Choosing well means matching each level of the hardware to a level of parallelism the problem actually has.

Go further

Resources

Interactive tools and references

Peer-reviewed reading

  • Flynn, M. J. (1966). Very high-speed computing systems. Proceedings of the IEEE, 54(12), 1901–1909.The origin of SISD, SIMD, MISD and MIMD.doi.org/10.1109/PROC.1966.5273
  • Russell, R. M. (1978). The CRAY-1 computer system. Communications of the ACM, 21(1), 63–72.The classic vector supercomputer.doi.org/10.1145/359327.359336
  • Kung, H. T. (1982). Why systolic architectures? IEEE Computer, 15(1), 37–46.The idea behind today's matrix accelerators.doi.org/10.1109/MC.1982.1653825
  • Lindholm, E., Nickolls, J., Oberman, S., & Montrym, J. (2008). NVIDIA Tesla: A unified graphics and computing architecture. IEEE Micro, 28(2), 39–55.The architecture that introduced SIMT computing on GPUs.doi.org/10.1109/MM.2008.31
  • Nickolls, J., & Dally, W. J. (2010). The GPU computing era. IEEE Micro, 30(2), 56–69.How GPUs became general-purpose parallel processors.doi.org/10.1109/MM.2010.41
  • Olukotun, K., et al. (1996). The case for a single-chip multiprocessor. Proc. ASPLOS VII, 2–11.Why several simple cores beat one complex core.doi.org/10.1145/248209.237140
  • Tullsen, D. M., Eggers, S. J., & Levy, H. M. (1995). Simultaneous multithreading: Maximizing on-chip parallelism. Proc. ISCA, 392–403.Thread-level parallelism inside one core.doi.org/10.1109/ISCA.1995.524578
  • Kumar, R., et al. (2003). Single-ISA heterogeneous multi-core architectures: The potential for processor power reduction. Proc. MICRO-36, 81–92.The research behind performance and efficiency cores.doi.org/10.1109/MICRO.2003.1253185
  • Censier, L. M., & Feautrier, P. (1978). A new solution to coherence problems in multicache systems. IEEE Transactions on Computers, C-27(12), 1112–1118.Directory-based coherence.doi.org/10.1109/TC.1978.1675013
  • Papamarcos, M. S., & Patel, J. H. (1984). A low-overhead coherence solution for multiprocessors with private cache memories. Proc. ISCA, 348–354.The protocol that became MESI.doi.org/10.1145/800015.808204
  • Torrellas, J., Lam, M. S., & Hennessy, J. L. (1994). False sharing and spatial locality in multiprocessor caches. IEEE Transactions on Computers, 43(6), 651–663.How block size creates false sharing.doi.org/10.1109/12.286299
  • Lamport, L. (1979). How to make a multiprocessor computer that correctly executes multiprocess programs. IEEE Transactions on Computers, C-28(9), 690–691.The definition of sequential consistency.doi.org/10.1109/TC.1979.1675439
  • Adve, S. V., & Gharachorloo, K. (1996). Shared memory consistency models: A tutorial. IEEE Computer, 29(12), 66–76.The standard introduction to relaxed memory models.doi.org/10.1109/2.546611
  • Dally, W. J. (1990). Performance analysis of k-ary n-cube interconnection networks. IEEE Transactions on Computers, 39(6), 775–785.Why low-dimensional meshes and tori suit real chips and machines.doi.org/10.1109/12.53599
  • Amdahl, G. M. (1967). Validity of the single processor approach to achieving large scale computing capabilities. Proc. AFIPS Spring Joint Computer Conference, 483–485.The original statement of Amdahl's law.doi.org/10.1145/1465482.1465560
  • Gustafson, J. L. (1988). Reevaluating Amdahl's law. Communications of the ACM, 31(5), 532–533.Scaled speedup when the problem grows with the machine.doi.org/10.1145/42411.42415
  • Karp, A. H., & Flatt, H. P. (1990). Measuring parallel processor performance. Communications of the ACM, 33(5), 539–543.Estimating the serial fraction from measured speedups.doi.org/10.1145/78607.78614
  • Hill, M. D., & Marty, M. R. (2008). Amdahl's law in the multicore era. IEEE Computer, 41(7), 33–38.The model behind the multicore design calculator.doi.org/10.1109/MC.2008.209
  • Esmaeilzadeh, H., et al. (2011). Dark silicon and the end of multicore scaling. Proc. ISCA, 365–376.Why power limits how many cores can run at once.doi.org/10.1145/2000064.2000108