diff --git a/docs/report/1H-codesign-paper/build/main.pdf b/docs/report/1H-codesign-paper/build/main.pdf index 2153fce..35a5490 100644 Binary files a/docs/report/1H-codesign-paper/build/main.pdf and b/docs/report/1H-codesign-paper/build/main.pdf differ diff --git a/docs/report/1H-codesign-paper/figures/gqa_short_context/batch_scaling.png b/docs/report/1H-codesign-paper/figures/gqa_short_context/batch_scaling.png index 74ebe81..482e834 100644 Binary files a/docs/report/1H-codesign-paper/figures/gqa_short_context/batch_scaling.png and b/docs/report/1H-codesign-paper/figures/gqa_short_context/batch_scaling.png differ diff --git a/docs/report/1H-codesign-paper/sections/05-gqa.tex b/docs/report/1H-codesign-paper/sections/05-gqa.tex index 00b86ec..a7de6ba 100644 --- a/docs/report/1H-codesign-paper/sections/05-gqa.tex +++ b/docs/report/1H-codesign-paper/sections/05-gqa.tex @@ -271,10 +271,13 @@ long-context batch sweep is 2H work (\S\ref{sec:future}). \si{\micro\second}) versus the number of concurrent decode users on one SIP, each user on a disjoint CUBE group. Each mapping scales almost linearly with $B$ up to its SIP capacity $16/C$---\textsf{1-kv-per-cube} saturates at two -users, \textsf{8-kv-per-cube} at sixteen. The dense mapping reaches the -highest throughput; the spread mapping is latency-optimal but -capacity-limited. Concurrent users overlap to within -\SI{3}{}--\SI{5}{\percent} of the single-user latency.} +users, \textsf{8-kv-per-cube} at sixteen. Solid segments are measured +concurrent runs; the dashed extensions are the saturated-throughput ceiling +beyond capacity, where further users run in waves at that sustained rate +(so the SIP is full, not idle). The dense mapping reaches the highest +ceiling; the spread mapping is latency-optimal but capacity-limited. +Concurrent users overlap to within \SI{3}{}--\SI{5}{\percent} of the +single-user latency.} \label{fig:gqa-batch} \end{figure} diff --git a/docs/sweeps/plot_scripts/plot_batch_scaling.py b/docs/sweeps/plot_scripts/plot_batch_scaling.py index bf3b4dc..c8996be 100644 --- a/docs/sweeps/plot_scripts/plot_batch_scaling.py +++ b/docs/sweeps/plot_scripts/plot_batch_scaling.py @@ -29,6 +29,7 @@ def main(): contexts = sorted({int(r["S_kv"]) for r in rows}) fig, axes = plt.subplots(1, len(contexts), figsize=(6.5 * len(contexts), 4.5), squeeze=False) + xmax = max(int(r["B"]) for r in rows) # largest SIP capacity (= 16) for col, S in enumerate(contexts): ax = axes[0][col] for m in MODES: @@ -40,8 +41,15 @@ def main(): if not pts: continue xs, ys = zip(*pts) + # Measured: concurrent users up to the SIP capacity 16/C. ax.plot(xs, ys, marker="o", color=MODE_COLOR[m], label=MODE_LABEL[m]) + # Beyond capacity the SIP is full: extra users run in waves at + # the saturated rate, so throughput plateaus. Draw that ceiling + # as a dashed extension (projected, not concurrently measured). + if xs[-1] < xmax: + ax.plot([xs[-1], xmax], [ys[-1], ys[-1]], + linestyle="--", color=MODE_COLOR[m], alpha=0.55) ax.annotate(f"{ys[-1]:.2f}", (xs[-1], ys[-1]), textcoords="offset points", xytext=(4, 4), fontsize=8) ax.set_title(f"S_kv = {S // 1024}K")