Lecture 8: Parallel Processors: Multicores, Multiprocessors, and Clusters

Computer Organization and Design — Chapter 7

Babafemi Sorinolu

Learning Objectives

By the end of this lecture, you should be able to:

  1. Explain why computers moved from one fast processor to many cores.
  2. Tell apart a multiprocessor, a multicore chip and a cluster.
  3. Distinguish concurrency from parallelism, and task-level parallelism from parallel processing.
  4. Use Amdahl’s law to predict speed-up, and tell strong from weak scaling.
  5. Compare shared memory multiprocessors with message-passing clusters.
  6. Describe fine-grained, coarse-grained, and simultaneous multithreading.
  7. Classify hardware as SISD, SIMD, MIMD, and explain vector instructions and GPUs.
  8. Compare network topologies and use the roofline model to find what limits a program.

Roadmap

  1. Why go parallel? What are we building, and why?
  2. Why parallel programming is hard: Why don’t 100 cores give 100× speed?
  3. Shared memory: How do cores share data?
  4. Clusters and message passing: What if each computer has its own memory?
  5. Hardware multithreading: How do we keep one core busy?
  1. SIMD and vector: One instruction on many data?
  2. GPUs: Thousands of threads at once?
  3. Network topologies: How do we connect the cores?
  4. Benchmarks and roofline: How fast is it really?
  5. Fallacies and summary: What should we remember?

Parts 1–10 follow Sections 7.1–7.13 of the textbook.

Part 1: Why Go Parallel?

Why Do We Need Multiple Processors?

Goal: do more work in less time, while using energy efficiently.

  • For decades, chips got faster by raising the clock rate, until the power wall: too much power and heat (Chapter 1).
  • New plan: put more processors (cores) on a chip instead of making one core faster.
  • Small, efficient cores give better performance per watt than one big, hot core.
  • Analogy: instead of one worker rushing through four jobs, hire four workers to share them.

Consequence for you

Sequential programs no longer get faster “for free” on new chips. To go faster, programs must use the extra cores.

Uniprocessor, Multicore, Cluster

A uniprocessor with one core, a multicore chip with four cores sharing memory, and a cluster of three computers on a network

A multicore chip is one kind of multiprocessor. A cluster links whole computers together.

Key Vocabulary

Term Meaning
Uniprocessor A computer with one processor
Multiprocessor A computer with two or more processors (the general term)
Multicore Several processors (cores) on one chip. A quad-core chip has 4 cores.
Cluster Separate computers, each with its own memory, connected by a network to work as one big system

Why Use Multiple Processors?

  • Higher performance: more work done at the same time.
  • Better energy efficiency: many small cores beat one big core in performance per watt.
  • Handle more tasks: a server can serve many users at once.
  • Better availability: if one of 4 processors fails, the other 3 can keep working (just more slowly).

Note

Key takeaway: more processors can improve performance, but only if the software is designed to use them.

Two Ways to Use Many Processors

Left: four cores each run a different program. Right: one job of 1000 photos split across four cores
  • Task-level (job-level) parallelism: run different, independent programs at the same time. Easy, with no changes to the programs.
  • Parallel processing program: one program split across several processors. This is harder, because the programmer must divide the work.

Concurrency vs. Parallelism

One core alternating between two tasks versus two cores running them at the same time
  • Concurrency (a property of the software): several tasks are in progress during overlapping periods. They can take turns on one core.
  • Parallelism (a property of the hardware): several operations execute at the same instant on multiple cores.
  • A program can be concurrent without running in parallel.

Sequential vs. Concurrent Software

Sequential software

Steps follow one fixed order.

Example: a compiler: lexical analysis → parsing → code generation → optimization.

Example: compute the total price, add tax, then print the result.

Concurrent software

Many activities make progress over overlapping periods.

Example: an operating system handling downloads, keyboard input and music playback, all at once.

Important

Running a sequential program on a multicore computer does not automatically make it faster. It still uses only one core at a time.

Hardware and Software Are Separate Questions

  1. Hardware: can the computer execute several operations at the same time? (serial vs. parallel)
  2. Software: is the program written as one sequence or as many tasks? (sequential vs. concurrent)
Sequential software Concurrent software
Serial hardware (1 core) Matrix multiply on a Pentium 4 Operating system on a Pentium 4
Parallel hardware (many cores) Matrix multiply on an 8-core Xeon (may use only 1 core!) Operating system on an 8-core Xeon

The challenge: make both kinds of software run fast on parallel hardware.

Quick Quiz

  1. A computer has four cores on one chip. What is it called?
  2. A single-core processor switches between a browser and a music player. Concurrency or parallelism?
  3. Several separate computers communicate over a network to solve a big problem. What is this called?
  4. True or false: To benefit from a multiprocessor, an application must be concurrent.
  1. A multicore processor (microprocessor).
  2. Concurrency. Both tasks make progress, but one core never runs both at the same instant.
  3. A cluster.
  4. False. Even sequential programs benefit through task-level parallelism: independent programs can each run on their own core.

Part 2: Why Is Parallel Programming Hard?

The Reporter Analogy

Hardware gives us the opportunity for parallelism. Software must use it, and that is the hard part.

Eight reporters want to write one news story 8× faster.

What can go wrong?

  • Story pieces are unequal → some reporters sit idle.
  • Reporters spend too long talking to each other.
  • Someone must combine the pieces at the end.

Same problems in parallel programs

  • Scheduling: who does what?
  • Load balancing: equal work for everyone
  • Dependencies & synchronization: some steps must wait for others
  • Communication overhead: sending data around

More reporters (processors) → these problems get worse. Parallel programs must be both correct and efficient.

Amdahl’s Law

The part of a program you cannot speed up limits the total speed-up.

\[ \text{Time after} = \frac{\text{Time affected}}{\text{Amount of improvement}} + \text{Time unaffected} \]

If the original time is 1 and a fraction \(F\) can run in parallel on \(P\) processors:

\[ \text{Speed-up} = \frac{1}{(1 - F) + \dfrac{F}{P}} \]

  • \((1 - F)\) = the sequential part, which no amount of processors can shrink.
  • As \(P \to \infty\): \(\text{Speed-up} \to \dfrac{1}{1 - F}\)

Amdahl’s Law: The Picture

Speed-up versus number of processors for 1, 5, 10 and 25 percent sequential code

Even with only 1% sequential code, 128 processors give less than 60×.

Example 1: Speed-up Challenge

Goal: a speed-up of 90× with 100 processors. How much of the program can be sequential?

  • Set up: \(\;90 = \dfrac{1}{(1 - F) + \dfrac{F}{100}}\)
  • Flip both sides: \(\;(1 - F) + 0.01F = \dfrac{1}{90} = 0.0111\)
  • Simplify: \(\;1 - 0.99F = 0.0111 \;\Rightarrow\; F = \dfrac{0.9889}{0.99} \approx 0.999\)
  • So the sequential part must be only about 0.1% of the original time!

Takeaway

To use many cores well, almost everything must be parallel.

Example 2: Make the Problem Bigger

Sum 10 scalar variables (sequential) + sum two matrices (parallel). One addition takes time \(t\).

Problem 1 processor 10 processors 100 processors
10×10 (100 adds) \(110t\) \(\frac{100t}{10} + 10t = 20t\) → 5.5× \(\frac{100t}{100} + 10t = 11t\) → 10×
100×100 (10,000 adds) \(10{,}010t\) \(\frac{10{,}000t}{10} + 10t = 1010t\) → 9.9× \(\frac{10{,}000t}{100} + 10t = 110t\) → 91×

With 100 processors: small problem → only 10% of the ideal 100×; large problem → over 90%. Bigger problems are easier to speed up: the parallel part grows, the sequential part doesn’t.

Strong vs. Weak Scaling

Strong scaling

  • Problem size stays fixed.
  • Add processors → each gets less work.
  • Memory per processor ≈ \(M / P\)
  • Hard: Amdahl’s law hits quickly.

Weak scaling

  • Problem size grows with the number of processors.
  • Each processor keeps the same amount of work.
  • Memory per processor ≈ \(M\)
  • Easier to show good speed-up.

Real-world example: a bank benchmark (TPC-C) must add more customer accounts to report more transactions per minute. Customers don’t use the ATM 100× more often just because the bank bought a faster computer.

Example 3: Load Balancing

Same 100×100 problem on 100 processors. Ideal: each processor does 1% of the work → 91×.

What if one processor gets more than its share?

One processor’s share Time Speed-up
1% (balanced) \(100t + 10t = 110t\) 91×
2% (200 adds) \(\max\!\left(\frac{9800t}{99}, 200t\right) + 10t = 210t\) 48×
5% (500 adds) \(\max\!\left(\frac{9500t}{99}, 500t\right) + 10t = 510t\) 20×

Everyone must wait for the slowest processor. One processor with 2× the load cuts the speed-up almost in half.

Check Yourself

True or false: Strong scaling is not bound by Amdahl’s law.

False. Strong scaling keeps the problem size fixed, so the sequential part limits the speed-up exactly as Amdahl’s law says. (Weak scaling can hide this by growing the parallel part.)

Part 3: Shared Memory Multiprocessors

Shared Memory Multiprocessor (SMP)

Processors with caches connected by a network to one shared memory
  • One address space: any processor can load or store any memory location.
  • Processors communicate implicitly through shared variables.
  • Hardware cache coherence keeps every core’s view of memory consistent (Chapter 5).
  • Most multicore chips work this way.

Important

Sharing memory makes communication easy, but cores must coordinate when they read and write the same data (next slides).

UMA vs. NUMA

UMA NUMA
Full name Uniform Memory Access Non-Uniform Memory Access
Memory access time About the same for every processor and every address Faster for nearby memory, slower for far memory
Programming Easier Harder (you should care where data lives)
Scale Smaller systems Scales to larger systems

Synchronization and Locks

When processors share data, they must coordinate.

  • Synchronization: coordinating two or more processes so that one does not use data before another has finished writing it.
  • Lock: only one processor at a time can hold it.
    • Processor acquires the lock → uses the shared data → releases the lock.
    • Others wait until the lock is released.

Note

Section 2.11 showed the MIPS instructions used to build locks (ll / sc).

Example: Sum 100,000 Numbers on an SMP

100 processors, numbered Pn = 0 … 99. Each sums its own 1,000 numbers.

Step 1: each processor sums its own slice

sum[Pn] = 0;
for (i = 1000*Pn; i < 1000*(Pn+1); i = i + 1)
    sum[Pn] = sum[Pn] + A[i];     /* sum the assigned area */
  • All data is in one shared array A; each processor just starts at a different address.
  • Now we have 100 partial sums. How do we combine them?

Step 2: Reduction (Divide and Conquer)

A reduction combines many values into one.

Reduction tree: 8 partial sums combined in 3 rounds

100 partial sums need only \(\lceil\log_2 100\rceil = 7\) rounds instead of 99 sequential additions.

Reduction Code

half = 100;                       /* 100 processors */
repeat
    synch();                      /* wait for partial sums to finish */
    if (half % 2 != 0 && Pn == 0)
        sum[0] = sum[0] + sum[half-1];   /* odd case: P0 takes the extra one */
    half = half / 2;              /* dividing line on who sums */
    if (Pn < half)
        sum[Pn] = sum[Pn] + sum[Pn+half];
until (half == 1);                /* final sum is in sum[0] */
  • synch() is a barrier: no processor continues until all arrive.
  • Without it, a processor might read a partial sum before it is ready.
  • i and half must be private variables, one copy per processor.

Check Yourself

True or false: Shared memory multiprocessors cannot take advantage of job-level parallelism.

False. An SMP can run many independent jobs at once, each in its own virtual address space.

Part 4: Clusters and Message Passing

Message-Passing Multiprocessor

Each node has a processor, cache and private memory; nodes are joined by a network
  • Each processor has a private address space.
  • To share data, a processor must explicitly send a message, and another must receive it.
  • send / receive also act as synchronization: the receiver waits until the message arrives.

Clusters

A cluster is a set of ordinary computers connected by standard network switches and cables.

  • Each node runs its own copy of the operating system.
  • Used for web servers, search engines, email, databases and science. Grid computing spreads them worldwide (e.g., SETI@home).
✅ Strengths ❌ Weaknesses
Cheap commodity parts Managing n machines ≈ cost of n separate machines
High availability: replace a broken machine without stopping the system Connected through I/O (slower) instead of the memory interconnect
Easy to expand gradually Memory is divided: n memories and n copies of the OS

Example: Memory Efficiency

  • Shared memory: 1 machine with 20 GB; the OS uses 1 GB.
  • Cluster: 5 machines with 4 GB each; each OS uses 1 GB.

How much more memory is available for user programs with shared memory?

\[ \frac{20 - 1}{5 \times (4 - 1)} = \frac{19}{15} \approx 1.27 \]

The shared-memory machine has about 27% more space for user programs, even though both systems have 20 GB in total.

Example: Sum 100,000 Numbers with Message Passing

Step 1: One processor sends 1,000 numbers to each of the 100 nodes.

Step 2: Every node sums its local array:

sum = 0;
for (i = 0; i < 1000; i = i + 1)   /* loop over local array */
    sum = sum + AN[i];

Now each of the 100 nodes holds one partial sum in its own memory.

Message Passing: The Reduction

Step 3: combine the partial sums by sending messages:

limit = 100; half = 100;              /* 100 processors */
repeat
    half = (half + 1) / 2;            /* send vs. receive dividing line */
    if (Pn >= half && Pn < limit) send(Pn - half, sum);
    if (Pn < (limit / 2))          sum = sum + receive();
    limit = half;                     /* upper limit of senders */
until (half == 1);                    /* final sum is on P0 */

Upper half sends, lower half receives and adds: same divide-and-conquer idea, but with messages.

Shared Memory vs. Message Passing

Shared memory (SMP) Message passing (cluster)
Address space One, shared One per node, private
Communication Implicit (load/store) Explicit (send/receive)
Synchronization Locks, barriers Built into send/receive
Hardware design Harder (cache coherence) Easier
Porting a sequential program Easier Harder (plan every message)
Performance surprises More (hidden communication) Fewer (visible communication)
Availability / expansion Harder Easier

Check Yourself

  1. True or false: Like SMPs, message-passing computers rely on locks for synchronization.
  2. True or false: Unlike SMPs, message-passing computers need multiple copies of the parallel program and the operating system.
  1. False. Sending and receiving a message is itself a form of synchronization.
  2. True. Each node has its own memory, so each needs its own copy of the program and of the OS.

Part 5: Hardware Multithreading

What Is Hardware Multithreading?

Idea: when one thread stalls (e.g., waiting on a cache miss), let another thread use the processor.

To make this possible, the hardware keeps a separate copy of each thread’s state:

  • its own register file
  • its own program counter (PC)

Memory is shared through virtual memory.

Why hardware?

A thread switch in hardware can be almost instant. A process switch in the operating system takes hundreds to thousands of cycles.

Three Styles of Multithreading

Style When does it switch threads? 👍 Good 👎 Bad
Fine-grained Every cycle (round-robin) Hides short and long stalls Each thread runs slower
Coarse-grained Only on costly stalls (L2 miss) One thread runs at full speed Can’t hide short stalls; pipeline refill cost
Simultaneous (SMT) Never: several threads issue in the same cycle Fills idle issue slots Needs a complex out-of-order, multiple-issue core

Example: Intel’s Nehalem cores run 2 threads with SMT (Intel calls it Hyper-Threading).

Who Uses the Issue Slots?

Issue slots used by four threads under no multithreading, coarse, fine, and simultaneous multithreading

A 4-wide superscalar processor running four threads (illustrative).

Reading the Picture

  • No multithreading: a long stall leaves the whole processor idle, and limited ILP wastes slots.
  • Coarse-grained: switches after a stall, so fewer fully empty cycles, but switching still costs cycles.
  • Fine-grained: a different thread every cycle, so almost no fully empty cycles, but each cycle still only uses one thread’s instructions.
  • SMT: many threads fill the slots in the same cycle, so the fewest wasted slots.

Note

Multicore and multithreading both use parallelism to get more work out of a chip. Multithreading shares one core’s units, while multicore duplicates the cores.

Check Yourself

  1. True or false: Both multithreading and multicore rely on parallelism to get more efficiency from a chip.
  2. True or false: Simultaneous multithreading uses threads to improve resource utilization of a dynamically scheduled, out-of-order processor.
  1. True.
  2. True.

Part 6: SISD, MIMD, SIMD, SPMD, and Vector

Flynn’s Classification

Classify hardware by the number of instruction streams and data streams:

Single data stream Multiple data streams
Single instruction stream SISD: a uniprocessor (Pentium 4) SIMD: x86 SSE instructions
Multiple instruction streams MISD: no real examples MIMD: a multicore (8-core Xeon)
  • SPMD (Single Program, Multiple Data) is the usual way to program a MIMD machine: write one program, run it on all processors, and use if (Pn == …) so processors can do different parts.
  • The sum examples earlier were SPMD programs!

SIMD: One Instruction, Many Data

A single SIMD instruction can, for example, add 64 pairs of numbers at once using 64 ALUs.

  • All units run the same instruction from one PC, which feels like ordinary sequential programming.
  • Only one copy of the code and one control unit are needed.
  • Works best on arrays in for loops → data-level parallelism.
  • Works worst on switch / case statements: units with the “wrong” case sit idle, so you get about \(1/n\) performance for \(n\) cases.

SIMD in x86: Multimedia Extensions (MMX, SSE)

One wide ALU can be split into smaller ALUs:

One 64-bit register can hold …
1 × 64-bit value
2 × 32-bit values
4 × 16-bit values
8 × 8-bit values
  • Added to speed up multimedia (images, audio, video).
  • The data width is encoded in the opcode, so every new width means new instructions → hundreds of SSE instructions.

Vector Architecture

An older, more elegant form of SIMD (Cray supercomputers).

  1. Load a whole vector of data from memory into a vector register.
  2. Operate on the elements in a pipelined ALU.
  3. Store the results back to memory.

Example: 32 vector registers, each holding 64 elements of 64 bits.

Example: DAXPY (Y = a × X + Y)

\(X\) and \(Y\) are vectors of 64 doubles; \(a\) is a scalar.

Ordinary MIPS (loop runs 64 times)

      l.d   $f0,a($sp)     ;load scalar a
      addiu r4,$s0,#512    ;upper bound
loop: l.d   $f2,0($s0)     ;load x(i)
      mul.d $f2,$f2,$f0    ;a * x(i)
      l.d   $f4,0($s1)     ;load y(i)
      add.d $f4,$f4,$f2    ;a*x(i) + y(i)
      s.d   $f4,0($s1)     ;store y(i)
      addiu $s0,$s0,#8     ;next x
      addiu $s1,$s1,#8     ;next y
      subu  $t0,r4,$s0     ;compute bound
      bne   $t0,$zero,loop ;done?

Vector MIPS

l.d     $f0,a($sp)  ;load scalar a
lv      $v1,0($s0)  ;load vector x
mulvs.d $v2,$v1,$f0 ;vector * scalar
lv      $v3,0($s1)  ;load vector y
addv.d  $v4,$v2,$v3 ;add y to product
sv      $v4,0($s1)  ;store result

6 instructions instead of almost 600!

Why Vectors Are Fast (and Save Power)

  • One instruction = a whole loop → far less instruction fetch and decode.
  • Elements in a vector are independent → no hazard checks inside a vector.
  • Hazards are checked once per vector, not once per element → about 64× fewer stalls than the scalar loop in DAXPY.
  • Known memory access pattern → memory latency is paid once per vector.
  • No loop branch → no control hazards.

Note

Vector vs. SSE: in a vector machine the number of elements is in a register, not in the opcode, so new hardware with longer vectors can run old binaries. Vectors also support strided and indexed (non-contiguous) loads.

Check Yourself

True or false: As exemplified in the x86, multimedia extensions can be thought of as a vector architecture with short vectors that supports only sequential (contiguous) vector data transfers.

True.

Part 7: Graphics Processing Units (GPUs)

How GPUs Differ from CPUs

GPUs grew out of video games: drawing millions of independent pixels.

CPU GPU
Role General purpose Accelerator for the CPU
Hiding memory latency Big multilevel caches Many threads: run others while one waits
Memory optimized for Latency Bandwidth
Cores A few powerful cores Many simple, multithreaded cores
Programming C, Java, … OpenGL, DirectX → now CUDA
  • CPU + GPU = a heterogeneous system (not all processors are the same).
  • Don’t forget the time to copy data between CPU and GPU memory.

NVIDIA GPU Vocabulary (Tesla, 2008)

GPU term Meaning
Streaming processor (SP) A simple core (8 per multiprocessor)
Multiprocessor (MP) A group of SPs (the GeForce 8800 GTX has 16)
Warp A group of 32 threads scheduled together
SIMT Single Instruction, Multiple Thread: a warp runs one instruction together
Thread block Up to 512 threads on one MP that can share local memory
CUDA C-like language for programming GPUs

Example: GeForce 8800 GTX by the Numbers

Peak compute: 16 multiprocessors, 8 SPs each, 1 multiply-add (= 2 FLOPs) per SP per clock, 1.35 GHz

\[ 16 \times 8 \times 2 \times 1.35 \text{ GHz} = 345.6 \text{ GFLOP/s} \]

Peak memory bandwidth: 6 memory partitions, 8 bytes wide, 2 transfers per clock, 0.9 GHz

\[ 6 \times 8 \text{ B} \times 2 \times 0.9 \text{ GHz} = 86.4 \text{ GB/s} \]

Ratio: \(345.6 / 86.4 = 4\) FLOPs per byte. To use the full compute power, a GPU program must do about 4 operations for every byte it reads. (This idea returns in the roofline model.)

Branch Divergence

Threads in a warp share one instruction fetch unit.

if (x[i] > 0)
    y[i] = a;      // some threads take this path ...
else
    y[i] = b;      // ... others take this one
  • If threads in a warp take different paths, the warp runs both paths, one after another, with some threads idle.
  • Best performance: all 32 threads in a warp follow the same path.
  • This is the same weakness as SIMD with switch statements.

Note

Modern GPUs have thousands of cores, but the core ideas (warps of 32 threads, SIMT, hiding latency with many threads) are still the same.

Check Yourself

True or false: GPUs rely on graphics DRAM chips to reduce memory latency and thereby increase performance on graphics applications.

False. Graphics DRAM provides high bandwidth. GPUs hide latency by switching among many threads, not by having low-latency memory.

Part 8: Multiprocessor Network Topologies

Connecting the Cores

Multicore chips need a network on chip. The design trade-off is cost vs. performance:

  • Cost: number of switches, links per switch, wires per link, link length
  • Performance: latency, throughput, contention, fault tolerance, power

Measuring a Network

Total network bandwidth (best case) = bandwidth of one link × number of links

Bisection bandwidth (worst case)

  1. Cut the machine into two halves.
  2. Add up the bandwidth of the links crossing the cut.
  3. Use the cut that gives the smallest value.

We use the worst case because a parallel program is often limited by its weakest link.

Comparing Topologies

\(P\) = number of processors; each link has bandwidth 1.

Topology Total bandwidth Bisection bandwidth \(P = 8\) (total / bisection)
Bus 1 1 1 / 1
Ring \(P\) 2 8 / 2
Fully connected \(\dfrac{P(P-1)}{2}\) \(\left(\dfrac{P}{2}\right)^2\) 28 / 16
  • Ring: cheap, and many messages can travel at once, but messages may hop through other nodes.
  • Fully connected: fastest but very expensive (links grow as \(P^2\)).
  • 2-D mesh and n-cube sit in between and appear in real machines.

Multistage Networks: Crossbar vs. Omega

Switches sit between processors instead of at each node.

Crossbar Omega network
Switches for \(n\) processors \(n^2\) \(2n \log_2 n\)
For \(n = 8\) 64 48
Any pattern of messages at once? ✅ Yes ❌ No, messages can block each other

In practice

Long wires are slow and costly, chips are 2-D, and power is limited. A topology that looks elegant on the whiteboard may be impractical in silicon, so many multicores use simple grids.

Part 9: Benchmarks and the Roofline Model

Parallel Benchmarks

Benchmark What it measures Scaling
Linpack Dense linear algebra (ranks the Top500) Weak
SPECrate Many SPEC CPU copies (job-level) Weak
SPLASH 2 Shared-memory scientific kernels Strong
NAS Fluid dynamics kernels Weak
PARSEC Multithreaded apps (Pthreads, OpenMP) Weak
Berkeley 13 patterns (sparse matrix, MapReduce, …) Either

Fixed rules keep benchmarks fair but block innovation; the Berkeley patterns allow any implementation.

The Roofline Model: Key Quantity

Arithmetic intensity (AI) = how much computation you do per byte you bring from memory:

\[ \text{AI} = \frac{\text{floating-point operations}}{\text{bytes transferred to/from main memory}} \]

  • Low AI (e.g., sparse matrix): mostly moving data → memory is the limit.
  • High AI (e.g., dense matrix multiply): lots of math per byte → compute is the limit.

The Roofline Model

\[ \text{Attainable GFLOP/s} = \min\left(\text{Peak memory BW} \times \text{AI},\;\; \text{Peak floating-point performance}\right) \]

Roofline for an AMD Opteron X2 with peak 16 GFLOP/s and memory bandwidth 16 GB/s

Example machine: AMD Opteron X2 (peak 16 GFLOP/s, memory bandwidth 16 GB/s).

Reading the Roofline

  • The slanted roof = memory limit. The flat roof = compute limit.
  • Draw a vertical line at your kernel’s AI, and performance can’t go above the roof there.
    • Kernel 1 (AI = 0.5) hits the slanted roof → memory-bound → at most \(16 \times 0.5 = 8\) GFLOP/s.
    • Kernel 2 (AI = 4) hits the flat roof → compute-bound → at most 16 GFLOP/s.
  • Ridge point (where the roofs meet):
    • Far left → almost any program can reach peak.
    • Far right → only programs with very high AI can reach peak.

Your Turn: Roofline Practice

A machine has peak = 32 GFLOP/s and memory bandwidth = 8 GB/s.

  1. Where is the ridge point?
  2. What is the attainable performance for a kernel with AI = 0.25?
  3. … and for a kernel with AI = 8?
  1. Ridge point: \(\text{AI} = 32 / 8 = 4\) FLOPs/byte
  2. \(\min(8 \times 0.25,\ 32) = 2\) GFLOP/s → memory-bound
  3. \(\min(8 \times 8,\ 32) = 32\) GFLOP/s → compute-bound

Optimizing with the Roofline: Ceilings

If your program is far below the roof, the roofline tells you what to fix first.

Compute ceilings (for high-AI kernels)

  1. Balance the floating-point mix (equal adds and multiplies, or use fused multiply-add)
  2. Improve ILP (e.g., loop unrolling) and use SIMD

Memory ceilings (for low-AI kernels)

  1. Software prefetching: keep many memory requests in flight
  2. Memory affinity: keep data in the DRAM next to the processor that uses it

You can also raise AI itself, for example with better cache use, so fewer bytes come from memory.

Real Stuff: Four Multicores (2008)

System Cores / threads Peak GFLOP/s SpMV* (GFLOP/s) LBMHD* (GFLOP/s)
Xeon e5345 8 / 8 75 (highest) 1.5 (lowest) 5.6 (lowest)
Opteron X4 8 / 8 74 3.6 14.1
UltraSPARC T2 16 / 128 22 4.1 10.5
Cell QS20 16 / 16 29 6.4 16.7

*Fully optimized. SpMV = sparse matrix × vector; LBMHD = fluid dynamics on a grid.

  • Highest peak → lowest real performance: the Xeon’s memory system was the bottleneck.
  • UltraSPARC T2 was the easiest to program well; Cell was the fastest but hardest.

Part 10: Fallacies, Pitfalls, and Summary

Fallacies

Fallacy: “Amdahl’s law doesn’t apply to parallel computers.”

  • One group claimed to “break” Amdahl’s law with linear speed-up on 1000 processors.
  • They used weak scaling: they did 1000× more work in the same time, not the same work 1000× faster.
  • Amdahl’s law still applies, but bigger problems help.

Fallacy: “Peak performance tracks observed performance.”

  • The Xeon had the highest peak and the slowest results.
  • Marketing multiplies peak per core by the number of cores, which assumes perfect speed-up!

Pitfall

Pitfall: Not rewriting software for a multiprocessor.

  • An OS protected the whole page table with one lock. That was fine on one CPU, but on many CPUs all page allocations were serialized.
  • Fix: use finer-grained locks (lock smaller pieces).

Summary

  • Power wall → the industry bet its future on multicore. Programmers must think in parallel.
  • Multicore = cores on one chip; cluster = computers on a network. Concurrency ≠ parallelism.
  • Amdahl’s law: the sequential part limits speed-up; weak scaling and load balancing help.
  • Shared memory (implicit, easy to port) vs. message passing (explicit, scalable, available).
  • Multithreading (fine, coarse, SMT) keeps a core busy when a thread stalls.
  • SIMD / vector / GPU exploit data-level parallelism in loops.
  • Networks: judge them by bisection bandwidth.
  • Roofline: performance ≤ min(memory BW × AI, peak FLOPs).

The Most Important Lesson

Hardware provides the opportunity for parallelism. Software must be designed to take advantage of it.

  • More cores only help if the work can be divided, balanced and coordinated.
  • Keep the sequential part small (Amdahl’s law), and know whether your program is limited by compute or memory (roofline).

Exit Ticket

  1. A program is 20% sequential. What is the maximum speed-up with infinitely many processors?
  2. Name one advantage of a cluster over a shared memory multiprocessor.
  3. A kernel has AI = 0.5 on the Opteron X2 roofline (16 GB/s, 16 GFLOP/s). Is it memory-bound or compute-bound?
  1. \(1 / 0.2 = 5\), so at most 5×
  2. Higher availability, easier to expand, cheaper commodity parts, simpler hardware (any one)
  3. Memory-bound: \(0.5 < 1\) (the ridge point), so it reaches at most 8 GFLOP/s