Purpose

These are the laws that make parallel-scaling claims falsifiable: given a measured speedup curve, they say whether the workload is limited by serial work, by communication, or by nothing yet. The numeric tables below are computed directly from the formulas (script run in the repo venv). These laws are the model layer under measurements like the reductions benchmark, which is an Amdahl story in miniature.

Amdahl’s law

Fix the problem. Split execution time into a fraction that parallelizes perfectly and a fraction that does not. On processors:

The derivation is one line — the parallel part shrinks by , the serial part does not — but the consequence is brutal because the serial term dominates as grows:

ceiling
0.501.781.972.002
0.904.718.779.9110
0.955.9315.4219.6420
0.997.4839.2691.18100
0.9997.9460.21506.181000

A 95%-parallel program never exceeds 20x, and at 64 cores it has already burned three quarters of its budget on the serial 5%. Historical footnote: Amdahl’s 1967 paper contains no formula — it is a two-and-a-half-page argument against parallel machines, estimating that data-management housekeeping consumed ~40% of executed instructions and would not parallelize. The algebra was formalized by later commentators.

The ceiling is set entirely by the serial fraction

No processor count escapes : a 5% serial share caps speedup at 20x forever. The approach is slow, too — at processors (19 for ) speedup is exactly half the ceiling, so the last factor of 2 costs unboundedly many cores. Hardware added past that point competes with the far cheaper option of shrinking itself.

Reading the serial fraction honestly. is not “lines of code outside the parallel loop.” It is everything whose cost fails to shrink with : lock acquisition and barriers, load imbalance (the barrier waits for the slowest worker), the fork/join and result-merge phases, and — critically on multicore — shared memory bandwidth. A saturated memory bus behaves exactly like serial work: for a bandwidth-bound kernel, speedup caps at (aggregate bandwidth) / (single-core bandwidth demand) no matter how many cores exist. When a measured curve flattens earlier than the code’s visible structure suggests, the effective serial fraction is telling you about one of these hidden components, and fitting to the measurements recovers it.

Gustafson’s law

Gustafson (1988) attacked the fixed-problem assumption: in practice, buying a 1024-node machine means running a 1024-node-sized problem. Fix the time instead, let the parallel work grow with , and ask how much more got done. If the scaled run spends fraction of its time in serial work, the same job on one processor would have taken , so the scaled speedup is

linear in with slope — no ceiling. With and : 1014x, against Amdahl’s 91x for the same fractions. This was not hypothetical: Gustafson’s team at Sandia reported 1016-1021x scaled speedups on a 1024-processor hypercube across three real applications, the results that ended the “Amdahl says parallelism is futile” era.

The two laws answer different questions rather than contradicting each other. Strong scaling (Amdahl): same problem, more processors, lower latency — the right lens when the problem size is fixed by external requirements, e.g. serving one request faster. Weak scaling (Gustafson): more processors, proportionally bigger problem, same wall-clock — the right lens for batch and simulation workloads where fidelity or dataset size soaks up capacity. Misapplied lenses produce nonsense in both directions: quoting weak-scaling numbers for a latency problem overstates what more hardware buys, and quoting Amdahl at a throughput problem understates it.

Where both laws are too optimistic

Both laws assume the parallel fraction costs nothing to coordinate. Add an overhead term that grows with (Brown 2000):

If is all-to-all communication, per step and the curve peaks at finite , then declines. Gunther’s Universal Scalability Law packages this into two fittable parameters:

where is contention (queueing for a shared resource; reduces the model to Amdahl’s shape) and is coherency (pairwise cost of keeping parties consistent: cache-line ping-pong, lock handoffs, consensus chatter — hence the ). The term is what Amdahl and Gustafson cannot express: retrograde scaling, throughput that falls when capacity is added, with the peak at . Computed example with , :

8326499200350
7.018.624.025.222.317.3

Peak 25.2x at , and 350 processors are 30% slower than 99. Fitting these three parameters to a measured scaling curve is the practical procedure: names your serialization, a nonzero names your crosstalk, and tells you where to stop buying hardware.

import numpy as np
 
def amdahl(p, N):    return 1 / ((1 - p) + p / N)
def gustafson(p, N): return N - (1 - p) * (N - 1)
def usl(N, sigma, kappa):
    return N / (1 + sigma * (N - 1) + kappa * N * (N - 1))
 
N = np.array([8, 32, 64, 99, 200, 350])
print(np.round(amdahl(0.95, N), 2))       # [ 5.93 12.55 15.42 16.78 18.26 18.97]
print(np.round(usl(N, 0.02, 1e-4), 1))    # [ 7.  18.6 24.  25.2 22.3 17.3]

Note the contrast in the two printed rows: the Amdahl curve with climbs monotonically toward its ceiling of 20, while the USL curve with a small turns over and falls.

Using the laws

  • Estimate before parallelizing. Profile the serial share first; if 20% of runtime is unparallelizable, the ceiling is 5x and a heroic 64-core port is wasted effort compared to attacking the serial 20%.
  • Diagnose from the curve’s shape. Flattening toward an asymptote is Amdahl-type serialization (); a peak followed by decline is coherency () — more parallelism will actively hurt, and the fix is reducing sharing (partitioning, per-core state, batching updates), not tuning the parallel code.
  • State which scaling regime a benchmark ran. “Linear to 1024 nodes” under weak scaling and under strong scaling are claims of very different strength; published speedup numbers are meaningless without this label.
  • Watch the denominator. Speedup is relative to the best serial implementation; a parallel program that scales beautifully over its own 1-thread mode may still lose to tuned serial code — Amdahl arguments silently assume the baseline is worth speeding up.

The queueing-side view of the same saturation phenomena — what happens to latency rather than throughput as load approaches capacity — is in Latency, Throughput, and Utilization and Queueing Theory.

Sources