Files
papers/lux-blockchain-scaling-laws/sections/03-measurements.tex
zeekay adfe7c8ad8 papers: lux-blockchain-scaling-laws — empirical Metal/WGSL/CPU NTT crossover + scaling laws
First measured scaling laws for post-quantum threshold consensus on
heterogeneous hardware. Real numbers from M1 Max with wgpu-native
29.0.0 (real WebGPU, not polyfill).

Main findings:
* CPU per-NTT cost flat at ~1.4 us across n=1..65536.
* Metal: 1.5 ms per dispatch, crosses CPU at n~3260, peaks 1.48x
  at n=65536.
* WGSL: 2.7 ms per dispatch, asymptotic per-op (1.58 us) HIGHER
  than CPU (1.38 us) — never crosses on M1 Max. Constraint:
  uint32-emulated u64 vs Metal's native u64.
* Pulsar production hot path n=2688 sits below both crossovers.
  Per-validator GPU acceleration unprofitable; aggregator-side
  multi-validator batching wins.

Three empirical scaling laws derived:
* L1 batch-size law: T_GPU/poly(n) = D/n + tau, crossover n* = D/(tau_CPU - tau_GPU).
* L2 validator-parallelism law: aggregator amortizes dispatch over k validators.
* L3 epoch-amortization law: workloads that batch at epoch boundary cross n* far earlier.

Sections (660 LoC of LaTeX):
  01-introduction       — claim summary + sharpest finding
  02-methodology        — bench harness, hardware, threats to validity
  03-measurements       — TSV-grade tables of NTT sweep + workload-level (ZAP, FHE, reshare)
  04-scaling-laws       — three theorems with fitted constants
  05-implications       — concrete posture for backend.Policy defaults
  06-honesty            — what was measured vs not (NVIDIA, Block-STM, DEX, e2e)
  99-conclusion         — production posture + queued workstreams

Data/ directory carries the raw TSV
(ntt-sweep-m1max-2026-05-04.tsv) emitted by the new
corona_lattice_ring_sweep_bench.

Honest scope: NVIDIA H100, Block-STM parallel EVM throughput, DEX
matching engine, and end-to-end consensus+EVM+DEX+FHE pipeline are
all queued for v0.3.0; not in this paper. Section 06 documents the
boundary.
2026-05-04 11:04:37 -07:00

148 lines
5.7 KiB
TeX
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
\section{Measurements}
\label{sec:measurements}
\subsection{NTT throughput sweep}
Table~\ref{tab:ntt-sweep} reports the per-polynomial NTT cost on
Apple M1 Max as a function of batch size $n$, for each of the three
backends (CPU scalar, Metal native, WGSL via wgpu-native). All three
produce byte-equal output by KAT construction.
\begin{table}[H]
\centering
\caption{NTT throughput by batch size, M1 Max, 2026-05-04. CPU is
\texttt{lattice\_ring::NTTStandard}; Metal is the
\texttt{canonical\_lattice\_ring.metal} kernel via metallib; WGSL is
the same kernel via wgpu-native 29.0.0 (real WebGPU, not polyfill).}
\label{tab:ntt-sweep}
\small
\begin{tabular}{rrrrrrrr}
\toprule
$n$ & CPU/poly & Metal/poly & WGSL/poly & CPU/batch & Metal/batch & WGSL/batch & iters \\
& (\textmu s) & (\textmu s) & (\textmu s) & (\textmu s) & (\textmu s) & (\textmu s) & \\
\midrule
1 & 1.36 & 1481.36 & 2731.92 & 1.36 & 1481.36 & 2731.92 & 2000 \\
4 & 1.34 & 505.23 & 692.78 & 5.35 & 2020.93 & 2771.13 & 2000 \\
16 & 1.36 & 186.58 & 172.38 & 21.76 & 2985.26 & 2758.04 & 2000 \\
64 & 1.36 & 89.51 & 56.31 & 86.75 & 5728.54 & 3604.07 & 2000 \\
256 & 1.35 & 23.55 & 15.29 & 346.59 & 6029.91 & 3914.81 & 1024 \\
1024 & 1.41 & 6.55 & 4.58 & 1445.17 & 6706.20 & 4688.74 & 256 \\
2688 & 1.38 & 3.20 & 2.65 & 3705.77 & 8588.15 & 7117.69 & 97 \\
4096 & 1.54 & 2.32 & 2.25 & 6328.00 & 9509.79 & 9215.33 & 64 \\
16384 & 1.49 & 1.19 & 1.68 & 24473.82 & 19518.02 & 27534.67 & 16 \\
65536 & 1.38 & 0.93 & 1.58 & 90652.03 & 61190.16 &103545.52 & 4 \\
\bottomrule
\end{tabular}
\end{table}
\subsection{Speedup curves}
The per-poly speedup of each GPU backend over CPU
(\texttt{CPU/poly} $\div$ \texttt{GPU/poly}) at each batch size:
\begin{table}[H]
\centering
\caption{GPU-vs-CPU speedup by batch size. Values $> 1.0$ mean GPU
beats CPU.}
\label{tab:speedup}
\small
\begin{tabular}{rcc}
\toprule
$n$ & Metal speedup & WGSL speedup \\
\midrule
1 & 0.001× & 0.000× \\
4 & 0.003× & 0.002× \\
16 & 0.007× & 0.008× \\
64 & 0.015× & 0.024× \\
256 & 0.057× & 0.089× \\
1024 & 0.215× & 0.308× \\
2688 & 0.431× & 0.521× \\
4096 & 0.665× & 0.687× \\
\textbf{16384} & \textbf{1.254×} & 0.889× \\
\textbf{65536} & \textbf{1.481×} & 0.875× \\
\bottomrule
\end{tabular}
\end{table}
\paragraph{Crossover.}
Metal crosses CPU between $n = 4{,}096$ ($0.67\times$) and $n = 16{,}384$
($1.25\times$). The crossover batch size is therefore in the range
$n^*_{\text{Metal}} \in (4{,}096, 16{,}384]$; a finer sweep would
pin the exact value. WGSL via wgpu-native does NOT cross CPU on this
hardware up to $n = 65{,}536$.
\paragraph{Production hot path.}
Pulsar's Round-1 dispatches $M \cdot N_\text{vec} \cdot \bar{D}
= 8 \cdot 7 \cdot 48 = 2{,}688$ NTTs per signature. At
$n = 2{,}688$:
\begin{itemize}[nosep]
\item CPU: $3.71$ ms total ($1.38$ \textmu s/poly).
\item Metal: $8.59$ ms total ($3.20$ \textmu s/poly, $2.32\times$ slower than CPU).
\item WGSL: $7.12$ ms total ($2.65$ \textmu s/poly, $1.92\times$ slower than CPU).
\end{itemize}
For one threshold signature, neither GPU lane wins on M1 Max. The
GPU lanes only become competitive when the consensus aggregator
batches signatures from multiple validators OR the workload itself
has natural parallelism beyond a single Round-1 mat-mul.
\subsection{Adjacent workload measurements}
The NTT sweep is the primitive-level data; the production-relevant
question is what happens at the workload level. Three direct
measurements taken from the same Lux Go test harnesses on the same
M1 Max box, 2026-05-04:
\begin{table}[H]
\centering
\caption{Workload-level Lux measurements, M1 Max, 2026-05-04.
\texttt{ZAPThroughput}: single-message PQ-TLS roundtrip latency.
\texttt{BootstrapSingle}: one TFHE bootstrap operation in
\texttt{luxfi/fhe} pure-Go.}
\label{tab:workload}
\small
\begin{tabular}{lrl}
\toprule
Workload & Wall-clock per op & Throughput \\
\midrule
ZAP message round-trip & 5.47 \textmu s & 183K msgs/sec \\
FHE bootstrap (single) & 119.9 ms & 8.34 ops/sec \\
Pulsar reshare $n{=}21$ & 12.67 s / 21 = 0.60 s & 1.65 ceremonies/sec \\
Pulsar reshare $n{=}64$ & 156.61 s / 64 = 2.45 s & 0.41 ceremonies/sec \\
Pulsar reshare $n{=}128$ & 1212.74 s / 128 = 9.47 s & 0.106 ceremonies/sec \\
\bottomrule
\end{tabular}
\end{table}
The reshare numbers come from
\texttt{threshold/protocols/lss/lss\_pulsar\_bench\_test.go}; ZAP
from \texttt{consensus/bench/zap\_throughput\_test.go}; FHE from
\texttt{fhe/bench\_crdt\_test.go::BenchmarkBootstrapSingle}.
\subsection{What is missing from this report}
Three workload categories that the introduction promises but the
v0.1.x measurements cannot cover honestly:
\begin{enumerate}[nosep,leftmargin=2em]
\item \textbf{Block-STM parallel EVM execution at GPU-native scale.}
\texttt{evm/core/parallel/blockstm.go} ships, but no benchmark
harness exists for it; nothing exercises the parallel execution
path under contention. A workload-level bench requires a synthetic
contention model (read/write set generator + version-conflict
distribution) that is not in tree.
\item \textbf{DEX matching engine throughput.}
\texttt{lx/dex} (the matching engine, accessed in this tree as the
symlink \texttt{$\sim$/work/lux/dex}) has no GPU surface today.
Reporting "DEX on GPU" numbers would require either porting the
match path to a compute kernel or measuring the existing CPU path
and labelling it as such; neither is in scope of this paper.
\item \textbf{End-to-end consensus + EVM + DEX + FHE pipeline.}
The Lux components ship as separate Go modules with no integrated
bench harness; building one is a v0.3.0 deliverable.
\end{enumerate}
\S\ref{sec:honesty} pins down exactly what we measured vs what is
extrapolated.