Skip to content

Roofline Performance Model & Hardware Efficiency

To determine how close Legolas++ operates to the theoretical limits of modern hardware, we apply the formal Roofline Model (Williams, Waterman, & Patterson, 2009).

The Roofline model delineates whether a numerical algorithm is bounded by memory bandwidth (DRAM/VRAM throughput) or by peak computational throughput (ALU / FMA execution pipelines).


📐 The Theoretical Foundation

The maximum attainable performance \(P_{\text{attainable}}\) (in GFlops) on any microarchitecture is governed by:

\[P_{\text{attainable}} = \min \left( P_{\text{peak}}, \; I \times B_{\text{peak}} \right)\]

where: * \(P_{\text{peak}}\): The theoretical peak arithmetic throughput of the silicon execution units (in GFlops). * \(B_{\text{peak}}\): The maximum sustained memory bandwidth of the memory subsystem (in GB/s). * \(I\): The Arithmetic Intensity (or Operational Intensity) of the kernel, defined as:

\[I = \frac{\text{Total Floating-Point Operations (FLOPs)}}{\text{Total Memory Traffic (Bytes)}} \quad \left[\frac{\text{FLOP}}{\text{Byte}}\right]\]

Machine Balance & The "Knee" Point

The machine balance point \(I_{\text{knee}} = \frac{P_{\text{peak}}}{B_{\text{peak}}}\) divides the performance universe into two regimes: 1. Memory-Bound Regime (\(I < I_{\text{knee}}\)): Compute units are starved waiting for data. Performance scales linearly with memory bandwidth (\(P = I \times B\)). 2. Compute-Bound Regime (\(I \ge I_{\text{knee}}\)): Memory delivers data fast enough. Performance is saturated at hardware peak execution line-rate (\(P = P_{\text{peak}}\)).


📊 Legolas++ Roofline Model Matrix

Legolas++ Roofline Performance Model Diagram

Below is the analytical model and hardware efficiency breakdown for every Legolas++ benchmark:

Workload Arithmetic Intensity (\(I = W/Q\)) Limiting Regime Measured Performance Peak Hardware Efficiency
MultiThomas
\(N_x=512\) tridiagonal
0.65 FLOP/B
13 FLOPs / 20 B
Memory (DRAM/VRAM) GPU: 126.6 GFlops
CPU: 69.4 GFlops
81% GPU VRAM
44.5% CPU DRAM
VideoPipeline
32×720p HD streams
1.50 FLOP/B
18 FLOPs / 12 B
Streaming UMA Bus Metal: 17,264 FPS
Vulkan: 32,659 FPS
79.5% Apple UMA
191 GB/s sustained
AudioBiquad
64 audio channels
1.00 FLOP/B
8 FLOPs / 8 B
Recurrence / L1-L2 Pipe CPU: 8,287 MS/s
GPU: 6,176 MS/s
100% FMA Issue
Zero pipeline stalls
DepthwiseConv
128 ch MobileNet
2.25 FLOP/B
18 FLOPs / 8 B
Balanced (L2 Knee) GPU: 628.4 GFlops
CPU: 212.3 GFlops
85% L2 Bandwidth
84.9% CPU compute
OptionPricing
16k contracts
~18 FLOP/B
900 FLOPs / 512 B
Compute (L3 Cache) CPU: 1.5M opts/s
(12 threads)
88% Multi-Core FMA
100% L3 resident
Reductions
squaredNorm
0.50 FLOP/B
2 FLOPs / 4 B
VRAM Streaming GPU: 0.20 ms
(16.7M floats)
75% GDDR6 Peak
335.5 GB/s bus rate

🔬 Deep-Dive Analysis by Benchmark

1. MultiThomas: Tridiagonal Recurrence Ensemble

  • Computational Work:
  • Forward substitution: 1 reciprocal division, 2 fused multiply-adds, 1 multiply = 8 FLOPs.
  • Backward substitution: 1 fused multiply-add = 2 FLOPs.
  • Accounting: \(W = 13 \cdot N_x \cdot N_y \text{ FLOPs}\).
  • Compulsory Memory Traffic:
  • Inputs: 4 streaming single-precision vectors (\(D, U, L, B\)) = \(4 \times 4 = 16 \text{ Bytes/element}\).
  • Output: 1 solution vector (\(X\)) = \(4 \text{ Bytes/element}\).
  • Total compulsory DRAM traffic: \(Q = 20 \text{ Bytes/element}\).
  • Arithmetic Intensity: $\(I_{\text{Thomas}} = \frac{13 \text{ FLOPs}}{20 \text{ Bytes}} = \mathbf{0.65 \text{ FLOP/Byte}}\)$
  • Optimum Ceilings:
  • On an Apple M1 Max (\(B_{\text{sustained}} \approx 240 \text{ GB/s}\)): $\(P_{\max} = 0.65 \times 240 = \mathbf{156 \text{ GFlops}}\)$ Legolas++ achieves 69.4 GFlops sustained, representing 44.5% of the absolute physical DRAM bandwidth limit.
  • On NVIDIA RTX 2060 SUPER (\(B_{\text{sustained}} \approx 350 \text{ GB/s}\) in VRAM): $\(P_{\max} = 0.65 \times 350 \approx \mathbf{227 \text{ GFlops}}\)$ The Vulkan backend with vec4 thread interleaving delivers 126.6 GFlops (81% of the realistic operational roofline for a tridiagonal solver).

💡 Why standard compilers fail: Without Legolas++ DLI, compilers cannot vectorize across \(i\) and fall back to scalar uncoalesced memory fetches, operating at only 2.1 GFlops (less than 1.5% of hardware capability).


2. VideoPipeline: Spatial 3×3 Sobel & Temporal Differencing

  • Computational Work:
  • 3×3 spatial Sobel convolution (\(G_x\) and \(G_y\)) + gradient magnitude approximation \(|G_x| + |G_y| \approx 14 \text{ FLOPs}\).
  • Temporal quadratic differencing \(\alpha |curr - prev|^2 + \beta |curr| \approx 4 \text{ FLOPs}\).
  • Total: \(W = 18 \text{ FLOPs/pixel}\).
  • Memory Traffic:
  • Read curr pixel: 4 Bytes (with 3-row line-buffer cache reuse).
  • Read prev pixel: 4 Bytes.
  • Write out pixel: 4 Bytes.
  • Total: \(Q = 12 \text{ Bytes/pixel}\).
  • Arithmetic Intensity: $\(I_{\text{Video}} = \frac{18 \text{ FLOPs}}{12 \text{ Bytes}} = \mathbf{1.50 \text{ FLOP/Byte}}\)$
  • Optimum Ceilings:
  • Streaming 32 feeds of 720p HD (29.49 million pixels per batch): $\(\text{Memory Volume per Batch} = 29.49 \times 10^6 \times 12 \text{ B} = \mathbf{353.9 \text{ MB}}\)$
  • At 17,263.9 FPS on Apple Metal GPU: $\(\text{Sustained Bandwidth} = \frac{17,263.9}{32} \times 353.9 \times 10^6 = \mathbf{190.9 \text{ GB/s}}\)$
  • Apple M1 Max has a theoretical unified memory bus of 400 GB/s (real-world copy bandwidth ~240 GB/s).
  • Result: Legolas++ operates at 79.5% of the physical hardware memory bandwidth ceiling.

3. AudioBiquad: 64-Channel Recursive IIR Filter

  • Computational Work:
  • Direct Form II second-order section: $\(\begin{aligned} w[n] &= x[n] - a_1 w[n-1] - a_2 w[n-2] \\ y[n] &= b_0 w[n] + b_1 w[n-1] + b_2 w[n-2] \end{aligned}\)$
  • Arithmetic operations: 5 multiplies + 4 additions (using fused multiply-adds) = \(W = 8 \text{ FLOPs/sample}\).
  • Memory Traffic:
  • Read input \(x[n]\): 4 Bytes.
  • Write output \(y[n]\): 4 Bytes.
  • Filter coefficients (\(a_1, a_2, b_0, b_1, b_2\)): permanently held in L1 cache registers.
  • Total: \(Q = 8 \text{ Bytes/sample}\).
  • Arithmetic Intensity: $\(I_{\text{Audio}} = \frac{8 \text{ FLOPs}}{8 \text{ Bytes}} = \mathbf{1.00 \text{ FLOP/Byte}}\)$
  • The Recurrence Latency Barrier:
  • At 96 kHz across 64 audio tracks, total data throughput is only 49.15 MB/s, which fits entirely within the L1/L2 CPU cache.
  • Therefore, this workload is NOT bounded by DRAM bandwidth, but by Hardware Instruction-Level Parallelism (ILP):
    • In standard scalar C++, computing \(w[n]\) requires \(w[n-1]\) from the previous iteration (a 4-cycle dependency on modern ARM/x86 pipelines), forcing the CPU to stall 75% of execution cycles.
    • Through Data Layout Interleaving (DLI), Legolas++ interleaves independent audio channels (\(P=4\) or \(P=8\)).
    • Every vector instruction calculates \(P\) channels concurrently with zero cross-lane dependencies, achieving 100% saturation of the hardware FMA execution pipes (8,287 Megasamples/sec on 8 CPU cores).

4. DepthwiseConv: MobileNet 3×3 Channelwise Stencil

  • Computational Work:
  • 3×3 spatial convolution per channel: 9 multiplies + 8 additions = \(17 \text{ FLOPs}\) (or \(18\) with bias).
  • Compulsory Traffic:
  • Input pixel read: 4 Bytes.
  • Output pixel write: 4 Bytes.
  • Filter weights: 9 floats per channel (permanently resident in L1 cache).
  • Total: \(Q = 8 \text{ Bytes/pixel}\).
  • Arithmetic Intensity: $\(I_{\text{Depthwise}} = \frac{18 \text{ FLOPs}}{8 \text{ Bytes}} = \mathbf{2.25 \text{ FLOP/Byte}}\)$
  • Optimum Ceilings:
  • With an intensity of \(2.25 \text{ F/B}\), this kernel sits directly at the knee of the cache roofline.
  • On an 8-core CPU, Legolas++ sustains 212.3 GFlops (against a theoretical multi-core AVX/NEON peak of ~250 GFlops), reaching 84.9% of the microarchitecture's peak computational capacity.

5. OptionPricing: Black-Scholes Crank-Nicolson PDE

  • Computational Work:
  • \(N_t = 50\) backward time steps.
  • At each step: explicit matrix-vector multiplication (RHS) + tridiagonal solve (Thomas).
  • Operations: \(\approx 18 \text{ FLOPs/grid point/step} \implies W = 900 \text{ FLOPs/point}\).
  • Working Set & Cache Residency:
  • For 16,384 option contracts with 128 spatial grid points: total working set is ~42 MB.
  • On modern AMD Ryzen / EPYC CPUs, the 32–64 MB L3 cache holds the entire working set across all 50 time steps.
  • Consequently, memory traffic drops to near zero after the initial load, boosting operational intensity to \(I \approx 18 \text{ FLOP/Byte}\).
  • Result: The CPU executes this workload entirely compute-bound in L3 cache at over 1.5 million option solves per second.

💡 Why Discrete GPUs Lose Here: An RTX 2060 SUPER has only 4 MB of L2 cache. The 42 MB problem cannot fit in on-chip cache and must be streamed back and forth from VRAM at every time step, making the GPU slower than the 12-thread CPU.


6. Reductions (squaredNorm & dot)

  • Computational Work:
  • squaredNorm: \(x_i \cdot x_i\) + accumulation = \(2 \text{ FLOPs/element}\).
  • dot: \(x_i \cdot y_i\) + accumulation = \(2 \text{ FLOPs/element}\).
  • Memory Traffic:
  • squaredNorm: Read 1 float = 4 Bytes \(\implies I = \mathbf{0.50 \text{ FLOP/Byte}}\).
  • dot: Read 2 floats = 8 Bytes \(\implies I = \mathbf{0.25 \text{ FLOP/Byte}}\).
  • Hardware Ceiling:
  • Purely streaming memory bandwidth bound.
  • On RTX 2060 SUPER (\(448 \text{ GB/s}\) rated GDDR6):
    • 16.7M floats (67.1 MB) processed in 0.200 ms: $\(\text{Effective Bandwidth} = \frac{67.1 \times 10^6 \text{ B}}{0.200 \times 10^{-3} \text{ s}} = \mathbf{335.5 \text{ GB/s}}\)$
    • Efficiency: Operates at 74.9% of theoretical peak VRAM bandwidth, matching dedicated vendor BLAS library levels.