Skip to main content

GPU vs. Wafer-Scale

Cerebras eliminates the memory wall, then hits a completely different one.

analysis
advanced
Compare conventional GPU inference to Cerebras weight-streaming silicon. The binding constraint shifts from HBM bandwidth to injection bandwidth: a qualitative regime change, not only a quantitative improvement.

The Question

A fundamentally different architecture can change which wall binds. GPUs are weight-stationary: weights live in HBM (80 GiB at 3.35 TB/s on NVIDIA H100), and the bottleneck is HBM capacity and bandwidth. The Cerebras CS-3 (WSE-3) takes the opposite approach: it is activation-stationary, holding activations on 44 GiB of on-wafer SRAM (21 PB/s) and streaming weights from external MemoryX nodes (1.2 TB/s). Does this eliminate the memory wall, or does it move the wall somewhere else?

NotePrerequisites

Complete Tutorial 0: Hello, Roofline, Tutorial 1: The Memory Wall, and Tutorial 9: Sensitivity Analysis. This tutorial assumes familiarity with roofline analysis, binding constraints, and sensitivity-based investment decisions.

NoteLearning Objectives
  • Compare GPU and Cerebras architectures on the same workload using different solvers
  • Identify that the binding constraint shifts from HBM bandwidth to injection bandwidth
  • Compute the optimal batch size \(B^*\) where injection and compute overlap perfectly
  • Explain why this is a qualitative regime change, not only a quantitative speedup
TipBackground: Two Philosophies of Memory

Conventional GPUs use a two-level memory hierarchy: fast but small on-chip SRAM (registers, L1/L2 cache) and large but slower off-chip HBM. The central idea of wafer-scale computing is to make the chip large enough that SRAM alone can hold the working set. The Cerebras CS-3 (WSE-3) is an entire silicon wafer (46,225 \(\text{mm}^2\) vs. ~800 \(\text{mm}^2\) for an NVIDIA H100 die) with 44 GiB of on-wafer SRAM delivering 21 PB/s of bandwidth and 125 PFLOP/s of peak compute across 900,000 cores.

GPU (weight-stationary): Model weights live in HBM (80 GiB at 3.35 TB/s on NVIDIA H100). At each decode step, the entire model streams from HBM to the compute units. Activations are small and transient. Bottleneck: HBM capacity and bandwidth.

Cerebras WSE-3 (activation-stationary): Activations and KV-cache live on the 44 GiB of on-wafer SRAM. However, 44 GiB cannot hold a 350 GB model (GPT-3 (175B) at FP16), so weights must stream in layer-by-layer from external MemoryX nodes, dedicated memory boxes connected to the wafer via the SwarmX / MemoryX interconnect (1.2 TB/s). Bottleneck: injection bandwidth from MemoryX.

Same model, same math, completely different performance physics.


1. Setup

import mlsysim
from mlsysim.solvers import SingleNodeModel
from mlsysim.solvers import WeightStreamingModel, SensitivitySolver

2. GPU Baseline: H100 Inference

The workload is GPT-3 (175B) (175B parameters across 96 layers), a model large enough that architectural differences in how weights reach compute become the dominant factor. At batch size 1, each decode step must stream all 350 GB of FP16 weights.

from mlsysim.solvers import SingleNodeModel
from mlsysim.solvers import WeightStreamingModel, SensitivitySolver
from mlsysim.show import table, info, banner

model = mlsysim.Models.Language.GPT3
gpu_hw = mlsysim.Hardware.Cloud.H100

gpu_solver = SingleNodeModel()
gpu_result = gpu_solver.solve(
    model=model, hardware=gpu_hw,
    batch_size=1, precision="fp16"
)

info("GPU Baseline",
     Model=f"{model.name} ({model.parameters.to('Bparam').magnitude:.0f}B)",
     Hardware=gpu_hw.name,
     Bottleneck=gpu_result.bottleneck,
     Latency=gpu_result.latency.to('ms'),
     HBM_BW=gpu_hw.memory.bandwidth.to('TB/s'),
     Peak_FLOPS=gpu_hw.compute.peak_flops.to('TFLOPs/s'))
── GPU Baseline ────────────────────────────
Model:       GPT-3 (175B) (175B)
Hardware:    NVIDIA H100
Bottleneck:  Memory
Latency:     6,016.6 ms
HBM BW:      3.35 TB/s
Peak FLOPS:  989 TFLOPs/s

At batch size 1, GPT-3 (175B) performs 2 FLOPs per parameter per token and must stream 175B parameters (350 GB at FP16). Its arithmetic intensity is 0.91 FLOP/byte, far below the NVIDIA H100 ridge point of 295.2 FLOP/byte. Because 350 GB exceeds a single NVIDIA H100’s 80 GiB HBM capacity, single-device execution spills over PCIe (64 GB/s) for a latency of 6,016.6 ms, and even across a multi-GPU node where weights fit in 3.35 TB/s HBM, pure weight transfer requires 104.5 ms while the 989 TFLOP/s compute units take 0.71 ms.


3. Cerebras Path: Weight Streaming on WSE-3

The next cell analyzes the same model on the Cerebras CS-3 (WSE-3). Instead of loading weights from HBM, the WSE-3 streams them from MemoryX nodes over the 1.2 TB/s SwarmX / MemoryX interconnect.

ws_hw = mlsysim.Hardware.Cloud.Cerebras_CS3
ws_solver = WeightStreamingModel()

ws_result = ws_solver.solve(
    model=model, hardware=ws_hw,
    seq_len=2048, batch_size=1, precision="fp16"
)

info("Cerebras WSE-3",
     Hardware=ws_hw.name,
     Feasible=ws_result.feasible,
     Bottleneck=ws_result.bottleneck,
     Throughput=f"{ws_result.throughput_tokens_per_sec:.1f} tokens/sec",
     Layer_compute_time=ws_result.layer_compute_time.to('ms'),
     Layer_injection_time=ws_result.layer_injection_time.to('ms'),
     Optimal_batch_size=ws_result.optimal_batch_size,
     SRAM_utilization=f"{ws_result.wafer_memory_utilization:.1%}")
── Cerebras WSE-3 ──────────────────────────
Hardware:              Cerebras CS-3 (WSE-3)
Feasible:              True
Bottleneck:            Interconnect-Bandwidth-Bound
Throughput:            3.4 tokens/sec
Layer compute time:    1.06e-03 ms
Layer injection time:  3.04 ms
Optimal batch size:    52083
SRAM utilization:      22.5%

The WSE-3 reports two times per layer: how long the wafer takes to compute one layer (1.06 µs at 125 PFLOP/s), and how long it takes to inject that layer’s weights from MemoryX (3.04 ms at 1.2 TB/s). The bottleneck is whichever is slower: at batch size 1, injection takes 2,871× longer than compute.


4. Side-by-Side: Where the Wall Shifts

gpu_lat_ms = gpu_result.latency.to('ms').magnitude
# Cerebras total decode: max(inject, compute) per layer * num_layers
ws_layer_time = max(
    ws_result.layer_injection_time.to('ms').magnitude,
    ws_result.layer_compute_time.to('ms').magnitude
)
ws_total_ms = ws_layer_time * model.layers
speedup = gpu_lat_ms / ws_total_ms if ws_total_ms > 0 else 0

table(
    ["Metric", "H100 (GPU)", "CS-3 (WSE)"],
    [
        ["Bottleneck", gpu_result.bottleneck, ws_result.bottleneck],
        ["Total decode time (ms)", f"{gpu_lat_ms:.2f}", f"{ws_total_ms:.2f}"],
        ["Speedup", "1.0x", f"{speedup:.1f}x"],
        ["Optimal batch B*", "N/A", ws_result.optimal_batch_size],
    ]
)
Metric                  H100 (GPU)                    CS-3 (WSE)
────────────────────────────────────────────────────────────────
Bottleneck                  Memory  Interconnect-Bandwidth-Bound
Total decode time (ms)     6016.60                        291.67
Speedup                       1.0x                         20.6x
Optimal batch B*               N/A                         52083

The GPU and WSE-3 hit fundamentally different walls:

  • GPU (NVIDIA H100): Limited by HBM capacity (80 GiB) and HBM bandwidth (3.35 TB/s)
  • WSE-3 (Cerebras CS-3 (WSE-3)): Limited by MemoryX injection bandwidth (1.2 TB/s, requiring 291.67 ms across 96 layers)

The optimization strategies therefore differ completely. On the GPU, optimization reduces the bytes loaded (quantization, smaller models, tensor parallelism). On the WSE-3, it overlaps injection with compute by increasing batch size toward \(B^* = 52\,083\).

ImportantKey Insight

The binding constraint is not a property of the model but a property of the model-architecture pair. GPUs are bound by HBM capacity and bandwidth (3.35 TB/s on NVIDIA H100). Cerebras CS-3 (WSE-3) eliminates the HBM wall entirely (activations stay in 44 GiB of 21 PB/s on-wafer SRAM) and replaces it with an injection bandwidth wall (1.2 TB/s from MemoryX). This is a qualitative regime change: the wall shifted, it did not disappear. When evaluating any novel architecture, the question is not “is it faster?” but “which wall does it move, and what new wall does it create?”


5. The SRAM Ceiling: Finding B*

The WSE-3 has a distinct optimization knob: batch size controls how much compute is performed per weight injection. At the theoretical balance point \(B^* = 52\,083\), per-layer compute time matches the 3.04 ms injection time. Activations and KV-cache, however, must fit in 44 GiB of on-wafer SRAM, and that limit is the SRAM ceiling.

rows = []
for batch in [1, 2, 4, 8, 16, 32, 64, 128]:
    r = ws_solver.solve(
        model=model, hardware=ws_hw,
        seq_len=2048, batch_size=batch, precision="fp16"
    )
    rows.append([
        batch, r.bottleneck,
        f"{r.throughput_tokens_per_sec:.1f}/s",
        f"{r.wafer_memory_utilization:.1%}",
        "YES" if r.feasible else "OOM"
    ])

table(["Batch", "Bottleneck", "Throughput", "SRAM Util", "Feasible"], rows)
Batch                    Bottleneck  Throughput  SRAM Util  Feasible
────────────────────────────────────────────────────────────────────
1      Interconnect-Bandwidth-Bound       3.4/s      22.5%       YES
2      Interconnect-Bandwidth-Bound       6.9/s      45.0%       YES
4      Interconnect-Bandwidth-Bound      13.7/s      90.0%       YES
8      Interconnect-Bandwidth-Bound       0.0/s     180.0%       OOM
16     Interconnect-Bandwidth-Bound       0.0/s     360.0%       OOM
32     Interconnect-Bandwidth-Bound       0.0/s     720.0%       OOM
64     Interconnect-Bandwidth-Bound       0.0/s    1440.0%       OOM
128    Interconnect-Bandwidth-Bound       0.0/s    2880.0%       OOM

At sequence length 2048, a single request consumes 22.5% of the 44 GiB on-wafer SRAM (3.4 tokens/s). Increasing batch size to 4 raises throughput to 13.7 tokens/s at 90.0% SRAM utilization, and at batch size 8 the KV-cache demand reaches 180.0% of wafer SRAM (OOM), long before reaching \(B^* = 52\,083\).


6. Sensitivity Confirmation: Different Walls, Different Levers

Running SensitivitySolver on NVIDIA H100 confirms how the GPU walls behave: for GPT-3 (175B) (350 GB), single-device execution binds on memory_capacity, and for an HBM-resident model (Llama-3.1-8B), it binds on memory_bandwidth (-0.0856).

sens_solver = SensitivitySolver()
gpu_sens = sens_solver.solve(
    model=mlsysim.Models.Language.Llama3_8B, hardware=gpu_hw, precision="fp16"
)

banner(f"GPU Sensitivity ({gpu_hw.name}, HBM-Resident {mlsysim.Models.Language.Llama3_8B.name})")
info(Baseline_latency=gpu_sens.baseline_latency.to('ms'),
     Binding_constraint=gpu_sens.binding_constraint)

sens_rows = [[param, f"{val:+.4f}"] for param, val in gpu_sens.sensitivities.items()]
table(["Parameter", "Sensitivity"], sens_rows)

banner("Cerebras WSE-3")
info(Binding_constraint="injection bandwidth (MemoryX -> wafer)",
     Optimization_lever="increase batch size within on-wafer SRAM capacity")

print()
print("Different architectures -> different walls -> different strategies.")

=== GPU Sensitivity (NVIDIA H100, HBM-Resident Llama-3.1-8B) ===
Baseline latency:    5.60 ms
Binding constraint:  memory_bandwidth
Parameter         Sensitivity
─────────────────────────────
peak_flops            +0.0000
memory_bandwidth      -0.0856
memory_capacity       +0.0000

=== Cerebras WSE-3 ===
Binding constraint:  injection bandwidth (MemoryX -> wafer)
Optimization lever:  increase batch size within on-wafer SRAM capacity

Different architectures -> different walls -> different strategies.
WarningThe Deeper Lesson

When evaluating novel architectures (wafer-scale, photonic, analog, neuromorphic), the diagnostic question is not “Is it faster?” but “Which wall does it move, and what new wall does it create?” Every architecture eliminates one bottleneck by introducing another.


Next Steps

Back to top