Parallel Processors and Multicore

Learn why processors became parallel and how today's computers split work across many units at once. Compare instruction-, data-, thread- and request-level parallelism, classify machines with Flynn's taxonomy, and calculate the limits of speedup with Amdahl's law, Gustafson's law and the roofline model. See how SIMD and vector instructions, GPUs, multicore chips with coherent caches, clusters and warehouse-scale computers each turn parallel hardware into faster or cheaper computing, with worked examples you can check by hand.

IntermediateLesson 6 of 6 in Computer Organization and Architecture Course

What you will learn

  1. Explain why processors became parallel, tell instruction-, data-, thread- and request-level parallelism apart, classify machines with Flynn's taxonomy, and describe how hardware multithreading keeps one core busy.
    • Explain why computers went parallel and name the kinds of parallelism
      Connect the power wall with the move to multicore chips, and recognize instruction-, data-, thread- and request-level parallelism in real programs.
    • Classify parallel hardware with Flynn's taxonomy
      Use the number of instruction streams and data streams to place a machine in SISD, SIMD, MISD or MIMD, and explain the SPMD programming style.
    • Keep a core busy with hardware multithreading
      Explain how fine-grained, coarse-grained and simultaneous multithreading hide stalls, and how hardware threads differ from extra cores.
  2. Calculate speedup and efficiency, apply Amdahl's and Gustafson's laws, account for load imbalance and overhead, and use the roofline model to see whether compute or memory bandwidth limits a program.
    • Calculate speedup and efficiency with Amdahl's law
      Define speedup and efficiency, apply Amdahl's law in both directions, and explain why the sequential fraction caps the speedup of a fixed-size problem.
    • Distinguish strong and weak scaling and account for overheads
      Compare fixed-size and scaled-size speedup, apply Gustafson's law, and estimate the effect of load imbalance, communication and synchronization.
    • Bound performance with the roofline model
      Compute arithmetic intensity, read a roofline to decide whether a kernel is limited by memory bandwidth or by peak compute, and choose optimizations accordingly.
  3. Use SIMD instructions and vector architectures to process arrays, explain how a GPU is organized for throughput, and write and analyze a simple GPU kernel.
    • Process several data elements at once with SIMD instructions
      Work out how many lanes a SIMD register has, vectorize simple loops, and recognize the data layouts, branches and dependences that limit SIMD speedup.
    • Explain how vector architectures run loops
      Describe vector registers, the vector length, strip mining, lanes and strided access, using the RISC-V vector extension as the example.
    • Describe how a GPU is organized for throughput
      Explain streaming multiprocessors, warps and SIMT execution, how GPUs hide memory latency, branch divergence, memory coalescing and the cost of moving data, and how GPUs compare with CPUs and domain-specific accelerators.
    • Write and analyze a simple GPU kernel
      Use the grid, block and thread hierarchy to map data to threads, organize host and device work, and synchronize within a block.
  4. Describe shared-memory multiprocessors and how threads divide work, explain what cache coherence guarantees, trace snooping and directory protocols, and avoid false sharing.
    • Describe shared-memory multiprocessors and divide work among cores
      Explain a single shared address space, uniform and nonuniform memory access, the cache layout of a multicore chip, and how threads split and combine work.
    • Explain the cache coherence problem and what coherence guarantees
      Show how private caches can return stale data, state the conditions of a coherent memory system, and tell coherence apart from consistency and from race-free code.
    • Trace a snooping protocol with MSI and MESI states
      Follow cache block states and bus transactions through a sequence of reads and writes, and explain what the Exclusive state saves.
    • Explain directory protocols and avoid false sharing
      Describe how a directory tracks sharers, estimate its storage cost, and recognize, measure and fix false sharing.
  5. Describe message-passing clusters and compare interconnection networks by bandwidth and cost, then explain how warehouse-scale computers deliver internet services with attention to cost, energy and failures.
    • Describe message-passing clusters and compare interconnection networks
      Explain how nodes with private memories cooperate by messages, and compare network topologies by total bandwidth, bisection bandwidth and cost.
    • Explain how warehouse-scale computers deliver services at scale
      Describe the organization of a warehouse-scale computer and reason about its network, energy use and failures with simple calculations.

Parallel Processors and Multicore study guide

5 chapters

1

Find and classify parallel work

Parallel hardware can work on instructions, array elements, threads, or independent requests. The useful choice depends on where a program has work that can run together. Connect that work to the power limits that pushed chips toward multiple cores, then classify the hardware by its instruction streams. Hardware multithreading adds another way to keep a core busy by finding useful instructions during stalls.

1.1 Why chips now share the work

Parallel computers carry out operations at the same time. They can reduce latency, the time one job takes, or increase throughput, the number of jobs finished per second. Those goals lead to different ways of splitting work.

The power wall

Raising the clock rate once made each generation of processors faster. Dynamic power roughly follows P≈CV2f: capacitance times voltage squared times switching frequency. Voltage matters twice in that product. Reducing both voltage and frequency by 15% gives 0.852×0.85=0.614125 of the original dynamic power, about 61%.

Voltage could not keep falling enough to offset higher clock rates. Leakage and heat made continued frequency growth too costly. This power wall pushed the industry toward multicore chips in the mid-2000s. A multicore chip places several processor cores on one chip; a multiprocessor system has at least two processors. More modest cores can deliver more total work per joule, provided there is enough work to share.

Four places to find parallel work
KindWhat runs together?Example
Instruction-level parallelism (ILP)Instructions from one instruction streamA pipeline overlaps stages of successive instructions.
Data-level parallelism (DLP)The same operation on many elementsAdd corresponding elements of two arrays.
Thread-level parallelism (TLP)Several instruction sequencesSeveral threads process different image regions.
Request-level parallelismIndependent jobsServers answer many users' queries at once.

ILP is found mainly by hardware and compilers. Pipelining, multiple issue, and out-of-order execution overlap instructions while preserving the program's required results. Dependencies and branches limit the available overlap.

DLP appears when many elements need the same calculation. SIMD instructions, vector processors, and GPUs exploit this regularity. TLP requires work to be divided into threads by code, a library, or a compiler. A thread has its own program counter, registers, and stack; threads in one process share its address space. Separate processes have separate address spaces.

Request-level work needs little cooperation between jobs. Adding servers can therefore increase capacity nearly in proportion to the added resources. Running several independent programs on a laptop also uses otherwise idle cores, increasing overall throughput even when none of those programs is parallelized internally.

Concurrent tasks and simultaneous execution

Concurrency means tasks make progress during overlapping periods. One core can do this by taking turns between them. Parallelism means operations execute at the same instant on separate hardware. A single-core system can keep several programs in progress without executing their instructions simultaneously.

A program with one sequential thread does not divide itself across eight cores simply because they exist. The extra cores can run other work, but shortening this program requires parallel work within it. Even after work is split, any remaining sequential part still limits the gain.

Key Takeaways

  • Parallel hardware can lower one job’s latency or raise total throughput.
  • Dynamic power depends on voltage squared and frequency.
  • ILP, DLP, TLP, and request-level parallelism expose different kinds of work.
  • Concurrency can use time sharing; parallelism uses simultaneous execution.

1.2 Count instruction and data streams

A processor can contain many arithmetic units without following many independent instruction streams. Flynn's taxonomy classifies hardware by its instruction streams and data streams, so the first step is to choose the level of the machine being described.

The four hardware classes
ClassInstruction streamsData streamsMeaning
SISDSingleSingleOne processor follows one ordinary instruction stream.
SIMDSingleMultipleOne instruction applies an operation to several data elements.
MISDMultipleSingleDifferent instruction streams operate on one data stream.
MIMDMultipleMultipleProcessors independently fetch instructions and work on data.

A conventional single-core processor is SISD even when its pipeline overlaps several instructions. Superscalar issue does not by itself create independent program counters or turn the core into MIMD hardware.

A SIMD instruction might add eight pairs of 32-bit floats in a 256-bit register. It has eight lanes of arithmetic, but they follow one instruction. Fixed-width SIMD extensions include x86 SSE and AVX and Arm Neon; vector architectures also fit the SIMD class. Regular array calculations fit well because many elements need the same operation.

MIMD processors choose their instructions independently. Multicore chips, shared-memory multiprocessors, and clusters fit this class. The cores can run different programs, or copies of the same program that reach different branches at different times.

MISD completes the two-by-two classification. It has few clear practical examples. Some fault-tolerant systems and processing pipelines are described this way, but their classification depends on how their streams are defined.

One program can still have many instruction streams

SPMD, single program, multiple data, is a programming style. Each worker runs a copy of the same program and uses its ID to select its share of the data. Workers have independent execution state, so SPMD commonly runs on MIMD hardware.

For four cores summing 4,000 values, core ID i handles indexes 1000i through 1000i+999. Core 0 handles 0–999; core 3 handles 3000–3999. Each produces a partial sum, and those four sums are combined. The shared program text does not require all four cores to issue the same instruction in the same cycle.

Classify each level separately

Consider an eight-core CPU whose threads use AVX instructions. Across cores it is MIMD: the cores advance independently. Inside an AVX operation it is SIMD: one instruction controls several lanes. Counting all the arithmetic units together would hide this structure.

A cluster running copies of one scientific program is likewise MIMD hardware using SPMD software. Its nodes communicate through messages. A GPU combines many independently scheduled thread groups with SIMD-like execution inside each group; NVIDIA calls its thread-based execution style SIMT.

To classify a description, ask who chooses the next instruction. Then ask whether that instruction processes one data element or several. The number of source files, programs installed, or arithmetic units alone cannot answer those two questions.

Key Takeaways

  • Flynn’s taxonomy counts instruction streams and data streams.
  • Pipelining within one instruction stream remains SISD.
  • SIMD shares instruction control across lanes; MIMD has independent instruction streams.
  • SPMD is a programming style that commonly runs on MIMD hardware.
  • One machine can be MIMD across cores and SIMD inside each core.

1.3 Fill idle cycles with another thread

A cache miss can leave a core waiting hundreds of cycles. Hardware multithreading keeps several threads' execution states inside one core so useful instructions from another thread can run during that wait.

What is duplicated and what is shared

Each hardware thread has its own program counter and register state. The threads share the core's execution units, caches, and access to memory bandwidth. Keeping state in hardware makes switching much faster than saving and restoring an operating-system process, which can cost thousands of cycles. Hardware can switch in a cycle or less.

The operating system sees each hardware thread as a logical processor. Eight physical cores with two hardware threads per core expose 16 logical processors. That count describes available thread contexts, not 16 complete physical cores.

Three scheduling approaches
ApproachWhen does the core choose another thread?Main tradeoff
Fine-grainedEvery cycle, skipping stalled threadsHides short and long stalls, but each thread waits between turns.
Coarse-grainedOn a long stall, such as a last-level cache missGives one thread long runs, but switching and pipeline refill cost time.
Simultaneous multithreading (SMT)Several threads may issue in the same cycleFills unused issue slots while sharing the core's resources.

Fine-grained scheduling can rotate among ready threads even when the previous thread could continue. Coarse-grained scheduling keeps running that thread until a costly stall justifies switching. SMT uses a multiple-issue, dynamically scheduled core: instructions from different threads can occupy different free issue slots during one cycle. Register renaming keeps their state separate. Intel's Hyper-Threading is an SMT implementation; some IBM POWER processors support eight hardware threads per core.

Work through latency hiding

Suppose a thread computes for 20 cycles and then waits 200 cycles for memory. Its cycle is 220 cycles long. Alone, useful work occupies 20/220≈0.091, or 9.1% of the time.

With four threads, freely staggered work, and no switching cost or added contention, useful work can occupy 4×20/220≈0.364, or 36.4%. The core still has gaps because four 20-cycle bursts cannot cover the waiting periods.

Eleven threads provide 220 cycles of compute bursts in total. While one waits for 200 cycles, the other ten can each compute for 20. This ideal schedule keeps the core busy. Real performance also depends on whether those threads compete for memory and execution resources.

Throughput and a thread's completion time

Multithreading primarily increases throughput. A particular thread may take longer because other threads use cycles and cache space it would otherwise receive. Two hardware threads sharing one arithmetic unit cannot both gain the capacity of a second full core.

If both threads already demand the same fully occupied execution units, SMT has little spare capacity to fill. If one stalls while the other can execute, sharing is useful. GPUs apply latency hiding at a larger scale by keeping many thread groups ready for their schedulers.

Key Takeaways

  • Hardware threads duplicate execution state while sharing a core’s resources.
  • Fine-grained switching occurs each cycle; coarse-grained switching responds to long stalls.
  • SMT can issue instructions from different threads during one cycle.
  • Logical processor counts include hardware thread contexts.
  • Latency hiding needs ready work and can be limited by contention.
  • Higher throughput need not shorten an individual thread’s run.
2

Estimate useful parallel speedup

Extra processors divide only the work that can run in parallel, and they introduce costs of their own. Start with elapsed time and the sequential fraction, then distinguish finishing a fixed job sooner from solving a larger job in the same time. Load balance and coordination explain further losses. The roofline model adds a different limit: whether memory can feed the available arithmetic units quickly enough.

2.1 Calculate the gain and its ceiling

A parallel machine is useful when it changes elapsed time. Speedup compares the best sequential run with the parallel run; efficiency compares that gain with the number of processors used.

Start with measured time

For p processors, S(p)=T1/Tp and E(p)=S(p)/p. A 100 s sequential job that finishes in 16 s on eight cores has speedup 100/16=6.25. Its efficiency is 6.25/8=0.78125, about 78%. Measure wall-clock time for both runs, using the same fixed job.

Divide time into improved and unchanged parts

In Amdahl's law, f is the fraction of the original execution time that an enhancement accelerates. It is a time fraction, not a fraction of source-code lines. If that part becomes s times faster, then

Tnew=Told((1−f)+f/s),S=1(1−f)+f/s.

The unchanged part still takes its full original time. For ideal parallel division across p processors, set s=p. This model excludes communication, imbalance, and synchronization overhead; those costs can make measured time longer.

With 90% parallel time and ten processors, normalized time is 0.1+0.9/10=0.19. Speedup is 1/0.19≈5.26, and efficiency is about 53%. With 100 processors, time is 0.1+0.009=0.109 and speedup is about 9.17. Increasing the processor count tenfold has not doubled the speedup.

Find the limit before buying more processors

As processor count grows, the parallel time approaches zero. The sequential fraction remains, giving the ceiling Smax=1/(1−f). A 10% sequential fraction caps ideal speedup at 10; a 5% fraction caps it at 20. Finite processor counts approach these ceilings from below.

Amdahl's law also evaluates one faster instruction class. If multiplication takes 30% of a run and becomes four times faster, normalized time becomes 0.7+0.3/4=0.775. The whole program is only 1/0.775≈1.29 times faster.

Work backward from a target

To obtain speedup 90 on 100 processors, write 1/90=(1−f)+f/100=1−0.99f. Therefore f=(1−1/90)/0.99≈0.99888. Only about 0.11% of the original time can remain sequential. A target close to the processor count demands a very small unchanged fraction.

A measured speedup can sometimes exceed the processor count. Splitting a large working set may make each part fit in cache, reducing the cost per operation. This superlinear speedup changes a premise of the simple model: parallel work is no longer just the original work divided into equal shares. Check the algorithm, data size, and cache behavior before interpreting such a measurement.

Key Takeaways

  • Speedup is sequential time divided by parallel time; efficiency is speedup divided by processor count.
  • Amdahl’s fraction refers to original execution time.
  • Only the improved fraction is divided by the enhancement factor.
  • The sequential fraction sets the fixed-workload speedup ceiling.
  • Cache effects can change the work’s cost and produce superlinear measured speedup.

2.2 Scale the problem and include the costs

Adding processors can either shorten the same job or let a machine handle a larger job. Strong scaling and weak scaling measure these different uses, and both depend on how much useful work survives the costs of coordination.

Fixed work and growing work

Strong scaling keeps the problem size fixed. Weak scaling grows work in proportion to processor count, keeping work per processor constant. Perfect weak scaling keeps elapsed time constant while total work grows.

Consider ten sequential additions followed by an element-wise sum of two matrices. A 10 by 10 matrix needs 100 parallel additions. Total time is 110 units on one processor, 20 on ten, and 12 on fifty: speedups 5.5 and about 9.2. A 40 by 40 matrix needs 1,600 parallel additions. Times become 1610, 170, and 42 units: speedups about 9.5 and 38.3. The larger problem gives useful parallel work more weight relative to the same ten sequential additions.

Gustafson's different baseline

Gustafson's law uses the sequential time fraction measured on the parallel run. Calling that fraction s, scaled speedup is SG=s+(1−s)p. For s=0.05 and 100 processors, SG=0.05+0.95(100)=95.05.

Amdahl's law with 5% sequential time on the original one-processor run gives only about 16.8 on 100 processors. These fractions use different denominators and answer different questions. A scaled speedup of 95.05 does not mean the original fixed-size job finished 95.05 times sooner.

The slowest worker sets the finish time

If 400 equal work units go to eight cores, the balanced share is 50 each. Suppose one gets 120 while the other seven get 40 each. The step lasts 120 time units, so speedup is 400/120≈3.33. Dividing by the average load would miss the wait for the busiest core.

Thread creation, scheduling, messages, barriers, and shared-bandwidth contention also consume time. Granularity is the amount of computation between communication or synchronization events. Larger chunks reduce coordination cost per useful operation, but too few chunks can leave some workers idle.

More processors can increase time

For a fully parallel 100 s job with overhead 0.5p seconds, Tp=100/p+0.5p. Ten processors take 15 s. Fourteen take about 14.14 s, close to the minimum near 200 processors. Forty take 22.5 s because their 20 s overhead outweighs the shorter useful calculation.

When reporting a result, state whether work stayed fixed or grew, and compare with the best sequential program's time. Using a slow parallel implementation running on one processor as the baseline can inflate the reported speedup.

Key Takeaways

  • Strong scaling fixes total work; weak scaling fixes work per processor.
  • Gustafson’s sequential fraction is measured on the parallel run.
  • The slowest worker determines a parallel step’s finish time.
  • Communication, synchronization, and contention can grow with processor count.
  • Granularity trades coordination cost against load balance.
  • Use elapsed time and a best-sequential baseline when reporting speedup.

2.3 Find the compute or memory roof

A processor's advertised arithmetic rate is only one limit. The roofline model also asks whether memory can supply data fast enough to sustain that rate. It gives an upper bound, which helps identify a useful direction for optimization.

Count operations per DRAM byte

Arithmetic intensity is floating-point operations divided by bytes transferred between DRAM and the processor. The original roofline work calls this DRAM-based measure operational intensity. Count the traffic at that boundary, including reads and writes.

DAXPY computes yi=axi+yi using double-precision numbers. Each element needs one multiplication and one addition: two FLOPs. Reading an 8-byte value from each array and writing 8 bytes back moves 24 bytes. Intensity is I=2/24≈0.0833 FLOPs per byte. The scalar coefficient is reused; it is not a fresh DRAM load for every element in this traffic model.

Apply both limits

If peak compute is P and peak memory bandwidth is B, the roof is min⁡(P,BI). Bandwidth times FLOPs per byte has units of FLOPs per second. On a log-log graph, the bandwidth bound slopes upward and the compute bound is flat.

For 1,000 GFLOP/s and 100 GB/s, the ridge point is P/B=1000/100=10 FLOPs per byte. Below this intensity, the bandwidth roof is lower; above it, the compute roof is lower. DAXPY is bounded by 100(2/24)≈8.33 GFLOP/s, under 1% of the machine's compute peak. A kernel at intensity 2 is bounded by 200 GFLOP/s.

A memory-bound kernel can still benefit from extra cores or wider SIMD while it has too few requests in flight to use the available bandwidth. Once that bandwidth is saturated, extra arithmetic capacity does not raise its roof. Raising bandwidth or doing more useful computation per transferred byte does.

Reuse changes intensity

Multiplying two 1000 by 1000 double-precision matrices performs about 2(1000)3=2×109 FLOPs. If each element of the two inputs and output crosses the DRAM boundary once, total traffic is 24 MB, giving about 83 FLOPs per byte. That is above the ridge of the example machine.

A naive implementation can reread matrix values repeatedly from DRAM. Blocking organizes loops around submatrices that fit in cache, so values serve many operations before being replaced. The algorithm is still matrix multiplication, but the implementation moves fewer DRAM bytes per operation.

A roof is not a measured result

A kernel can run below the bound because of dependencies, instruction overhead, poor access patterns, or insufficient parallel work. Lower ceilings show such restrictions: lack of SIMD can lower the compute ceiling, while poor access patterns lower usable bandwidth. A point below a roof needs investigation; the roof alone does not predict its exact running rate.

Key Takeaways

  • Intensity counts FLOPs per byte at the DRAM boundary.
  • The roof is the smaller of peak compute and bandwidth times intensity.
  • The ridge point is peak compute divided by peak bandwidth.
  • Reuse can increase intensity without changing the mathematical algorithm.
  • A roofline gives an upper bound; lower ceilings explain additional restrictions.
3

Process arrays with lanes and GPU threads

Arrays offer repeated operations on independent elements, which can be shared across lanes and threads. Follow that idea from fixed-width SIMD registers to variable-length vector loops and then to GPU warps. Each design needs an effective data layout and enough work to fill its hardware. A small kernel shows how array indexes become thread indexes, while transfer costs determine whether offloading helps the complete job.

3.1 Run array operations across SIMD lanes

A SIMD extension divides a wide register into lanes. One instruction performs the same operation in every lane, making regular loops over independent elements a good fit.

Count lanes and iterations

Lanes equal register width divided by element width. A 256-bit register holds eight 32-bit floats, four 64-bit doubles, or 32 one-byte elements. SSE uses 128-bit XMM registers; AVX and AVX2 use 256-bit YMM registers. In 64-bit mode there are 16 YMM registers. AVX-512 provides 32 512-bit ZMM registers, each holding 16 floats. Arm Neon uses 128-bit registers.

For c[i] = a[i] + b[i] over 1,000 floats, eight-lane instructions process the array in 125 vector iterations. Each iteration loads two vectors, adds their lanes, and stores a vector. With 1,003 elements, 125 full iterations leave three elements. A scalar remainder loop or a masked operation handles that short tail without accessing beyond the arrays.

Eight lanes are an arithmetic capacity, not a guarantee of eightfold program speedup. Setup, remainder handling, sequential work, and memory bandwidth still take time.

Choose a layout that fills a register

Simple vector loads work well on contiguous, unit-stride elements. An array of 4-byte {x, y, z} points places consecutive x fields 12 bytes apart. A structure of arrays puts the x values together, then the y values, then the z values. Processing only x can now fill a vector with one contiguous load. Gather and scatter instructions support scattered addresses, but usually at a higher access cost.

Keep conditional work within lanes

For c[i] = (a[i] > 0) ? a[i] : 0, a compare creates a per-lane mask. A blend chooses between candidate results, or masked instructions update only the selected lanes. Inactive lanes retain or receive values according to the instruction's mask behavior.

If different lanes need long, different branches, the instructions for those paths must still be issued, with only the relevant lanes active. The group cannot give each lane a separate instruction stream. A mask preserves correctness but cannot make all those path instructions disappear.

Check iteration independence

Compilers can auto-vectorize loops; programmers can also use libraries or intrinsics such as _mm256_add_ps. The compiler must establish that simultaneous iterations preserve the result. The recurrence a[i] = a[i-1] + b[i] depends on the preceding iteration's new value and cannot be directly vectorized as independent elements. Possible pointer overlap, called aliasing, can also require a run-time overlap check or prevent vectorization.

A reduction keeps several partial sums in a register, then combines lanes. Reordering floating-point additions can change the last bits because addition is not associative. Integer sums agree when the chosen arithmetic has no overflow or uses defined modular arithmetic.

SIMD and multicore execution can combine. Eight cores each issuing one eight-lane add per cycle can perform up to 64 float additions per cycle. They still share limits such as memory bandwidth.

Key Takeaways

  • SIMD lane count depends on both register width and element width.
  • Remainders need a scalar tail or correctly masked access.
  • Contiguous layouts help vector loads use their lanes efficiently.
  • Masks handle per-element conditions while sharing instruction issue.
  • Dependencies and aliasing can block direct vectorization.
  • Floating-point reductions can change rounding when operations are regrouped.

3.2 Let vector length control each loop pass

A vector architecture expresses an operation on a sequence of elements and stores the active vector length in a register. The same program can run on implementations with different vector-register capacities.

Separate capacity, length, and lanes

The RISC-V vector extension, RVV, version 1.0 was ratified in 2021. It provides 32 vector registers, v0 through v31. Each implementation chooses its register width, VLEN, as a power of two. Element width and register grouping determine how many elements fit.

The active length, vl, is the number of elements handled by the next vector instructions. vsetvli configures the vector operation from the remaining element count and the desired element format, returning the selected vl. Code advances by that returned value. This matters because portable code must use the actual length selected by the implementation.

Lanes are the parallel pipelines that execute the vector operation. A 32-element add on four lanes takes about eight cycles after pipeline startup. A 32-element vector does not require 32 arithmetic units. Longer vectors and more lanes are separate design choices.

Strip mine a loop

Strip mining divides a long loop into vector-sized pieces. For 100 elements and a maximum of 32 per operation, one valid sequence of lengths is 32, 32, 32, and 4. Each pass loads the next portion, computes it, stores it, and reduces the remaining count by its vl.

DAXPY over 1,000 doubles can similarly use 31 passes of 32 followed by a pass of eight, for 32 passes in all. RVV can choose other legal lengths near the end, so the loop uses the returned vl instead of assuming a particular final split. Setting the active length handles the short tail without a separate scalar remainder loop.

The loop-control pattern is:

  1. Request a length for the remaining elements.
  2. Load and compute that many elements.
  3. Store the results.
  4. Advance pointers and subtract the returned length.

One vector instruction describes many element operations, reducing fetch and decode work compared with a scalar body repeated for every element.

Feed dependent operations and noncontiguous data

Chaining lets a vector consumer start on early results before the producer has finished later elements. For a multiply followed by an add, the first product can enter the add pipeline while later products are still being formed.

A mask, commonly in RVV register v0, selects which elements update. A strided load accesses a fixed byte spacing. In a row-major 100 by 100 matrix of doubles, moving down one column advances 100 elements, or 800 bytes. Indexed loads and stores use explicit addresses for irregular data.

Both vector architectures and fixed-width extensions are SIMD in Flynn's taxonomy. Fixed-width extensions encode particular widths; RVV code expresses lengths that adapt to the available hardware. Both still need an execution order that respects the loop's data dependencies.

Key Takeaways

  • Vector length says how many elements an operation handles; lanes say how many can advance together.
  • RVV code advances by the actual length returned by vsetvli.
  • Strip mining processes a long array in vector-sized pieces.
  • Chaining overlaps dependent vector operations element by element.
  • Masks, strides, and indexed accesses support less regular data.

3.3 Keep a GPU busy with many warps

A CPU concentrates resources on low latency for a few threads. A GPU concentrates resources on high throughput across many data-parallel threads. Choosing between them requires looking at the whole job, including data movement.

Threads run on streaming multiprocessors

A GPU from NVIDIA contains many streaming multiprocessors, or SMs. An SM has arithmetic lanes, warp schedulers, a large register file, and fast on-chip shared memory. A “CUDA core” names an arithmetic lane, not a complete independent CPU-like core. AMD calls the corresponding processing group a compute unit.

NVIDIA groups threads into warps of 32. One issued instruction operates on the warp's active threads, each with its own register values and data. This is SIMT, single instruction, multiple threads. AMD uses wavefronts, with 32 or 64 threads depending on the architecture.

An SM keeps many warps resident. When one waits for memory, the scheduler selects another ready warp. Having more ready threads than lanes hides latency; it does not reduce the latency of an individual DRAM access.

Divergence leaves lanes inactive

If threads in one warp take different branches, the warp executes the required paths with the other threads masked off. An evenly split if-else with equally costly branches can take roughly twice the path time because both paths must execute. A branch can be harmless when its condition is uniform within each warp, even if different warps choose different paths.

Make memory accesses work together

Per-thread registers hold private values. Per-block shared memory is on-chip storage managed by the program. L1 and L2 caches serve automatic reuse, while global memory is the GPU's DRAM, such as GDDR or HBM.

When 32 threads read consecutive 4-byte words, their 128-byte range can be served by a small number of wide transactions. This coalescing uses bandwidth efficiently. Scattered addresses can require many transactions for the same useful data. Shared-memory reuse can further reduce repeated global-memory traffic.

Include the transfer time

For a discrete GPU, inputs and results cross a link such as PCIe or NVLink. Sending 800 MB and receiving 400 MB at an effective 20 GB/s transfers 1.2 GB in 0.06 s, or 60 ms. Adding a 10 ms kernel gives 70 ms overall. A CPU finishing in 50 ms wins this comparison despite the much faster GPU calculation.

Keeping data on the GPU across several kernels avoids repeated transfers. Large, regular jobs can also provide enough useful arithmetic to outweigh movement and launch costs. Small, sequential, branch-heavy jobs often favor a CPU.

Specialize further when the work allows it

A heterogeneous system uses the CPU to run the program and operating system and an accelerator for suitable parts. Domain-specific accelerators such as TPUs and NPUs devote hardware to a narrower task, often matrix multiplication with 8-bit integers or 16-bit floating point. Specialization can improve performance per watt in that domain, while reducing the range of work the hardware handles well.

Key Takeaways

  • An SM schedules warps; a CUDA core is an arithmetic lane.
  • NVIDIA warps contain 32 threads with separate data and shared instruction issue.
  • Resident ready warps hide memory waits.
  • Divergence and scattered accesses waste lane time and memory bandwidth.
  • Offload decisions include transfers as well as kernel time.
  • Specialized accelerators trade flexibility for efficiency in a narrower domain.

3.4 Map array elements to GPU threads

A GPU kernel runs once per launched thread. The host launches a grid of thread blocks, and each thread computes which part of the data it owns. CUDA calls the CPU the host and the GPU the device; OpenCL uses the related terms work-item and work-group.

Calculate a unique index

For a one-dimensional launch, the element index is blockIdx.x * blockDim.x + threadIdx.x. With 256 threads per block, thread 5 in block 2 handles element 517: the two preceding blocks account for 512 elements, and the thread adds an offset of five. Thread and block indexes start at zero.

A SAXPY kernel applies one multiply and one add to each float:

__global__ void saxpy(int n, float a, float *x, float *y) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) {
        y[i] = a * x[i] + y[i];
    }
}

The grid replaces the ordinary loop over elements. Each active thread updates its own y[i]; neighboring threads use neighboring addresses, supporting coalescing.

Round the block count up

For 1,000,000 elements and 256 threads per block, the grid needs ⌈1000000/256⌉=3907 blocks. These launch 1,000,192 threads. The last 192 have indexes outside the array, so the condition i < n prevents their memory accesses. Rounding down would launch too few threads and leave valid elements untouched.

A block of 256 threads forms eight warps. Blocks can be assigned to any SM and execute in any order. Program correctness must not depend on block 0 finishing before block 1.

Organize host and device work

A typical host allocates device storage, copies the inputs, launches saxpy<<<3907, 256>>>(n, 2.0f, d_x, d_y), and obtains the results. Launch is asynchronous: the CPU can continue while the kernel runs. The host must wait through synchronization or a suitable blocking result copy before it uses the finished data.

Cooperate inside a block

Threads in one block can exchange values through shared memory and meet at __syncthreads(). Every thread participating in that block-wide barrier must reach it. Putting the barrier inside if (i < n) is unsafe when only some threads satisfy the condition.

For a reduction of 1,024 shared-memory values, 512 threads add pairs, then 256 combine the results, then 128, and so on. Ten halving stages leave one sum. A barrier between stages prevents a thread from consuming a partial result before its producer writes it.

An ordinary launch has no grid-wide barrier. Separate blocks can write partial sums and a second kernel can combine them, or appropriate atomic operations can update a global result. A block barrier alone cannot coordinate different blocks. A grid-stride loop is another mapping pattern: each thread handles several elements, advancing by the total grid size.

Key Takeaways

  • Compute indexes from block size, block index, and thread index.
  • Round block counts up and guard out-of-range accesses.
  • Kernel launches are asynchronous with respect to the host.
  • Shared memory and __syncthreads() support cooperation within a block.
  • Ordinary blocks run independently; combining block results needs another mechanism.
4

Share memory and trace cache ownership

A common address space lets threads exchange values through ordinary memory operations. Private caches make those operations fast but create multiple copies that need coordination. Follow a reduction from local work to shared results, then trace the permissions that keep cached copies coherent. Directory storage and false sharing connect those correctness mechanisms to the performance cost of placing data in memory.

4.1 Share an address space and combine partial results

A shared-memory multiprocessor gives its processors one physical address space. Threads communicate with loads and stores to shared variables, while still keeping private values such as local partial sums.

Shared addresses can have different costs

In UMA, uniform memory access, memory access time is roughly the same from every processor. In NUMA, nonuniform memory access, a socket reaches its local memory faster than another socket's memory. The address space is shared even though the physical memory is distributed.

With 70% local accesses at 80 ns and 30% remote accesses at 140 ns, the weighted average is 0.7(80)+0.3(140)=98 ns. Moving data near its main user reduces the remote share. Counting every access as local would underestimate time.

A common cache layout gives each core private L1 instruction and data caches, often private L2, and a shared last-level cache. A ring or mesh connects the cores and caches. Shared memory describes addressing; it does not require every core to use one common cache.

Split, compute, and reduce

To sum 64,000 values on 64 cores, each core handles 1,000 values. The 64 partial sums can be combined in a reduction tree. The number of active adders halves at each stage: 32, 16, 8, 4, 2, and 1. Six stages combine the partial results.

Using roughly 1,000 local addition steps plus six combining steps gives about 1,006 steps along the longest path, before overhead. The tree avoids making every input update one shared counter. Each stage depends on the previous stage's completed values, so the workers meet at barriers between stages.

OpenMP can express this with #pragma omp parallel for reduction(+:sum). It splits iterations, gives threads private partial sums, and combines them. POSIX threads offer more explicit control over thread management.

Make an update indivisible

An atomic read-modify-write operation makes an update indivisible as observed by other processors. Atomic swap and fetch-and-add are examples. A load followed by an ordinary store is two separate operations, so another thread can intervene.

RISC-V provides lr.w and sc.w. The load-reserved reads a word and establishes a reservation. The store-conditional attempts the write and reports success or failure. An intervening write to the reserved location makes the attempt fail; software retries. The reservation does not block other processors, and failure can also occur for other permitted reasons. These primitives support synchronization mechanisms.

Watch the shared bottlenecks

If each core can stream 15 GB/s but the socket supplies 60 GB/s, about four such streams saturate bandwidth. More cores cannot increase the socket's data rate. Communication through caches also takes work: a writer without write permission must obtain ownership and invalidate other copies. A writer already holding a Modified block can continue locally; later readers may need to fetch a new copy.

Key Takeaways

  • Shared memory means one address space, with private data and caches still possible.
  • NUMA makes data placement part of performance.
  • Local partial sums and a reduction tree limit contention.
  • Barriers separate dependent phases of work.
  • Atomic operations protect indivisible updates; LR/SC retries after failed attempts.
  • Cores share memory bandwidth and pay for ownership transfers.

4.2 Keep copies of one location coherent

Private caches improve latency but can hold several copies of the same memory location. Cache coherence keeps those copies from giving conflicting histories of that location's writes.

Why updating memory is insufficient

Start with X = 0 in memory. Core A reads and caches zero; core B does the same. A writes one into its write-back cache. Without a coherence protocol, B can hit in its own cache and keep reading zero. Writing through to memory would not fix B's already cached copy.

Coherence works at cache-block granularity, commonly 64 bytes. A controller tracks each block's state and follows protocol rules when processors read or write it. Migration moves useful data into the cache of its current user. Replication lets several readers hold clean copies. Coherence must preserve both benefits while controlling writes.

Three required properties
PropertyWhat it requires
Program order for one locationA processor reads its own preceding write if no intervening write replaces it.
Write propagationA write eventually becomes visible to the other processors.
Write serializationAll processors agree on the order of writes to that location.

If a location receives a write of one followed by a write of two, readers cannot disagree about which write came later. Observing the later write and then the earlier write would reverse that history. A fresh subsequent write could of course store the value one again; serialization concerns write events, not whether a numeric value can ever recur.

Control ownership and copies

In a write-invalidate protocol, a writer obtains exclusive write permission and invalidates other cached copies. A later read of an invalidated block misses and fetches current data. This is a coherence miss, in addition to compulsory, capacity, and conflict misses.

A write-update protocol sends new values to existing copies instead. Repeated writes can make this expensive. Snooping broadcasts coherence requests so caches can react. A directory tracks sharers and directs messages to relevant caches.

Coherence, ordering, and atomicity

Coherence concerns one location. A memory consistency model defines allowed observable orderings and results of reads and writes, including operations on different locations. Sequential consistency requires an outcome that matches one interleaving preserving each processor's program order. Relaxed models allow more reorderings; fence instructions enforce required ordering where needed.

Neither coherent copies nor a consistent ordering makes a multi-instruction increment atomic. Suppose two threads increment a shared count initially equal to five. A possible sequence is: A reads five, B reads five, A writes six, B writes six. Every read and write can be coherent, yet the final count is six instead of seven. The program needs an atomic update or suitable synchronization to preserve both increments.

Key Takeaways

  • Coherence is needed even when caches write through to memory.
  • Coherent systems preserve own-location program order, propagate writes, and serialize writes.
  • Write invalidation removes other usable copies before a new owner writes.
  • Invalidated data can cause coherence misses.
  • Consistency models address ordering across locations.
  • A coherent read and a coherent write still form two separate operations.

4.3 Follow MSI and MESI ownership changes

A snooping cache controller watches coherence requests on a broadcast interconnect. To trace a protocol, keep a state for each core's copy of a block and update every affected copy after each access.

Read the states as permissions
StateUsable copy?Who else may hold it?Is memory current?
Modified (M)Yes, reads and writesNo other valid copyNo
Shared (S)Yes, readsOther readers may hold copiesYes
Invalid (I)NoOther caches may hold copiesDepends on their state
Exclusive (E), MESI onlyYes, reads and silent transition to writingNo other valid copyYes

In basic MSI, a read miss sends a bus read and loads the block in S. Writing a block in S requires an upgrade to invalidate other copies. Writing from I needs a read-exclusive request to fetch data and obtain ownership. The writer ends in M. A hit in M requires no coherence transaction.

Trace five accesses

Begin with X = 0 in memory and both A and B Invalid.

  1. A reads X. A bus read supplies zero. States: A = S, B = I.
  2. B reads X. Another bus read supplies zero. States: A = S, B = S.
  3. A writes one. Its upgrade invalidates B. States: A = M, B = I.
  4. B reads X. B misses; A supplies one and downgrades to S. In basic MSI, memory becomes current too. States: A = S, B = S.
  5. B writes two. Its upgrade invalidates A. States: A = I, B = M.

Each access in this trace requires a bus transaction. The fourth access is the important ownership check: memory alone still had the old value before A supplied its dirty data.

What Exclusive saves

MESI adds E for a single clean cached copy. If A reads an uncached block and no other cache has it, A receives E. A subsequent write changes E to M silently, because there are no other copies to invalidate. MSI would first load S and then send an upgrade for that write.

If another core reads while A holds E, both become S. M and E both have one valid owner, but only M contains data newer than memory.

Repeated writes and scale

A writer that has obtained M can update the block ten times without ten new invalidations. A write-update scheme would send the changed values to sharers.

Broadcast snooping becomes expensive as more cores watch every request. Directory structures reduce that fan-out. More elaborate protocols add useful states: MOESI's Owned state permits a dirty shared copy, and MESIF designates a Forward sharer to answer requests.

Key Takeaways

  • MSI tracks Modified, Shared, and Invalid copies.
  • A writer needs exclusive ownership; Modified hits stay local.
  • A remote read makes a Modified owner supply current data and downgrade in basic MSI.
  • MESI’s Exclusive state lets a lone clean reader write without an upgrade transaction.
  • Exclusive and Modified both have one owner, but only Modified is dirty.

4.4 Track sharers and separate independent data

Broadcasting every coherence request becomes costly on large machines. A directory records which caches might hold each block so requests can go to those caches. The same block-level tracking also explains a common performance problem: false sharing.

Ask a block's home

Each block has a home directory entry recording whether it is uncached, shared, or modified and which caches hold it. Homes are distributed across nodes or directory slices, spreading storage and request handling.

A read miss goes to the home. If memory has the current data, it can supply them and the directory records the new sharer. If another cache owns a Modified copy, the home forwards the request to that owner so current data can be supplied. In a basic directory protocol, this also makes memory current again.

To write without existing Modified ownership, a core asks the home for permission. The directory sends invalidations to recorded sharers, waits for acknowledgments, and grants exclusive ownership. Repeated write hits in M then need no further coherence messages. Directory indirection adds latency, but point-to-point traffic avoids asking every cache about every block. On-chip snoop filters serve a related purpose by restricting requests to possible holders.

Estimate directory storage

A full presence vector has one bit per core per block. For 64 cores, that is 64 bits, or eight bytes. Relative to a 64-byte data block, presence bits alone cost 8/64=0.125, or 12.5%. With 256 cores, the 32-byte vector costs 50%. State bits add more. Limited sharer lists, coarser vectors, and tracking only cached blocks reduce this storage burden.

Recognize false sharing

True sharing occurs when cores exchange data through the same word. False sharing occurs when they access different variables within one cache block and at least one writes. The variables are independent in the program, but the coherence unit is larger than either variable.

Two threads increment separate 8-byte counters at 0x1000 and 0x1008. With 64-byte blocks, their block numbers are ⌊4096/64⌋=64 and ⌊4104/64⌋=64. Each ownership change moves permission for both counters together. Frequent alternating writes can make the block bounce between caches even though neither thread needs the other's value.

Moving the second counter to 0x1040 puts it in block 65. Padding or alignment can separate per-thread data; grouping values by their writer also helps. A local accumulator written back once reduces ownership traffic without adding padding to every value.

A writer and a reader of a neighboring variable can also suffer false sharing: the writer invalidates the reader's otherwise useful block. Two readers alone do not cause it. False sharing adds traffic and delay; it does not itself make updates to separate variables produce incorrect values. Measure access patterns and cache-line placement before changing a data layout.

Key Takeaways

  • Directories send coherence messages to recorded holders through a block’s home.
  • Presence-vector storage grows with both core count and block count.
  • False sharing involves different variables in one block and at least one writer.
  • Separate ownership by padding, placement, or fewer shared writes.
5

Connect nodes and operate at warehouse scale

Beyond one shared-memory machine, nodes exchange messages through a network. A cluster must place data and organize communication as carefully as it divides arithmetic. At warehouse scale, the same network sits beside power, cooling, and routine hardware failures. Compare network capacity with a critical cut, then use energy and latency calculations to judge how a large fleet delivers a reliable service.

5.1 Compare private-memory nodes and their networks

A cluster connects complete computers, each with its own memory and operating system. Nodes cooperate through explicit messages. Data placement and communication cost therefore become part of the program's performance model.

Partition data and combine results

MPI, the Message Passing Interface, gives each process a rank and operations such as send, receive, broadcast, and reduce. An SPMD program can use ranks to select each process's data. A pointer in one node's private address space is not an ordinary shared-memory reference to another node's data.

If one million values are already distributed over 100 nodes, each node sums 10,000 locally. A tree reduction combines the partial sums in seven rounds because ⌈log⁡2100⌉=7. Those rounds involve network messages, not just local additions. Keeping data close to its work reduces transfers.

Clusters scale with standard components, and failed hardware can be replaced. An application may still need recovery or restart after a node fails; replaceable nodes alone do not preserve an interrupted job's progress.

Measure more than link speed

Latency is the time a message takes to arrive. Link bandwidth is one link's data rate. Total network bandwidth sums link capacity and describes an ideal aggregate with all links busy. Bisection bandwidth sums the capacity crossing the lowest-capacity cut that divides nodes into equal halves.

For equal-capacity links of bandwidth B, compare 64-node networks using one consistent link-counting convention:

TopologyLinksTotal capacityBisection capacity
Ring6464B2B
8 by 8 mesh112112B8B
8 by 8 torus128128B16B
6-dimensional hypercube192192B32B
Fully connected20162016B1024B

The mesh has eight rows of seven horizontal links and eight columns of seven vertical links, giving 112. Wrapping both dimensions produces the torus's 128. Each hypercube node has six neighbors, giving 64(6)/2=192 links because each link is counted at two endpoints.

Follow the cut, then consider the cost

A ring cut into two halves crosses only two links. Many messages can therefore contend at that boundary despite the ring's 64 links overall. A fully connected network crosses 32(32)=1024 links between its two halves, but needs 64(63)/2=2016 links in total.

More links can improve bandwidth and reduce hops while increasing switch ports, cables, and power. Shared buses have a single shared communication resource; meshes and tori spread links across space. Large clusters often use multistage switched networks such as fat trees. Their usefulness depends on the traffic pattern as well as their aggregate capacity. For communication between halves of a machine, the bisection exposes a limit that the total hides.

Key Takeaways

  • Cluster nodes use private address spaces and explicit communication.
  • MPI ranks identify processes; collective operations combine distributed work.
  • Message rounds add cost beyond local arithmetic.
  • Total bandwidth measures aggregate link capacity; bisection measures a critical cross-machine cut.
  • Network capacity trades against ports, cables, power, and hops.

5.2 Measure a data center as one computer

A warehouse-scale computer combines tens of thousands of servers with power, cooling, and a network to deliver internet services. Independent requests provide parallel work, while batch frameworks such as MapReduce split large data-processing jobs across machines.

Match the design to the service

Warehouse-scale systems emphasize cost per request, energy efficiency, and availability. Software retries work, replicates data, and routes around failed machines. A supercomputer more often emphasizes one tightly coupled scientific program and a fast interconnect.

Servers connect to top-of-rack switches, which connect through higher switch levels. Extra levels add communication latency. Uplinks are often oversubscribed, meaning their capacity is below the aggregate capacity of the server links. Some nonblocking Clos-style fabrics provide enough upper capacity to avoid this restriction.

Forty servers with 10 Gbit/s links offer 400 Gbit/s to a rack switch. Four 25 Gbit/s uplinks provide 100 Gbit/s, so the ratio is 4:1. If all servers send off-rack together and share equally, each averages 2.5 Gbit/s. A lightly loaded server can use more when others are idle.

Separate facility overhead from useful computation

Power usage effectiveness, PUE, is total facility energy divided by IT equipment energy over the same period. Ten MW of steady IT load plus 1.5 MW of cooling and distribution overhead gives PUE=11.5/10=1.15. The ideal value is 1.0. Google reported an annual fleet-wide PUE of 1.09 for 2025.

PUE measures facility overhead, not useful computations per joule. Idle or inefficient servers can waste energy inside the IT boundary even when the facility has excellent PUE.

For 50,000 servers averaging 300 W, IT power is 15 MW. At PUE 1.2, facility power is 18 MW. Sustained for 8,760 hours, that uses 157,680 MWh; overhead alone uses 26,280 MWh. Power equipment, cooling, electricity, servers, and buildings all contribute to ownership cost.

Low load can still draw substantial power

Energy proportionality means power should rise in proportion to load. A server with 150 W idle power and 300 W peak, increasing linearly, draws 150+0.3(150)=195 W at 30% load. It uses 65% of peak power for 30% of peak work. Historical warehouse-scale measurements found many servers operating between roughly 10% and 50% utilization, making idle power important.

Plan for failures and slow responses

If 50,000 servers each average one failure per ten years, the fleet expects 5,000 failures per year, about 14 per day. That expectation motivates redundancy and retries; it does not schedule exactly 14 failures every day.

A request that needs replies from many servers waits for its slowest required reply. If each of 100 servers independently has a 1% chance of being slow, the chance none is slow is 0.99100. Thus at least one is slow with probability 1−0.99100≈0.634. Tail latency at one server becomes a common request-level delay when the fan-out is large.

Key Takeaways

  • Warehouse-scale design balances service throughput, energy, cost, and availability.
  • Oversubscribed uplinks limit simultaneous off-rack traffic.
  • PUE measures facility overhead, while server efficiency measures useful work inside IT.
  • Idle power makes low utilization costly.
  • Large fleets experience routine failures, and fan-out magnifies tail latency.

Parallel Processors and Multicore examples

5 Walkthroughs

1

Choose a useful source of parallel work

15 steps
Follow a workload from power limits to instruction streams, then use ready threads to cover memory waits.
  1. 1
    IntroductionMore work without a hotter clock

    A service must handle more jobs, but increasing its CPU clock would exceed its power budget. Parallel hardware gets more done within a fixed power budget. The designers can add cores (MIMD), widen data operations (SIMD), or hold more threads ready (multithreading). Each choice needs a suitable source of work. Start by identifying what can run together, then ask how that work reaches the hardware and whether the benefit is shorter response time or greater service capacity (throughput).

  2. 2
    ExplanationVoltage has a squared effect

    Dynamic power roughly follows P≈CV2f. With capacitance unchanged, lowering voltage and frequency to 85% multiplies power by 0.85×0.85×0.85=0.614125. That large reduction helps explain why several modest cores can be attractive. The power wall arose when voltage reductions could no longer offset the heat and power cost of raising clock rates.

  3. 3
    ExampleSeparate one request from many requests

    If four independent downloads run on four cores, the machine may complete more downloads per second even when each download takes the same time. That is a throughput gain from request-level work. If one image is divided into independent regions and four threads process them, that one image may finish sooner. Parallel hardware serves both goals, but the program must expose the appropriate work.

  4. 4
    ExplanationFind work inside a program

    A pipeline overlaps instructions from one stream: ILP. An array operation repeats across elements: DLP. Separate threads provide TLP, with their own execution state and a shared process address space. These forms can coexist. A threaded array program can divide regions across cores, use SIMD inside each region, and execute those instructions through each core’s pipeline.

  5. 5
    ChallengeDoes taking turns count?

    One core alternates between two tasks. Both are in progress for one second, but their instructions never execute at the same instant. Is this parallel execution?

    ---reveal---

    It is concurrent execution through time sharing. Parallelism requires simultaneous operations on separate hardware resources. Another core could provide that simultaneity, but it would still need work ready to execute.

  6. 6
    ExplanationAsk who chooses the next instruction

    Flynn’s taxonomy starts with instruction and data streams. A conventional scalar single core is SISD. A wide operation that applies one instruction to several elements is SIMD. Independently controlled processors handling their data are MIMD. MISD combines multiple instruction streams with one data stream and has few unambiguous practical examples. Count streams at a chosen hardware level.

  7. 7
    ExampleOne program, separate progress

    Four workers use their IDs to split a 4,000-element array into four 1,000-element regions. They run the same program, but one can reach its final addition while another is still loading values. This is SPMD software on MIMD hardware. Sharing program text does not require lockstep instruction issue. A SIMD instruction inside any worker would add another level of parallel execution.

  8. 8
    ChallengeClassify the chosen level

    An independently controlled multicore CPU uses vector additions inside every core. What are the classes across cores and inside a vector addition?

    ---reveal---

    The cores form MIMD hardware because they choose instructions independently. Each vector addition is SIMD because one instruction operates on several data elements. A single machine can have both descriptions when they refer to different levels.

  9. 9
    ExplanationKeep execution state ready

    A hardware thread context stores a program counter and registers. Several contexts can share one core’s arithmetic units and caches. When a memory request stalls one thread, another ready thread can fill idle execution capacity. The operating system sees each context as a logical processor. Two contexts in one core still share that core’s physical execution resources.

  10. 10
    ExplanationChoose when threads share the core

    Fine-grained multithreading selects a ready thread each cycle. Coarse-grained multithreading switches after a long stall, paying switch and pipeline-refill costs. SMT goes further on a multiple-issue core: instructions from different threads can issue during the same cycle. All three depend on useful work being ready; none supplies unlimited extra arithmetic capacity.

  11. 11
    ExampleFirst measure the idle gap

    A thread computes for 20 cycles and then waits 200. Its period is 220 cycles, so active time is 20/220≈9.1%. A long wait leaves most cycles unused when no other thread is available. Keep the full compute-plus-wait period in the denominator. Dividing by the wait alone would describe a different ratio, not the fraction of elapsed cycles doing useful work.

  12. 12
    ExampleFill the gap with ready bursts

    With four freely staggered threads, each contributing 20 compute cycles per 220-cycle period, ideal utilization is 80/220≈36.4%. Eleven threads can fill the period: while one waits 200 cycles, the other ten contribute 200 compute cycles. This ideal model has free switching and no added contention; real bandwidth and cache competition can leave less useful work ready.

  13. 13
    ChallengeWould another context solve it?

    A core’s arithmetic units are already fully occupied, and its two threads both need those same units. Would adding another hardware thread provide the capacity of another core? Explain using the resource they share.

    ---reveal---

    No. A new context supplies another instruction stream but still shares the occupied execution units. Another complete core adds execution hardware. Multithreading is most useful when it fills capacity that stalls or limited ready instructions leave unused.

  14. 14
    ConnectionMatch the service improvement to its cause

    The service adds hardware contexts and now completes more independent requests per second, while each request’s CPU work takes slightly longer. That result is consistent with improved throughput: ready requests fill idle slots while sharing resources. It would be misleading to call it a single-request latency improvement. Choose a performance measure that matches the work users need completed.

  15. 15
    RecapMake the first hardware decision

    For a new workload, first identify independent instructions, data elements, threads, or requests. Then locate the hardware level controlling their instruction streams. If the proposed gain comes from extra contexts, inspect which stalls leave capacity available and which resources the contexts share. This gives a concrete basis for choosing more cores, wider operations, or more ready threads before measuring the result.

2

Find the limit before adding processors

16 steps
Work through fixed-size speedup, scaled workloads, and a bandwidth-bound kernel.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionThree reasons extra hardware can disappoint
  2. 2
    ExplanationChoose the time baseline
  3. 3
    ExampleDivide only the parallel portion
  4. 4
    Key InsightThe fixed part becomes the whole limit
  5. 5
    ChallengeIs the speedup target possible?
  6. 6
    ExplanationKeep the workload question visible
  7. 7
    ExampleUse the parallel run’s fraction
  8. 8
    ExampleWait for the busiest worker
  9. 9
    ChallengeWhen does adding cores make time worse?
  10. 10
    ExplanationCount the bytes that leave memory
  11. 11
    ExampleBuild the two roofs
  12. 12
    ExplanationReuse shifts the kernel right
  13. 13
    ChallengeWhich upgrade lifts the current bound?
  14. 14
    ChallengeA fast kernel inside a slow program
  15. 15
    TipMake the reported gain reproducible
  16. 16
    RecapChoose the next measurement
3

Turn an array loop into GPU work

22 steps
Count SIMD elements, strip mine a vector loop, and build a guarded GPU mapping with correct cooperation.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionStart with independent array elements
  2. 2
    ExampleCount elements before instructions
  3. 3
    ExplanationPut the values next to each other
  4. 4
    ExplanationSelect elements with a mask
  5. 5
    ChallengeCan all iterations start together?
  6. 6
    ExplanationLet the active length describe the pass
  7. 7
    ExampleSplit a long vector into passes
  8. 8
    ConnectionFeed one vector operation into another
  9. 9
    ChallengeAdvance by what actually ran
  10. 10
    ExplanationSchedule a warp while another waits
  11. 11
    ExampleDifferent paths waste active lanes
  12. 12
    ExplanationMake one transaction serve many threads
  13. 13
    ChallengeInclude the trip to the device
  14. 14
    ConnectionSpecialize for a narrower workload
  15. 15
    ExampleFind one thread’s array element
  16. 16
    ExampleCover the final partial block
  17. 17
    ExplanationWait before the host uses results
  18. 18
    ExampleReduce inside a block
  19. 19
    ChallengeCan one block wait for all the others?
  20. 20
    Key InsightA reduction changes the arithmetic order
  21. 21
    ChallengeCombine a safe mapping with efficient access
  22. 22
    RecapCheck the complete array path
4

Follow a shared block from reader to writer

19 steps
Divide a sum, trace cache permissions, and diagnose interference between independent counters.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionShared variables still need coordination
  2. 2
    ExplanationOne address space, different access paths
  3. 3
    ExampleFinish local work before combining
  4. 4
    ChallengeWhat must survive an intervening write?
  5. 5
    ExampleFind the stale cache hit
  6. 6
    ExplanationAgree on one location’s history
  7. 7
    ChallengeCan coherence preserve both increments?
  8. 8
    ConnectionKeep ordering separate from ownership
  9. 9
    ExplanationRead the permissions in MSI
  10. 10
    ExampleFirst give both cores clean copies
  11. 11
    ExampleMove ownership to the writer
  12. 12
    Key InsightExclusive removes a private-data request
  13. 13
    ChallengeTrace one read and two writes
  14. 14
    ExplanationSend the request through the home
  15. 15
    ExampleConvert bits before measuring overhead
  16. 16
    ExampleFind which bytes share ownership
  17. 17
    ChallengeDoes the neighboring reader need to write?
  18. 18
    ChallengeMake a correct sum less contentious
  19. 19
    RecapInspect both the program and the block
5

Follow data, energy, and slow replies across a fleet

14 steps
Compare network cuts, calculate facility energy, and see why large services plan for rare events.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionA node is now a complete computer
  2. 2
    ExplanationPlace work near its input
  3. 3
    ExampleCombine partial sums in message rounds
  4. 4
    ExplanationCount the narrow cut
  5. 5
    ChallengePay for a wider network
  6. 6
    ExplanationShare the uplinks
  7. 7
    ExampleInclude cooling and distribution
  8. 8
    ExampleTurn steady power into annual energy
  9. 9
    ChallengeWhich efficiency did the change improve?
  10. 10
    ExampleLow load still consumes power
  11. 11
    ExplanationSmall failure rates add across the fleet
  12. 12
    ExampleOne slow reply can hold the request
  13. 13
    ChallengeWill more servers shorten every request?
  14. 14
    RecapChoose a fleet metric with a purpose

Parallel Processors and Multicore practice questions

50 Practice Questions in 5 sets

Set 1: Apply scaling, indexing, and coherence rules10 Practice Questions

Question 1 of 10

A core issues instructions from two different threads during the same cycle. Which hardware technique does this describe?
  1. Coarse-grained multithreading
  2. Fine-grained multithreading
  3. Simultaneous multithreading
  4. Operating-system time sharing
Show answerHide answer
Answer: C
Simultaneous multithreading fills a multiple-issue core’s slots with instructions from different threads in one cycle. Fine-grained multithreading changes the selected thread from cycle to cycle; it does not by itself imply that two threads issue instructions during that same cycle.

Question 2 of 10

A fixed job spends 20% of its sequential time in work that cannot be parallelized. With ideal division of the rest over four processors, what speedup results?
  1. 2.5
  2. 3.2
  3. 4.0
  4. 5.0
Show answerHide answer
Answer: A
Normalized time is 0.2+0.8/4=0.4, so speedup is 1/0.4 = 2.5. Dividing the entire job by four would incorrectly accelerate the sequential part. The value five is the unlimited-processor ceiling, which four processors cannot attain.

Question 3 of 10

A simulation increases from two million cells on four processors to four million cells on eight processors, keeping work per cell fixed. What scaling experiment is this?
  1. Strong scaling
  2. Superlinear scaling
  3. Fixed-workload scaling
  4. Weak scaling
Show answerHide answer
Answer: D
The cell count and processor count both double, keeping the number of cells per processor constant. That is weak scaling. Strong scaling would hold the total simulation size fixed and measure how much sooner the same work finishes when more processors share it.

Question 4 of 10

An RVV loop has 90 elements left. Its implementation chooses successive active lengths of 32, 32, and 26. How many elements should the code advance after its second pass?
  1. 26 elements
  2. 32 elements
  3. 64 elements
  4. 90 elements
Show answerHide answer
Answer: B
The second pass processes its returned active length of 32, so its pointer advance is 32 elements. Sixty-four is the cumulative progress after two passes, not the second pass’s increment. Portable RVV code uses each returned length to update pointers and the remaining count.

Question 5 of 10

An array has 4,103 elements. A kernel handles one element per thread and uses 128 threads per block. How many blocks are needed?
  1. 33 blocks
  2. 32 blocks
  3. 34 blocks
  4. 129 blocks
Show answerHide answer
Answer: A
Thirty-two blocks cover 4,096 elements and leave seven untouched. Rounding the quotient up gives 33 blocks, with a bounds check disabling threads beyond index 4102. Rounding down to 32 would be sufficient only if the kernel had another mechanism to process those remaining elements.

Question 6 of 10

Six cores each run a copy of one program. They choose instructions independently and process different array regions. What is the hardware class?
  1. SIMD
  2. SISD
  3. MISD
  4. MIMD
Show answerHide answer
Answer: D
The cores have independent instruction streams and work on different data, which makes the hardware MIMD. Copies of one program describe the SPMD software style; that shared program text does not force the cores to issue one instruction together as SIMD lanes do.

Question 7 of 10

In MESI, A reads an uncached block, writes it, writes it again, and then B reads it. Start with both copies Invalid. How many coherence bus requests occur in this sequence?
  1. 1 request
  2. 3 requests
  3. 2 requests
  4. 4 requests
Show answerHide answer
Answer: C
A’s read obtains Exclusive with one request, and both writes then occur locally as it moves to Modified and stays there. B’s read needs a second request and obtains A’s current data. Counting three requests treats the Exclusive-to-Modified write like an MSI upgrade, which MESI avoids.

Question 8 of 10

A full directory uses one presence bit per core for each 128-byte data block. With 128 cores, what is the storage overhead of the presence vector alone?
  1. 1.56%
  2. 12.5%
  3. 16%
  4. 100%
Show answerHide answer
Answer: B
The presence vector has 128 bits, or 16 bytes. Relative to a 128-byte block, that is 16/128=12.5%. Treating 128 bits as 128 bytes gives 100% and misses the bit-to-byte conversion; additional state fields would increase the actual directory cost beyond the vector alone.

Question 9 of 10

Forty-eight cluster nodes already hold equal shares of 960,000 values. A binary tree combines one local sum per node. What are the values per node and the number of combining rounds?
  1. 20,000 values and 48 rounds
  2. 46,080,000 values and 6 rounds
  3. 20,000 values and 5 rounds
  4. 20,000 values and 6 rounds
Show answerHide answer
Answer: D
Each node handles 960,000/48=20,000 values. Six binary rounds can combine up to 64 partial sums, while five can combine only 32. Forty-eight rounds would describe a much more serial combining process, not the stated binary tree of partial results.

Question 10 of 10

A rack has 24 servers with 25 Gbit/s links and six 50 Gbit/s uplinks. Under equal sharing when every server sends off-rack at once, what are the oversubscription ratio and per-server rate?
  1. 2:1 and 25 Gbit/s
  2. 4:1 and 6.25 Gbit/s
  3. 2:1 and 12.5 Gbit/s
  4. 1:2 and 50 Gbit/s
Show answerHide answer
Answer: C
Server-facing capacity is 24×25=600 Gbit/s, while uplinks provide 6×50=300 Gbit/s. The ratio is 2:1 and equal sharing gives 300/24=12.5 Gbit/s. Assigning each server its full 25 Gbit/s would require twice the available uplink capacity.
Set 2: Recognize parallel work and its costs10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A web service assigns independent image-download requests to different servers. What kind of parallelism is being used?
  1. Instruction-level parallelism
  2. Request-level parallelism
  3. Data-level parallelism
  4. Fine-grained multithreading
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

All processors agree on the order of writes to one memory location. Which coherence property is this?
  1. Write propagation
  2. Sequential consistency
  3. Atomic read-modify-write
  4. Write serialization
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A task takes 144 s on the best sequential implementation and 24 s on eight processors. What is its parallel efficiency?
  1. 75%
  2. 16.7%
  3. 60%
  4. 80%
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A kernel has intensity 3 FLOPs per byte on hardware with 720 GFLOP/s peak compute and 80 GB/s DRAM bandwidth. What roofline bound applies?
  1. 720 GFLOP/s
  2. 960 GFLOP/s
  3. 240 GFLOP/s
  4. 26.7 GFLOP/s
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

How many 64-bit elements fit in a 512-bit SIMD register?
  1. 4 elements
  2. 16 elements
  3. 8 elements
  4. 64 elements
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Two GPU warps take opposite paths through an if-else. Within each warp, all threads agree on the path. What happens to branch divergence?
  1. Both warps execute every branch.
  2. Neither warp diverges internally.
  3. Half of each warp becomes inactive.
  4. Each warp splits into two warps.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A NUMA workload makes 60% of its accesses at 75 ns and the rest at 135 ns. What is the average access latency?
  1. 99 ns
  2. 105 ns
  3. 81 ns
  4. 135 ns
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

Two threads both read a coherent counter as 9 and then both store 10 after an ordinary increment. What property is missing from the increment?
  1. Write propagation
  2. Write serialization
  3. Cache replication
  4. Atomicity
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

In basic MSI, A and B start Invalid for a block holding 4. A reads, A writes 7, and then B reads. What are the final A/B states and the value B reads?
  1. M/S, with B reading 7
  2. S/S, with B reading 7
  3. I/S, with B reading 4
  4. S/S, with B reading 4
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A 20-node ring has equal link bandwidth 5 Gbit/s. Using one capacity value per link, what is its bisection bandwidth?
  1. 10 Gbit/s
  2. 100 Gbit/s
  3. 50 Gbit/s
  4. 5 Gbit/s
Show answerHide answer

Save this lesson to see this answer.

Set 3: Diagnose performance limits across the system10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A single superscalar core follows one instruction stream and overlaps independent scalar instructions. How is it classified in Flynn’s taxonomy?
  1. SIMD
  2. SISD
  3. MIMD
  4. MISD
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

Capacitance stays fixed while voltage falls to 90% and frequency to 80% of their original values. What fraction of the original dynamic power remains?
  1. 0.720
  2. 0.810
  3. 0.5832
  4. 0.648
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

Six cores initially receive equal-cost task counts of 35, 35, 35, 35, 35, and 65. A scheduler moves ten tasks from the busiest core to each of the other five. With no overhead and one task per time unit per core, how does speedup over sequential execution change?
  1. From about 3.69 to 5.33
  2. From about 3.69 to 6.00
  3. From exactly 6.00 to 5.33
  4. From exactly 4.00 to 5.33
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A machine peaks at 960 GFLOP/s and 120 GB/s. A kernel performs 12 GFLOPs and transfers 3 GB from DRAM. Blocking halves traffic without changing work. What happens to the roofline bound?
  1. It rises from 480 to 1,920 GFLOP/s.
  2. It stays fixed at 480 GFLOP/s.
  3. It rises from 480 to 960 GFLOP/s.
  4. It rises from 240 to 480 GFLOP/s.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A loop computes a[i] = a[i-1] + b[i] from left to right. Why can the compiler not directly replace consecutive iterations with independent SIMD lanes?
  1. Each iteration reads values from two different arrays.
  2. Each iteration needs the preceding iteration’s new result.
  3. Each iteration contains more than one arithmetic input.
  4. Each iteration stores its result into a contiguous array.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

An RVV loop has 50 doubles remaining and capacity 32. The implementation returns vl = 28. The programmer advances both pointers by 32 elements and subtracts 32 from the remaining count. What is the first lost data range?
  1. Original indexes 0 through 27
  2. Original indexes 32 through 49
  3. Original indexes 24 through 27
  4. Original indexes 28 through 31
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

In a NUMA system, why can two accesses to the same shared address have different latency from different sockets?
  1. The address can be local to one socket and remote to another.
  2. Each socket must assign the address a different numeric value.
  3. Each socket must use a separate application-level address space.
  4. The address must bypass every private cache on the machine.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

With 64-byte blocks, A repeatedly writes an 8-byte counter at 0x2040; B repeatedly reads an independent 8-byte status value at 0x2078. Why can B suffer coherence misses?
  1. The variables occupy adjacent blocks, so every read fetches both blocks.
  2. Both threads write the same counter, so an increment is lost.
  3. Both variables occupy block 129, and A’s writes invalidate B’s copy.
  4. The reader needs Modified ownership before it can read the status.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A 72-element vector add runs on six lanes. Ignoring startup, how many cycles are needed for the element operations?
  1. 6 cycles
  2. 72 cycles
  3. 12 cycles
  4. 432 cycles
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

IT equipment draws a steady 8 MW and facility overhead adds 2 MW. What is the PUE?
  1. 1.25
  2. 0.25
  3. 0.80
  4. 4.00
Show answerHide answer

Save this lesson to see this answer.

Set 4: Combine hardware behavior with performance models10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A machine has 12 cores and two hardware threads per core. How many logical processors are visible, and how many physical cores exist?
  1. 24 logical processors and 12 cores
  2. 24 logical processors and 24 cores
  3. 12 logical processors and 24 cores
  4. 12 logical processors and 12 cores
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A single-core system alternates between two long-running tasks, never executing their instructions at the same instant. How should their execution be described?
  1. Parallel but not concurrent
  2. Both parallel and concurrent
  3. Concurrent but not parallel
  4. Neither parallel nor concurrent
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A low-intensity kernel already saturates DRAM bandwidth and runs at its roofline bound. SIMD width doubles while bandwidth and intensity stay fixed. How does its roofline bound change?
  1. It doubles.
  2. It falls by half.
  3. It rises by the original intensity.
  4. It stays the same.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A reduction kernel uses if (i < n) { load_into_shared(); __syncthreads(); combine(); }. In its last block only some threads satisfy the condition. What structural correction makes the block barrier safe?
  1. Remove the bounds check so all block threads load an array element.
  2. Let all block threads reach the barrier, with neutral values for inactive inputs.
  3. Replace the block barrier with a host wait after kernel launch.
  4. Place a second identical barrier inside the same conditional branch.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A CPU takes 36 ms per batch. A discrete GPU needs one 500 MB upload, then three 4 ms kernels, then one 100 MB download. Transfers achieve 15 GB/s, cannot overlap computation, and launch cost is negligible. Which path is faster and by how much?
  1. The GPU is faster by 24 ms.
  2. The CPU is faster by 16 ms.
  3. The CPU is faster by 4 ms.
  4. The GPU is faster by 16 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Thirty-two cores split 32,000 values equally. Each thread starts at zero and adds its assigned values, then a binary tree combines the partial sums. Each addition costs one time unit; each tree stage also has a two-unit barrier. With no other costs, what speedup results over a sequential sum starting at zero?
  1. About 31.53
  2. About 31.84
  3. About 31.69
  4. Exactly 32.00
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A core uses a write-through cache. Another core already holds a clean cached copy of the same address. Why is a coherence mechanism still needed after the first core writes?
  1. Write-through prevents the first core from updating memory.
  2. A clean cache copy cannot ever become invalid.
  3. The second core must discard every cache block on each read.
  4. Updating memory alone leaves the other cached copy stale.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

In MESI, A reads an uncached block, B reads it, A writes 3, A writes 6, and B reads again. How many bus requests occur, and what value does B’s final read obtain?
  1. 3 requests, returning 6
  2. 5 requests, returning 6
  3. 4 requests, returning 6
  4. 4 requests, returning 3
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

Two facilities have the same PUE. One runs mostly idle servers; the other completes far more work with its IT energy. What does equal PUE establish?
  1. Their useful computations per joule match.
  2. Their total facility energy amounts match.
  3. Their server utilization percentages match.
  4. Their facility-to-IT energy ratios match.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Eight independently controlled CPU cores each execute an eight-lane SIMD add in one cycle. How should the two levels be described?
  1. SIMD across cores and SISD within each add
  2. SISD across cores and MIMD within each add
  3. MIMD across cores and SIMD within each add
  4. MISD across cores and SIMD within each add
Show answerHide answer

Save this lesson to see this answer.

Set 5: Transfer the models to new design decisions10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

An ideal fixed-workload run reaches speedup 4 on eight processors. Its sequential work is then made twice as fast, leaving the parallel work unchanged. What speedup does the new eight-processor run achieve relative to the original sequential baseline?
  1. 4.0
  2. 5.6
  3. 4.67
  4. 8.0
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

Design A has four cores with two hardware contexts each; design B has two cores with eight contexts each. Each thread repeats 15 compute cycles then 105 wait cycles. Each core can perform one compute step per cycle. With ideal staggering, free switching, and no memory contention, how do their steady-state compute throughputs compare?
  1. A supplies twice B’s throughput.
  2. Both supply the same throughput.
  3. B supplies twice A’s throughput.
  4. B supplies four times A’s throughput.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A fixed workload must reach speedup at least 12 on sixteen processors under ideal Amdahl scaling. What is the largest allowed sequential fraction of its original time?
  1. 1/45, about 2.22%
  2. 1/12, about 8.33%
  3. 1/16, about 6.25%
  4. 1/15, about 6.67%
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A fully divisible job has measured time model Tp=288/p+2p seconds. You can use 8, 12, 16, or 24 processors. Which allocation finishes fastest?
  1. 8 processors
  2. 16 processors
  3. 24 processors
  4. 12 processors
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A loop adds two arrays of 1,237 floats using 256-bit SIMD instructions. Full vectors are processed first, then a scalar tail. How many full iterations and scalar elements are needed?
  1. 155 vector iterations and 3 scalar elements
  2. 154 vector iterations and 8 scalar elements
  3. 153 vector iterations and 5 scalar elements
  4. 154 vector iterations and 5 scalar elements
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A 16-node ring and a fully connected 16-node network both use 10 Gbit/s links. Under one capacity value per link, what bisection-capacity gain does full connection give, and how many extra links does it need?
  1. 32 times the capacity, with 120 extra links
  2. 32 times the capacity, with 104 extra links
  3. 8 times the capacity, with 104 extra links
  4. 7.5 times the capacity, with 104 extra links
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What hardware group contains 32 threads that share instruction issue in NVIDIA’s SIMT execution model?
  1. A thread block
  2. A streaming multiprocessor
  3. A warp
  4. A CUDA core
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A guarded one-element-per-thread kernel launches 37 blocks of 64 threads for an array of 2,350 elements. How many threads in the final block access valid elements, and what is their last valid thread index within that block?
  1. 46 threads; last local index 45
  2. 46 threads; last local index 46
  3. 18 threads; last local index 17
  4. 47 threads; last local index 46
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A cache holds a block in Exclusive state under MESI. Its processor writes the block while no other core accesses it. What state and coherence request result?
  1. Modified, with no bus request
  2. Shared, with a bus read
  3. Modified, with an upgrade request
  4. Exclusive, with a write-update request
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Two independent 8-byte counters occupy 0x3000 and 0x3038 with 64-byte cache blocks. Each has its own writer. What movement separates them into different blocks?
  1. Move the second counter to 0x3020.
  2. Move the second counter to 0x3040.
  3. Move the first counter to 0x3008.
  4. Move the second counter to 0x3010.
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

100 Key Terms, each with its definition

A

Aliasing
Aliasing occurs when different references can access overlapping storage, which can make simultaneous loop operations unsafe.
A compiler checks for aliasing before reordering loads and stores through potentially overlapping pointers.
Amdahl’s law
Amdahl’s law bounds an enhancement’s overall speedup using the original time fraction it affects and the acceleration of that fraction.
Amdahl’s law explains why making a small part of a program much faster may barely change its total time.
Arithmetic intensity
Arithmetic intensity is floating-point operations per transferred byte; in a DRAM roofline it counts bytes at the DRAM boundary.
Cache reuse increases arithmetic intensity when the useful operation count stays fixed but DRAM traffic falls.
Asynchronous launch
An asynchronous launch starts device work without making the host wait for that work to finish before continuing execution.
An asynchronous launch needs a later completion check or blocking result copy before host-side result use.
Atomic read-modify-write
An atomic read-modify-write updates a memory location indivisibly as observed by other processors, combining the read and write.
Atomic read-modify-write prevents two counter increments from both overwriting the same old value.
Auto-vectorization
Auto-vectorization is a compiler transformation that converts suitable scalar loop work into SIMD operations while preserving required results.
Possible pointer overlap can prevent auto-vectorization unless a check establishes that the arrays do not overlap.
Availability
Availability is the ability of a service to remain usable despite failures, supported at scale by redundancy, retries, and rerouting.
A warehouse-scale service protects availability by routing new requests away from a failed server.

B

Barrier
A barrier is a synchronization point that all participating threads must reach before any continues into the next phase.
A barrier between reduction stages prevents a worker from reading a partial sum before it is written.
Bisection bandwidth
Bisection bandwidth is the least total link capacity across a cut dividing a network’s nodes into two equal-sized groups.
A ring has only two links across a minimum cut, so its bisection bandwidth can limit cross-half traffic.
Bounds check
A bounds check tests that a computed index lies inside the valid data range before a thread makes the associated memory access.
When a grid is rounded up to whole blocks, a bounds check disables the extra threads in the final block without skipping valid elements.
Branch divergence
Branch divergence occurs when threads within one warp follow different paths, requiring those paths to execute with different active masks.
Branch divergence can leave half a warp inactive while the threads assigned to the other path execute.

C

Cache coherence
Cache coherence coordinates copies of a location so processors observe a compatible history of its writes and read values.
Cache coherence prevents a reader from indefinitely using a stale private copy after another core updates it.
Ceiling
A ceiling is a lower limit within a roofline analysis that represents a restriction such as missing SIMD or poor access patterns.
A bandwidth ceiling below the main roof can show the performance lost to inefficient memory accesses.
Chaining
Chaining overlaps dependent vector operations by allowing a consumer to start on early elements before the producer finishes all elements.
Chaining lets an add use the first products while the multiply pipeline continues generating later products.
Cluster
A cluster is a network-connected collection of complete computers, each with its own memory and operating system.
A cluster distributes a large array among nodes and combines their local results through network messages.
Coalescing
Coalescing combines neighboring threads’ nearby memory accesses into a small number of wide transactions to use bandwidth efficiently.
Coalescing works well when consecutive warp threads read consecutive 4-byte elements of an array.
Coarse-grained multithreading
Coarse-grained multithreading changes threads on long stalls, allowing extended single-thread execution between costly switches.
Coarse-grained multithreading may switch after a last-level cache miss that requires a long memory access.
Coherence miss
A coherence miss occurs when an access must refetch a block that another processor’s coherence action has invalidated.
A neighboring variable’s writer can cause a coherence miss even when the reader’s own variable never changes.
Compute-bound kernel
A compute-bound kernel has enough intensity that peak arithmetic capacity is the lower limit in the roofline model.
Blocking can move a computation toward a compute-bound kernel by reusing data for many arithmetic operations.
Concurrency
Concurrency is progress on multiple tasks during overlapping periods, including taking turns on one execution resource.
A single-core operating system supports concurrency by alternating between a download and an editor.

D

Data-level parallelism
Data-level parallelism applies the same operation across multiple independent data elements, often using SIMD lanes or GPU threads.
Adding corresponding array elements offers data-level parallelism because each pair can be processed independently.
Directory
A directory records coherence state and cached holders of memory blocks so requests can be sent to the relevant caches.
A directory forwards a read request to the cache holding the latest Modified copy instead of broadcasting it.
Domain-specific accelerator
A domain-specific accelerator specializes hardware for a restricted workload, trading flexibility for high performance per watt in that domain.
A matrix-oriented domain-specific accelerator may favor low-precision multiplication for neural-network work.

E

Energy efficiency
Energy efficiency compares useful work completed with energy consumed, including whether server resources are used effectively.
A facility can improve PUE while leaving server energy efficiency poor if much of its IT load does no useful work.
Energy proportionality
Energy proportionality is the design goal that power consumption should increase in proportion to the useful load a system handles.
High idle power weakens energy proportionality because a lightly loaded server still consumes substantial energy.
Exclusive state
The Exclusive state in MESI marks a clean block held by only one cache, allowing a silent transition to Modified on a write.
A read followed by a private write benefits from Exclusive state because the write needs no upgrade request.

F

False sharing
False sharing is coherence interference between cores accessing different variables in one cache block when at least one core writes.
False sharing can make separate counters slow when their writers repeatedly exchange ownership of one block.
Fan-out
Fan-out is the distribution of one request’s work to several servers whose required replies contribute to its completion.
Larger fan-out gives a rare slowdown at any one server more chances to delay the complete request.
Fetch-and-add
Fetch-and-add is an atomic operation that returns a location’s previous value while adding a specified amount indivisibly.
Fetch-and-add can preserve every increment when several threads update one shared counter concurrently.
Fine-grained multithreading
Fine-grained multithreading selects a thread each clock cycle, usually rotating among ready contexts while skipping stalled ones.
Fine-grained multithreading can alternate short bursts from several threads to cover pipeline stalls.
Flynn’s taxonomy
Flynn’s taxonomy classifies hardware by whether instruction streams and data streams are single or multiple at a chosen machine level.
Flynn’s taxonomy can describe independent CPU cores differently from the SIMD units inside those cores.

G

Global memory
Global memory is GPU device DRAM accessible across the grid, with accesses served through the device’s cache hierarchy.
A kernel can reuse shared-memory tiles to reduce the number of times it rereads data from global memory.
Granularity
Granularity is the amount of computation performed between communication or synchronization events in a parallel computation.
Larger granularity can reduce messaging cost per operation but leave too few chunks for good load balance.
Grid
A grid is the collection of thread blocks created by a GPU kernel launch, whose ordinary blocks may run in any order.
A grid must contain enough blocks to cover all data when the kernel handles only one element per thread.
Gustafson’s law
Gustafson’s law estimates scaled speedup from processor count and the sequential time fraction measured on the parallel run.
Gustafson’s law describes how a larger parallel problem can use a bigger machine within a similar time budget.

H

Hardware multithreading
Hardware multithreading keeps several thread contexts in one core so it can execute ready work while another thread stalls.
Hardware multithreading can fill memory-wait cycles without duplicating a complete physical core.
Home node
A home node manages the directory entry for a particular memory block and coordinates requests involving that block’s cached copies.
Different blocks can have different home nodes, distributing directory storage and request handling.
Host
The host is the CPU side of a heterogeneous program, responsible for organizing device storage, transfers, launches, and result use.
The host can continue after a launch but must wait for completed device results before consuming them.

I

Indexed access
An indexed access obtains element addresses from indexes, supporting irregular vector gathers and scatters beyond fixed strides.
An indexed access can fetch the selected array entries named by an irregular list of positions.
Instruction-level parallelism
Instruction-level parallelism overlaps instructions from one instruction stream through techniques such as pipelining and multiple issue.
A core exploits instruction-level parallelism by issuing two independent scalar additions together.
Invalid state
The Invalid state marks a cache block whose contents cannot be used to satisfy the processor’s read or write access.
A later read of a block in Invalid state must obtain a valid copy through the memory hierarchy.

K

Kernel
A kernel is a device function launched over many GPU threads, each executing the function with its own indexes and data.
A SAXPY kernel assigns one array element to each valid thread and checks the upper index bound.

L

Latency hiding
Latency hiding executes other ready work during a wait, improving resource use without shortening the waiting operation itself.
A GPU uses latency hiding when its scheduler selects another warp during a pending memory access.
Link bandwidth
Link bandwidth is the data rate available on one network link, measured under a consistent directional capacity convention.
A topology with more links can have greater total capacity even when every link bandwidth is unchanged.
Load balance
Load balance is the distribution of useful work among processors so that no worker’s excess load unnecessarily delays the phase.
Poor load balance leaves seven workers waiting while one worker finishes a disproportionately large partition.
Logical processor
A logical processor is a hardware thread context visible to the operating system as a place where a software thread can run.
A six-core chip with two contexts per core exposes twelve logical processors while sharing six cores.
Loop-carried dependence
A loop-carried dependence occurs when one iteration requires a value produced by another iteration, constraining their execution order.
An accumulating recurrence has a loop-carried dependence because each new value uses the preceding result.

M

Mask
A mask selects active elements of a SIMD or vector operation, allowing conditional work without a separate instruction stream per lane.
A mask can suppress updates for array elements that fail a comparison or lie beyond the valid tail.
Memory consistency model
A memory consistency model defines allowed observable orderings and results of reads and writes, including different locations.
A memory consistency model determines how another processor may observe accesses to a flag and its data.
Memory-bound kernel
A memory-bound kernel has a lower memory-bandwidth roof than compute roof, so its upper rate depends on data supply.
Once a memory-bound kernel saturates DRAM bandwidth, wider arithmetic alone cannot raise its roofline bound.
MIMD
MIMD is a hardware class with multiple independently controlled instruction streams operating on multiple data streams.
A cluster is MIMD when its nodes independently advance through their computations and exchange messages.
MISD
MISD is the hardware class with multiple instruction streams acting on one data stream; few practical machines fit it clearly.
The MISD label completes the four combinations of single and multiple streams, while proposed real examples often depend on interpretation.
Modified state
The Modified state marks the only valid cached copy of a block, with data that has been written and is newer than memory.
A core can update a block in Modified state repeatedly without obtaining write permission again.
MPI
MPI is a standard message-passing interface for processes to exchange data and perform collective operations across a parallel program.
An MPI reduction combines distributed partial sums without treating remote node data as ordinary local pointers.

N

NUMA
NUMA is a shared-memory organization in which memory access cost depends on the processor’s location relative to the data.
A NUMA workload can reduce average latency by placing frequently used pages near the threads that access them.

O

Oversubscription
Oversubscription occurs when upper network links provide less capacity than the aggregate capacity of the lower links feeding them.
A rack with 400 Gbit/s of server links and 100 Gbit/s of uplinks has 4:1 oversubscription.

P

Parallel efficiency
Parallel efficiency is speedup divided by processor count, expressing the useful gain relative to the processors allocated.
A speedup of six on eight processors gives parallel efficiency of 75%, even though the time reduction is larger.
Parallel overhead
Parallel overhead is execution cost added by parallel organization, such as scheduling, communication, synchronization, or extra work.
Parallel overhead can grow enough that a job takes longer after its processor count is increased.
Parallelism
Parallelism is the simultaneous execution of operations on separate hardware resources to reduce latency or increase throughput.
A simulation uses parallelism when several cores update independent regions at the same instant.
Power wall
The power wall is the power and heat constraint that limits performance gains from continuing to raise processor clock rates.
The power wall encouraged chip designers to spend additional transistors on more processor cores.
Presence vector
A presence vector uses one bit per core to record which caches hold a particular block in a full-vector directory.
A presence vector for 64 cores requires eight bytes per tracked block before the coherence state bits.
PUE
PUE is the ratio of total facility energy to IT equipment energy over the same period, measuring energy overhead outside the IT load.
A PUE of 1.2 means total facility energy is 20% above IT energy, without measuring useful work inside servers.

R

Rank
A rank is the identifier of an MPI process within a communicator, used to select participants and assign data or communication roles.
A process uses its rank to determine which array partition to sum and where to send its partial result.
Reduction tree
A reduction tree combines partial results in successive parallel stages, reducing many values to one with a short dependent path.
A reduction tree combines 32 partial sums in five pairing stages instead of 31 consecutive additions.
Request-level parallelism
Request-level parallelism executes independent jobs or service requests at once, with little coordination between their computations.
A search service gains request-level parallelism from thousands of users asking independent questions.
Ridge point
The ridge point is the intensity where the bandwidth roof meets the compute roof, equal to peak compute divided by bandwidth.
A ridge point of ten FLOPs per byte puts a two-FLOP-per-byte kernel below the compute-limited region.
Roofline model
The roofline model bounds attainable arithmetic performance by the lower of peak compute and bandwidth multiplied by intensity.
The roofline model helps decide whether faster arithmetic or less data movement can raise a kernel’s bound.

S

Sequential consistency
Sequential consistency requires results matching one interleaving of all processors’ operations that preserves each processor’s program order.
Sequential consistency constrains the combined history without requiring processors to execute at the same speed.
Sequential fraction
The sequential fraction is the portion of baseline execution time that cannot be divided among processors in the parallel model.
A sequential fraction of 0.1 leaves one tenth of the original time even if all parallel work became free.
Shared memory
Shared memory is program-managed on-chip GPU storage available to threads in one block for cooperation and data reuse.
A block loads a tile into shared memory before reusing that tile across several arithmetic operations.
Shared state
The Shared state marks a clean, read-only cached copy of a block that may also be present in other caches.
A writer must request ownership before changing a block in Shared state because other readers may hold it.
Shared-memory multiprocessor
A shared-memory multiprocessor lets processors communicate through loads and stores in one physical address space.
A shared-memory multiprocessor can still have separate private caches and memory distributed over sockets.
SIMD
SIMD is a hardware class in which one instruction controls the same operation across multiple data elements or arithmetic lanes.
An eight-lane array add is SIMD even though it performs eight element additions with one issued instruction.
SIMD lane
A SIMD lane is one element position and its associated arithmetic work within a wide operation controlled by a shared instruction.
A 256-bit add has eight SIMD lanes for 32-bit floats but four lanes for 64-bit doubles.
SIMT
SIMT is a GPU execution style that presents independent threads while issuing an instruction across a group’s active threads.
SIMT code computes one index per thread even though instruction issue is shared within each warp.
Simultaneous multithreading
Simultaneous multithreading lets a multiple-issue core issue instructions from different hardware threads within the same cycle.
Simultaneous multithreading fills spare issue slots when one thread cannot supply enough ready instructions.
SISD
SISD is a hardware class with one instruction stream and one data stream, including conventional scalar cores with pipelining.
A scalar pipelined core remains SISD because overlapping instructions still follow one instruction stream.
Snooping
Snooping is a coherence method in which cache controllers monitor broadcast requests and update their blocks’ permissions or data.
Snooping lets a Modified owner detect another core’s read request and supply the current block contents.
Speedup
Speedup is best sequential execution time divided by parallel execution time for the workload being compared.
A program finishing in 12 s instead of 60 s has a speedup of five relative to its sequential baseline.
SPMD
SPMD is a programming style in which workers execute copies of the same program and use their identities to select different data.
An SPMD array sum uses each worker’s ID to choose a region before combining the workers’ partial results.
Streaming multiprocessor
A streaming multiprocessor is a processing unit in NVIDIA GPUs that schedules resident warps across arithmetic lanes and on-chip storage.
A streaming multiprocessor can issue another ready warp when one resident warp waits for global memory.
Strided access
A strided access visits successive elements at a fixed address spacing, such as the distance between entries in a matrix column.
A strided access down a 100-column double matrix advances 800 bytes between neighboring column entries.
Strip mining
Strip mining divides a long loop into chunks that fit the vector configuration, updating progress after each processed chunk.
Strip mining can process 100 elements with successive active lengths of 32, 32, 32, and four.
Strong scaling
Strong scaling measures how elapsed time changes as more processors execute the same fixed-size computational problem.
A strong scaling experiment keeps a simulation’s cell count fixed while increasing its processor allocation.
Structure of arrays
A structure of arrays stores each field’s values in a separate array, making values of one field contiguous for vector access.
A structure of arrays keeps all x coordinates together when a geometry loop processes only that field.
Superlinear speedup
Superlinear speedup is a measured speedup exceeding processor count, possible when parallel partitioning also lowers the cost of work.
Improved cache fit can produce superlinear speedup when each partition avoids the sequential run’s DRAM misses.

T

Tail latency
Tail latency is the high-delay end of response times, which can dominate a request that needs replies from many servers.
A fan-out request waits for its slowest required reply, making single-server tail latency a service-wide concern.
Thread block
A thread block is a group of GPU threads that can cooperate through shared memory and synchronize with a block-wide barrier.
A thread block can combine its partial sums, while a later kernel combines results from separate blocks.
Thread-level parallelism
Thread-level parallelism executes several threads at the same time, each with its own program counter and register state.
An image renderer uses thread-level parallelism by assigning different image regions to different workers.
Torus
A torus is a mesh network with wraparound links connecting opposite edges, adding paths and increasing cross-section capacity.
An 8 by 8 torus has 128 links, including the wraparound connections that an ordinary mesh lacks.
True sharing
True sharing occurs when processors communicate through the same memory word, so their coherence interaction concerns the same data.
A producer writes a value that a consumer reads, creating true sharing of that communication variable.

U

UMA
UMA is a shared-memory organization with approximately uniform memory access time from its processors to memory locations.
A small UMA machine presents similar memory-access paths without a local-versus-remote socket distinction.

V

Vector length
The vector length is the number of active elements processed by vector instructions under the current vector configuration.
A short vector length lets a loop’s last pass update its eight remaining elements without executing a separate scalar tail.
VLEN
VLEN is an RVV implementation’s vector-register width in bits, distinct from active element count and parallel execution-lane count.
A larger VLEN can hold more elements, while the program still advances by the active length it receives.

W

Warehouse-scale computer
A warehouse-scale computer operates a large building of networked servers, power, and cooling as one platform for services and batch work.
A warehouse-scale computer must account for energy and routine failures as well as request throughput.
Warp
A warp is a group of 32 threads in NVIDIA’s execution model; active threads share instruction issue and retain separate data.
Threads in a warp can use consecutive indexes so their loads combine into efficient memory transactions.
Weak scaling
Weak scaling grows total work in proportion to processor count, keeping work per processor constant across the experiment.
A weak scaling experiment doubles the data when it doubles the processors, then compares elapsed times.
Write propagation
Write propagation is the coherence requirement that a processor’s write eventually becomes visible to other processors’ reads.
Write propagation ensures a new value does not remain permanently hidden in its writer’s private cache.
Write serialization
Write serialization requires every processor to agree on the order of writes to the same location in a coherent memory system.
Write serialization prevents processors from observing opposite orders for two writes to the same location X.
Write-invalidate protocol
A write-invalidate protocol grants a writer exclusive write permission by making other cached copies of its block unusable.
A write-invalidate protocol lets an owner perform repeated Modified writes without broadcasting every new value.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started