% The Parameter-Sweep Roofline: a closed-form batch-size amortization law and a
% machine-invariant CPU analog. Controlled, seeded study. Every number in this
% manuscript comes from results/results.json (seed 0), produced by
% scripts/run_all.py. NO GPU is measured; all numbers are closed-form model
% values or deterministic operation counts.
% Primary arXiv category: cs.PF (Performance).
% Cross-list: cs.DC (Distributed, Parallel, and Cluster Computing).
\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{amsmath,amssymb}
\usepackage{booktabs}
\usepackage[numbers,round]{natbib}
\usepackage{microtype}
\usepackage[hidelinks]{hyperref}
\setlength{\emergencystretch}{2em}

\newcommand{\code}[1]{\texttt{#1}}

\title{The Parameter-Sweep Roofline:\\
A Closed-Form Batch-Size Amortization Law\\
and a Machine-Invariant CPU Analog}
\author{Eugen Soloviov}
\date{July 2026}

\begin{document}
\maketitle

\begin{abstract}
A parameter sweep dispatched one combination at a time re-pays a fixed per-call
overhead --- kernel launch plus a host/device-style transfer of the whole
series --- on every combination; batched into one call, that overhead is paid
once and amortized. This gives an elementary closed-form law for the speedup of
batched over per-call execution as a function of batch size $B$:
$S(B)=B(O+b)/(O+bB)$, where $O$ is the fixed overhead and $b$ the marginal work
per combination. The law is monotone increasing, starts at $S(1)=1$, and
saturates toward a ceiling $1+O/b$ that a finite batch never reaches; it is
governed by a batch-space \emph{ridge} $B_{\mathrm{ridge}}=O/b$ (fixed overhead
equals batched marginal) and a \emph{compute-bound crossover}
$B^\star(f)=fO/[b(1-f)]$ (the batch at which $S$ reaches a fraction $f$ of the
ceiling). On a seeded instance calibrated from a real workload
($O=3{,}605{,}000$, $b=150{,}000$, so $O/b=24.03$), the law predicts a speedup
that climbs from $S(1)=1.00$ to $S(61)=17.96$ toward an asymptote of $25.03$,
with the ridge at $B=24.03$ and the $90\%$ compute-bound crossover at
$B\approx216$; the fixed overhead falls from $96.0\%$ of the batched cost at
$B=1$ to $28.3\%$ at $B=61$. We then show the same law is not an abstraction: a
real, seeded NumPy weighted-moving-average sweep, run batched versus per-call
with work measured as a \emph{deterministic operation count} rather than
wall-clock time, reproduces $S(B)$ exactly, produces bit-identical numerical
output on both paths, and, when the law is fit back out of the op-count curve,
recovers $O/b=24.03$ and the asymptote $25.03$ with a maximum relative residual
of exactly $0$. Because work is an operation count, the analog is invariant to
the machine it runs on. \textbf{We measure no GPU and no wall-clock time.} The
device speedups of the accompanying blog post ($54.5\times$ to $359.6\times$ on
an Apple M2 Max) are prior engineering measurements and are \emph{not}
reproduced here; the contribution is strictly the amortization law and its
machine-invariant realization. This study accompanies a
\href{https://marketmaker.cc}{marketmaker.cc} blog post.
\end{abstract}

\section{Introduction}
\label{sec:intro}

The seductive pitch of GPU-accelerated backtesting is ``one big matrix'': stack
every parameter combination into a tensor and let the hardware eat it. The
awkward fact underneath the pitch is that the same hardware, handed one
combination at a time, is often \emph{slower} than the CPU it was meant to
replace. The speedup of a batched processor over a per-call one is not a
property of the chip; it is a function of how much work you hand it per call.

The reason is a fixed cost. Every dispatch pays a roughly constant price ---
launch the kernel, move the input across the (unified, but not free) memory
boundary, move the result back --- that does not shrink when the call does less
work. Run a sweep of $B$ combinations one per call and you pay that overhead $B$
times; batch the same $B$ into a single call and you pay it once. A small sweep
cannot amortize the overhead, so it sits in the regime where fixed cost
dominates and the accelerator barely earns its keep; a large sweep amortizes the
overhead across many combinations and approaches the true marginal-cost ratio.

This paper isolates that amortization into its simplest exact form. We model the
cost of running $B$ combinations two ways --- batched (fixed overhead $O$ paid
once, plus marginal work $b$ per combination) and per-call (the same overhead
re-paid on every combination) --- and take the ratio. The result is a one-line
closed-form law, $S(B)=B(O+b)/(O+bB)$, whose entire behavior is set by the
single dimensionless number $O/b$: it rises monotonically from $S(1)=1$,
saturates toward $1+O/b$, has its half-way ``ridge'' at $B=O/b$, and reaches any
target fraction $f$ of its ceiling at a batch $B^\star(f)=fO/[b(1-f)]$ that is
independent of the marginal work.

We then make the law concrete and, crucially, \emph{machine-invariant}. We run a
real, seeded NumPy weighted-moving-average (WMA) sweep two ways over the same
synthetic series --- batched and one-per-call --- but measure work as a
deterministic \emph{operation count} rather than wall-clock seconds. The per-call
path re-does the fixed launch-plus-transfer charge on every combination; the
batched path does it once. Because the reported quantity is an integer op count,
the whole curve is bit-reproducible run-to-run and machine-to-machine, and it
realizes $S(B)$ exactly. Both paths compute the identical WMAs and return
bit-identical numbers; only the overhead accounting differs. Fitting the law back
out of the op-count curve recovers its parameters with zero residual: the analog
does not merely resemble the law, it \emph{is} the law.

\paragraph{Scope and honesty constraints.} Two constraints bound the claims, and
they are load-bearing. First, we measure \emph{no} GPU and \emph{no} wall-clock
time. Every number in this paper is either a closed-form value of the model or a
deterministic operation count from the seeded NumPy sweep; there are no timings
and no hardware measurements. Second, the device speedups quoted in the
accompanying blog post --- a GPU-over-CPU curve rising from $54.5\times$ at one
combination per call to $359.6\times$ at $61$ on an Apple M2 Max, the
$3.2\times$/$6.2\times$ hardware ratios, and the $167\times=27\times\cdot6.2\times$
algorithm/hardware decomposition --- are \emph{prior engineering measurements}
that this paper does \emph{not} reproduce and does \emph{not} claim. What is
reproduced here is the underlying \emph{law} those numbers obey (a speedup that
rises with batch size and saturates as fixed overhead is amortized), together
with a machine-invariant op-counted realization of it. All results derive from
one seeded run of one public harness (\code{scripts/run\_all.py}), with the
model and the analog in \code{scripts/roofline.py}.

\section{The amortization law}
\label{sec:law}

\paragraph{Two cost models.} Consider a sweep of $B$ parameter combinations over
one series. Each combination requires the same marginal work $b$. Each
\emph{call} additionally pays a fixed overhead $O$ --- the launch charge plus the
transfer of the series across the memory boundary --- that is independent of how
many combinations the call computes. Batching all $B$ combinations into one call
pays $O$ once; dispatching them one per call re-pays $O$ on every combination:
\begin{equation}
\label{eq:costs}
T_{\mathrm{batched}}(B) = O + bB, \qquad
T_{\mathrm{percall}}(B) = B\,(O + b).
\end{equation}
Both paths do the identical useful work $bB$ in total; they differ only in how
often the fixed overhead is paid. (In a slightly more general form
$T_{\mathrm{percall}}=B(O+a)$ one writes the per-call marginal as $a$; here each
per-call combination re-pays the full fixed cost $O$ on top of the shared
marginal, so $a=b$, and we use that throughout.)

\paragraph{The speedup.} The speedup of batched over per-call execution is the
ratio of the two costs:
\begin{equation}
\label{eq:speedup}
S(B) = \frac{T_{\mathrm{percall}}(B)}{T_{\mathrm{batched}}(B)}
     = \frac{B\,(O + b)}{O + bB}.
\end{equation}
For $O>0$ and $b>0$ this is monotone increasing in $B$, with $S(1)=1$ (a single
combination cannot be amortized against anything) and a decelerating rise. It is
the parameter-sweep instance of Amdahl's law~\citep{amdahl1967}: the fixed
overhead $O$ is a serial cost that a batch dilutes but never deletes.

\paragraph{The saturation ceiling.} As $B\to\infty$ the fixed overhead is spread
over infinitely many combinations and the speedup approaches
\begin{equation}
\label{eq:asymptote}
\lim_{B\to\infty} S(B) = \frac{O+b}{b} = 1 + \frac{O}{b},
\end{equation}
a ceiling the curve rises toward but --- for any finite $B$ --- never reaches.
The fraction of this ceiling attained at batch $B$ is $S(B)/(1+O/b)$.

\paragraph{The batch ridge.} The roofline model~\citep{williams2009roofline}
locates a \emph{ridge point} where a workload stops being overhead-bound and
becomes compute-bound. In batch space that ridge is the batch at which the
batched path's fixed overhead equals its marginal compute for the whole batch,
$O = b\,B$:
\begin{equation}
\label{eq:ridge}
B_{\mathrm{ridge}} = \frac{O}{b}.
\end{equation}
Past the ridge, the batched cost $O+bB$ is dominated by the $bB$ marginal rather
than by the fixed $O$: the call is compute-bound. Note that the ridge and the
asymptote differ by exactly one, $1+O/b = 1 + B_{\mathrm{ridge}}$.

\paragraph{The compute-bound crossover.} How wide must the sweep be to reach a
chosen fraction $f$ of the ceiling? Setting $S(B)=f\,(1+O/b)$ in
Eq.~\eqref{eq:speedup} and solving,
\begin{equation}
\label{eq:crossover}
\frac{B(O+b)}{O+bB} = f\,\frac{O+b}{b}
\;\Longrightarrow\;
bB = f\,(O + bB)
\;\Longrightarrow\;
B^\star(f) = \frac{f\,O}{b\,(1-f)}.
\end{equation}
The marginal $b$ appears only through $O/b$, and $a$ (had we kept it) cancels
entirely: the crossover is a \emph{pure overhead-amortization threshold},
determined by the overhead-to-marginal ratio and the target fraction alone. We
report it for $f=0.90$ and $f=0.95$.

\paragraph{The two-term decomposition.} The batched cost $O+bB$ splits cleanly
into a fixed-overhead term and a useful-compute term, and their fractions are
\begin{equation}
\label{eq:decomp}
\phi_{\mathrm{ovh}}(B) = \frac{O}{O+bB}, \qquad
\phi_{\mathrm{use}}(B) = \frac{bB}{O+bB} = \frac{S(B)}{1+O/b},
\end{equation}
with $\phi_{\mathrm{ovh}}+\phi_{\mathrm{use}}=1$. As $B$ grows the overhead
fraction falls and the useful fraction rises toward one: this is the
two-ceiling roofline picture --- overhead-bound on the left, compute-bound on
the right --- drawn along the batch axis. The per-call path, by contrast, re-pays
$O$ on every combination, so its overhead fraction $O/(O+b)$ is constant in $B$.

\section{The CPU analog: operation-count work}
\label{sec:analog}

The law of Section~\ref{sec:law} is an identity; to show it governs real work we
instantiate it in a genuine computation --- but one whose ``cost'' is a
\emph{deterministic operation count}, not a timing. This buys two things: the
result is bit-reproducible on any machine (no wall-clock noise, no hardware
dependence), and the accounting of fixed versus marginal work is exact rather
than fitted.

\paragraph{The workload.} We sweep window lengths of a linearly weighted moving
average over a single seeded synthetic price series. The series is a geometric
random walk of $n=150{,}000$ bars from \code{numpy.random.default\_rng(0)}
(initial price $30{,}000$, per-bar log-return standard deviation
$5\times10^{-4}$); each combination convolves the series with a normalized linear
kernel. A batch of size $B$ uses $B$ distinct window lengths.

\paragraph{The op-count model of overhead and marginal.} Each call pays a fixed
overhead: a launch charge plus a transfer of the whole series across an
(analog) memory boundary,
\begin{equation}
\label{eq:opsO}
O_{\mathrm{ops}}(n) = L_{\mathrm{launch}} + \tau\, n
= 5000 + 24 \cdot 150{,}000 = 3{,}605{,}000,
\end{equation}
with $L_{\mathrm{launch}}=5000$ the dispatch charge and $\tau=24$ the transfer
cost per series element. This is independent of how many combinations the call
computes --- exactly the quantity a batch amortizes. Each combination's marginal
useful work is one windowed pass over the series,
\begin{equation}
\label{eq:opsb}
b_{\mathrm{ops}}(n) = n = 150{,}000,
\end{equation}
a constant $n$ ops per combination. (Keeping the marginal constant is a modelling
choice, not an approximation: it makes the batched marginal exact, so the
op-count curve equals the closed-form law rather than approximating it.)

\paragraph{Batched versus per-call, and their equivalence.} The batched sweep
pays $O_{\mathrm{ops}}$ once and accumulates $b_{\mathrm{ops}}$ per combination;
the per-call sweep re-pays $O_{\mathrm{ops}}$ on every combination:
\begin{equation}
\label{eq:opscosts}
\mathrm{total}_{\mathrm{batched}}(B) = O_{\mathrm{ops}} + b_{\mathrm{ops}}B,
\qquad
\mathrm{total}_{\mathrm{percall}}(B) = B\,(O_{\mathrm{ops}} + b_{\mathrm{ops}}),
\end{equation}
and the analog speedup is their ratio, which by construction equals
Eq.~\eqref{eq:speedup} with $O=O_{\mathrm{ops}}$, $b=b_{\mathrm{ops}}$.
Critically, both paths run the \emph{same} NumPy convolutions over the same data
and accumulate the same deterministic checksum of the outputs: they produce
\emph{bit-identical} numerical results. Batching changes only the overhead
accounting, never the arithmetic --- so the speedup is a pure amortization
effect, not a numerical artifact. Across the whole batch grid the equivalence
check holds (\code{all\_paths\_equivalent}=\,true).

\paragraph{Fitting the law back out.} Finally we recover the law's parameters
from the analog's op-count speedup curve by least squares (normalizing $b=1$,
since $S$ is invariant to a common scale of $O,a,b$) and check that the fitted
law reproduces the curve. The fit is exact: it returns $O/b=24.03$, asymptote
$1+O/b=25.03$, and a maximum relative residual of exactly $0$. Because the
marginal is a genuine constant, there is no residual to leave --- the analog is a
faithful realization of the closed form, not a noisy sample of it.

\section{Results}
\label{sec:results}

All numbers below come from one seeded run (seed $0$, Python 3.12.3, NumPy 2.5.1)
of \code{scripts/run\_all.py}, calibrated to $O=3{,}605{,}000$,
$b=150{,}000$ (so $O/b=24.03$), over the batch grid $B\in\{1,2,4,8,16,32,61\}$
that mirrors the shape of the blog's sweep.

\paragraph{The speedup curve and its landmarks.} Table~\ref{tab:curve} reports
the closed-form speedup $S(B)$ and the fraction of the asymptote it attains at
each batch. The curve climbs from $S(1)=1.00$ (a single combination amortizes
nothing) to $S(61)=17.96$, which is $71.7\%$ of the way to the ceiling
$1+O/b=25.03$. The batch ridge sits at $B_{\mathrm{ridge}}=O/b=24.03$; the
compute-bound crossover is $B^\star(0.90)=216.3$ and $B^\star(0.95)=456.63$ ---
i.e.\ reaching $90\%$ of the ceiling needs a batch of $216$, and $95\%$ needs
$457$, both far to the right of the $61$-wide grid. The grid lives on the rising
overhead-amortized part of the curve, well left of saturation, which is exactly
the regime a modest sweep occupies.

\begin{table}[t]
\centering
\caption{The closed-form amortization law $S(B)=B(O+b)/(O+bB)$ over the batch
grid ($O=3{,}605{,}000$, $b=150{,}000$, $O/b=24.03$, seed $0$). The speedup rises
monotonically from $1.00$ toward the asymptote $1+O/b=25.03$; the fraction of the
ceiling attained is $S(B)/(1+O/b)$. The ridge is at $B=24.03$ and the $90\%$
crossover at $B\approx216$, so the $B\le61$ grid is on the rising, overhead-bound
part of the curve.}
\label{tab:curve}
\begin{tabular}{rrr}
\toprule
Batch $B$ & Speedup $S(B)$ & Fraction of asymptote \\
\midrule
$1$  & $1.000$   & $0.03995$ \\
$2$  & $1.9232$  & $0.07682$ \\
$4$  & $3.5719$  & $0.1427$  \\
$8$  & $6.2518$  & $0.2497$  \\
$16$ & $10.005$  & $0.3997$  \\
$32$ & $14.296$  & $0.5711$  \\
$61$ & $17.958$  & $0.7174$  \\
\bottomrule
\end{tabular}
\end{table}

\paragraph{The CPU analog reproduces the law exactly.} Table~\ref{tab:analog}
reports the op-counted analog. Each row shows the total batched op count
$O+bB$, the total per-call op count $B(O+b)$, and their ratio --- the analog
speedup --- alongside the useful fraction of the batched path. The analog
speedup equals the model speedup of Table~\ref{tab:curve} to every printed
digit ($S(1)=1.00$, $S(61)=17.96$), the two paths are numerically equivalent at
every batch, and the batched useful fraction rises from $3.99\%$ at $B=1$ to
$71.7\%$ at $B=61$ (identical, as Eq.~\eqref{eq:decomp} requires, to the
fraction-of-asymptote column of Table~\ref{tab:curve}). The per-call path's
overhead never amortizes: its total is $B$ copies of the single-call cost.

\begin{table}[t]
\centering
\caption{The CPU analog: a seeded NumPy WMA sweep run batched versus per-call,
work measured as a deterministic operation count ($O_{\mathrm{ops}}=3{,}605{,}000$,
$b_{\mathrm{ops}}=150{,}000$, seed $0$). ``Batched ops'' is $O+bB$, ``per-call
ops'' is $B(O+b)$, and their ratio is the analog speedup --- equal to the
closed-form $S(B)$ of Table~\ref{tab:curve}. Both paths produce bit-identical
numerical output (\emph{equiv.}).}
\label{tab:analog}
\begin{tabular}{rrrrrr}
\toprule
Batch $B$ & Batched ops & Per-call ops & Analog $S(B)$ & Useful frac.\ (batched) & Equiv. \\
\midrule
$1$  & $3{,}755{,}000$  & $3{,}755{,}000$   & $1.000$  & $0.03995$ & yes \\
$2$  & $3{,}905{,}000$  & $7{,}510{,}000$   & $1.9232$ & $0.07682$ & yes \\
$4$  & $4{,}205{,}000$  & $15{,}020{,}000$  & $3.5719$ & $0.1427$  & yes \\
$8$  & $4{,}805{,}000$  & $30{,}040{,}000$  & $6.2518$ & $0.2497$  & yes \\
$16$ & $6{,}005{,}000$  & $60{,}080{,}000$  & $10.005$ & $0.3997$  & yes \\
$32$ & $8{,}405{,}000$  & $120{,}160{,}000$ & $14.296$ & $0.5711$  & yes \\
$61$ & $12{,}755{,}000$ & $229{,}055{,}000$ & $17.958$ & $0.7174$  & yes \\
\bottomrule
\end{tabular}
\end{table}

\paragraph{The overhead/compute decomposition.} Table~\ref{tab:decomp} splits the
batched cost into its two roofline terms per batch. The fixed overhead, which is
$96.0\%$ of the batched cost at $B=1$, is amortized down to $28.3\%$ at $B=61$;
the useful-compute fraction rises correspondingly from $3.99\%$ to $71.7\%$. The
per-call path's overhead fraction stays pinned at $96.0\%$ for every batch,
because it re-pays $O$ on every combination and so never crosses out of the
overhead-bound regime. This is the mechanism of the whole paper in one table:
batching moves the workload rightward along the roofline; per-call keeps it
stuck on the left.

\begin{table}[t]
\centering
\caption{Overhead/compute decomposition of the batched path versus the pinned
per-call path (seed $0$). As $B$ grows the batched overhead fraction
$O/(O+bB)$ falls from $0.9601$ to $0.2826$ and the useful fraction rises from
$0.03995$ to $0.7174$; the per-call overhead fraction $O/(O+b)=0.9601$ is
constant.}
\label{tab:decomp}
\begin{tabular}{rrrr}
\toprule
Batch $B$ & Overhead frac.\ (batched) & Useful frac.\ (batched) & Overhead frac.\ (per-call) \\
\midrule
$1$  & $0.9601$ & $0.03995$ & $0.9601$ \\
$2$  & $0.9232$ & $0.07682$ & $0.9601$ \\
$4$  & $0.8573$ & $0.1427$  & $0.9601$ \\
$8$  & $0.7503$ & $0.2497$  & $0.9601$ \\
$16$ & $0.6003$ & $0.3997$  & $0.9601$ \\
$32$ & $0.4289$ & $0.5711$  & $0.9601$ \\
$61$ & $0.2826$ & $0.7174$  & $0.9601$ \\
\bottomrule
\end{tabular}
\end{table}

\paragraph{Fit-back verification.} Table~\ref{tab:fit} closes the loop: fitting
the closed-form law to the analog's op-count speedup curve recovers the ridge
$O/b=24.03$ and the asymptote $1+O/b=25.03$ (fitted with $b$ normalized to $1$,
so $O=24.03$, $a=1.00$), with a maximum relative residual of exactly $0$. The
analog does not approximate the law; it is the law, realized to machine
precision. The zero residual is a direct consequence of the constant marginal in
Eq.~\eqref{eq:opsb}: there is no curvature for the fit to miss.

\begin{table}[t]
\centering
\caption{Fit-back verification: the closed-form law recovered from the analog's
op-count speedup curve ($b$ normalized to $1$, seed $0$). The recovered ridge and
asymptote match the calibration exactly and the fit is residual-free.}
\label{tab:fit}
\begin{tabular}{lr}
\toprule
Fitted quantity & Value \\
\midrule
fitted $O$ (with $b=1$)          & $24.033$ \\
fitted $a$ (with $b=1$)          & $1.000$  \\
fitted asymptote $1+O/b$         & $25.033$ \\
fitted ridge $O/b$               & $24.033$ \\
max relative residual            & $0$ \\
\bottomrule
\end{tabular}
\end{table}

\section{Discussion}
\label{sec:discussion}

\paragraph{The speedup is a curve, not a number.} The single most useful thing
the law says is that ``how much faster is batched than per-call'' has no scalar
answer: it is $S(B)$, a function of batch size. Quoting one point on that curve
--- the small-batch number or the large-batch number --- and hiding the rest is
not measuring the amortization, it is choosing a headline. The blog's device
curve rising from $54.5\times$ to $359.6\times$ (prior work, not reproduced here)
is the empirical shadow of exactly this $S(B)$; the law explains why any such
measurement \emph{must} rise with batch size, whatever the hardware.

\paragraph{Amdahl and the roofline, in batch space.} The law is two classical
results wearing a batch-size coordinate. The fixed overhead $O$ is Amdahl's
serial fraction~\citep{amdahl1967}: it can be amortized across a batch but never
removed, which is why $S(B)$ saturates at $1+O/b$ rather than growing without
bound. And the ridge $B_{\mathrm{ridge}}=O/b$ is the roofline's ridge
point~\citep{williams2009roofline} cast into batch space: left of it the batched
call is overhead-bound (the flat $O$ dominates), right of it compute-bound (the
$bB$ marginal dominates). The two-term decomposition of Table~\ref{tab:decomp} is
the roofline's memory-bound/compute-bound split drawn along $B$.

\paragraph{A decision rule.} The crossover $B^\star(f)=fO/[b(1-f)]$ turns the law
into an actionable threshold. It says: to reach $90\%$ of the achievable
amortization on this calibration you need a batch of $216$; a sweep of a few
dozen combinations lives far to the left of that, deep in the overhead-bound
regime, where most of the cost is still fixed launch-and-transfer. The lever is
either a wider batch (move rightward on the curve) or richer per-combination work
(raise $b$, which lowers the ridge $O/b$ and pulls the crossover left).

\paragraph{Why an operation count, not a timing.} Reporting work as a
deterministic op count, rather than seconds, is what makes the analog
\emph{machine-invariant}: the same seed produces the same curve on any CPU, with
no warm-up, no thermal drift, no scheduler noise, and no dependence on a
particular device. The cost is that the analog demonstrates the \emph{law}, not a
\emph{speed}: it shows that batched-versus-per-call amortization obeys $S(B)$
exactly, without asserting how fast any real processor runs. That trade --- give
up the timing to gain reproducibility and portability --- is the deliberate
design of this study.

\section{Limitations}
\label{sec:limitations}

\begin{itemize}
\item \textbf{A model and an analog, not a GPU measurement.} We measure no GPU
  and no wall-clock time. Every number is a closed-form value of $S(B)$ or a
  deterministic operation count from the seeded NumPy sweep. The study
  establishes the amortization \emph{law} and a machine-invariant realization of
  it; it does not measure any device's speed.
\item \textbf{Prior GPU numbers are not reproduced.} The accompanying blog's
  device speedups --- $54.5\times$ to $359.6\times$ on an Apple M2 Max, the
  $3.2\times$ and $6.2\times$ hardware ratios, the
  $167\times=27\times\cdot6.2\times$ algorithm/hardware decomposition --- are
  prior engineering measurements on specific hardware. They are cited only to
  motivate the law and are explicitly \emph{not} reproduced or claimed here.
\item \textbf{Idealized cost structure.} The law assumes a constant per-call
  overhead $O$ and a constant marginal $b$. Real dispatch overhead can vary with
  batch, transfers can be non-linear, and marginal work can depend on the
  parameter (window length here is held marginal-constant by construction). Those
  effects add curvature and quantization (e.g.\ chunk-boundary wobble) that the
  idealized law smooths over; the qualitative shape --- monotone rise to a
  ceiling with a ridge and a crossover --- is robust to them.
\item \textbf{One calibration and one workload.} The reported landmarks (ridge
  $24.03$, asymptote $25.03$, crossover $216$) are specific to the seeded
  calibration $O=3{,}605{,}000$, $b=150{,}000$. Only the ratio $O/b$ matters to
  the shape; a different overhead-to-marginal ratio moves every landmark, but the
  functional form of $S(B)$ does not change.
\end{itemize}

\section{Conclusion}
\label{sec:conclusion}

A parameter sweep dispatched one combination at a time re-pays a fixed per-call
overhead on every combination; batched into one call it pays that overhead once.
The speedup of batched over per-call execution is therefore an elementary
closed-form law, $S(B)=B(O+b)/(O+bB)$: monotone rising from $S(1)=1$, saturating
toward a ceiling $1+O/b$ it never reaches, with a batch-space ridge at $O/b$ and
a compute-bound crossover at $fO/[b(1-f)]$. On a seeded calibration with
$O/b=24.03$ the law climbs from $S(1)=1.00$ to $S(61)=17.96$ toward an asymptote
of $25.03$, with the ridge at $24.03$ and the $90\%$ crossover at $216$; the
fixed overhead falls from $96.0\%$ of the batched cost at $B=1$ to $28.3\%$ at
$B=61$. A real, seeded NumPy weighted-moving-average sweep --- with work measured
as a deterministic operation count rather than wall-clock time --- reproduces the
law exactly, produces bit-identical output on both paths, and, fitted back,
recovers $O/b=24.03$ and the asymptote $25.03$ with a maximum relative residual
of $0$. The whole demonstration is machine-invariant because the reported work is
an operation count, not a timing. We measure no GPU and reproduce none of the
prior work's device speedups; the contribution is the law and its
machine-invariant analog. If a batched sweep gets dramatically faster as you feed
it more combinations, that is not the hardware waking up --- it is the fixed
overhead being amortized, exactly as far as $S(B)$ says and no further.

\paragraph{Reproducibility.} All numbers derive from one seeded run.
\code{scripts/run\_all.py} regenerates \code{results/results.json} from seed $0$
(Python 3.12.3, NumPy 2.5.1) deterministically; the closed-form model and the
op-counted CPU analog are in \code{scripts/roofline.py}. The synthetic series is
a geometric random walk from \code{numpy.random.default\_rng(0)} (initial price
$30{,}000$, per-bar log-return standard deviation $5\times10^{-4}$,
$n=150{,}000$). \code{tests/} contains deterministic invariant tests for the
model (monotonicity, saturation, ridge, crossover), the analog (path
equivalence, overhead amortization), their agreement, and byte-level
reproducibility, and a guard asserting that only operation counts and model
values --- never timings --- are reported.

\bibliographystyle{plainnat}
\bibliography{refs}

\end{document}
