#!/usr/bin/env python3 """Plot measured knob conditional effects for the AITuner harness study.""" from __future__ import annotations from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np from matplotlib.lines import Line2D from matplotlib.patches import Patch OUT = Path("docs/harness-ablation/figures") def save(fig: plt.Figure, name: str) -> None: OUT.mkdir(parents=True, exist_ok=True) fig.savefig(OUT / f"{name}.png", dpi=220, bbox_inches="tight") fig.savefig(OUT / f"{name}.svg", bbox_inches="tight") def plot_c1_surface() -> None: # Qwen30B mixed workload, TP x MNS screen. Values are req/s/GPU. # Source runs: # - interaction-mixed-qwen30b-tp-mns-surface-high1-dash1-d8899c5-20260701T095858Z # - interaction-mixed-qwen30b-tp4-mns-nocap-qps20-dash1-d8899c5-20260701T161900Z mns = np.array([8, 16, 32, 64]) tp = np.array([1, 2, 4]) values = np.array( [ [2.1000, 2.3500, 2.2833, 2.2833], [2.2750, 2.2750, 3.2833, 3.2583], [1.2833, 2.4417, 2.4417, 2.4417], ] ) fig, axes = plt.subplots(1, 2, figsize=(12.8, 4.8), gridspec_kw={"width_ratios": [1.05, 1.2]}) ax = axes[0] im = ax.imshow(values, cmap="YlGnBu", aspect="auto", vmin=1.2, vmax=3.35) ax.set_xticks(range(len(mns)), labels=mns) ax.set_yticks(range(len(tp)), labels=[f"TP={x}" for x in tp]) ax.set_xlabel("max-num-seqs (MNS)") ax.set_ylabel("tensor-parallel-size") ax.set_title("C1 response surface: req/s/GPU") for i in range(values.shape[0]): for j in range(values.shape[1]): color = "white" if values[i, j] > 2.75 else "black" ax.text(j, i, f"{values[i, j]:.2f}", ha="center", va="center", color=color, fontsize=10) cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04) cbar.set_label("req/s/GPU") ax = axes[1] colors = {1: "#4E79A7", 2: "#59A14F", 4: "#E15759"} for idx, t in enumerate(tp): ax.plot(mns, values[idx], marker="o", linewidth=2.4, color=colors[int(t)], label=f"TP={t}") ax.set_xscale("log", base=2) ax.set_xticks(mns, labels=mns) ax.set_xlabel("max-num-seqs (MNS)") ax.set_ylabel("req/s/GPU") ax.set_title("Non-parallel lines imply interaction") ax.grid(True, axis="y", alpha=0.28) ax.legend(frameon=False) ax.annotate( "TP=2 only becomes best\nwhen MNS reaches 32", xy=(32, 3.2833), xytext=(20, 3.05), arrowprops={"arrowstyle": "->", "lw": 1.2}, fontsize=9, ) ax.annotate( "TP=4 is bad at MNS=8\nbut recovers at MNS>=16", xy=(8, 1.2833), xytext=(10, 1.55), arrowprops={"arrowstyle": "->", "lw": 1.2}, fontsize=9, ) fig.suptitle("Knob effects are conditional: MNS effect depends on TP", fontsize=14, y=1.02) fig.tight_layout() save(fig, "knob-conditional-c1-qwen30b-surface") plt.close(fig) def plot_c1_oat_counterexample() -> None: # C1 Qwen30B: one-knob-at-a-time tuning gets trapped at a coordinate-wise # local optimum 25.6% below the measured global best. The right panel zooms # into the trap's neighbourhood so the reader can SEE that every single-knob # move from the trap is worse or flat, instead of having to read a caption. mns = [8, 16, 32, 64] tp = [1, 2, 4] values = np.array( [ [2.1000, 2.3500, 2.2833, 2.2833], [2.2750, 2.2750, 3.2833, 3.2583], [1.2833, 2.4417, 2.4417, 2.4417], ] ) idx = {(t, s): (mns.index(s), tp.index(t)) for t in tp for s in mns} fig, axes = plt.subplots(1, 2, figsize=(14.0, 6.2), gridspec_kw={"width_ratios": [1.5, 1.0]}) ax = axes[0] im = ax.imshow(values, cmap="YlGnBu", aspect="auto", vmin=1.2, vmax=3.35) ax.set_xticks(range(len(mns)), labels=mns) ax.set_yticks(range(len(tp)), labels=[f"TP={x}" for x in tp]) ax.set_xlabel("max-num-seqs (MNS)", fontsize=11) ax.set_ylabel("tensor-parallel-size", fontsize=11) ax.set_title("Two OAT paths from the same start", fontsize=12, loc="left") for i in range(values.shape[0]): for j in range(values.shape[1]): color = "white" if values[i, j] > 2.75 else "black" ax.text(j, i, f"{values[i, j]:.2f}", ha="center", va="center", color=color, fontsize=11, weight="bold") def draw_path(path: list[tuple[int, int]], color: str, labels: list[str]) -> None: for (a, b) in zip(path, path[1:]): x0, y0 = idx[a] x1, y1 = idx[b] ax.annotate( "", xy=(x1, y1), xytext=(x0, y0), arrowprops={"arrowstyle": "->", "lw": 3.2, "color": color, "shrinkA": 22, "shrinkB": 22}, ) for (a, b), lbl in zip(zip(path, path[1:]), labels): x0, y0 = idx[a] x1, y1 = idx[b] mx, my = (x0 + x1) / 2, (y0 + y1) / 2 if x0 == x1: # vertical move -> label to the side ax.text( mx + 0.30, my, lbl, color=color, fontsize=9.5, ha="left", va="center", weight="bold", bbox={"boxstyle": "round,pad=0.2", "facecolor": "white", "edgecolor": "none", "alpha": 0.85}, ) else: # horizontal move -> label above ax.text( mx, my - 0.32, lbl, color=color, fontsize=9.5, ha="center", va="bottom", weight="bold", bbox={"boxstyle": "round,pad=0.2", "facecolor": "white", "edgecolor": "none", "alpha": 0.85}, ) # Red: tune MNS first, then TP -> walks into a coordinate-wise local optimum. draw_path([(1, 8), (1, 16), (4, 16)], "#C0392B", ["tune MNS", "tune TP"]) # Green: tune TP first, then MNS -> reaches the measured global best. draw_path([(1, 8), (2, 8), (2, 32)], "#2E7D32", ["tune TP", "tune MNS"]) # start / trap / best markers (explained by the legend below the grid) sx, sy = idx[(1, 8)] ax.scatter([sx], [sy], marker="o", s=210, facecolors="none", edgecolors="black", linewidths=2.2, zorder=5) trap = (4, 16) tx, ty = idx[trap] ax.add_patch(plt.Rectangle((tx - 0.5, ty - 0.5), 1, 1, fill=False, edgecolor="#C0392B", linewidth=3.4)) best = (2, 32) bx, by = idx[best] ax.add_patch(plt.Rectangle((bx - 0.5, by - 0.5), 1, 1, fill=False, edgecolor="#2E7D32", linewidth=3.4)) legend_elements = [ Line2D([0], [0], marker="o", color="w", markerfacecolor="none", markeredgecolor="black", markeredgewidth=2, markersize=10, label="start TP1,MNS8 = 2.10"), Patch(facecolor="none", edgecolor="#C0392B", linewidth=2.4, label="OAT trap TP4,MNS16 = 2.44 (no improving single-knob move)"), Patch(facecolor="none", edgecolor="#2E7D32", linewidth=2.4, label="global best TP2,MNS32 = 3.28"), ] ax.legend(handles=legend_elements, loc="upper center", bbox_to_anchor=(0.5, -0.11), ncol=1, frameon=False, fontsize=9.5) cbar = fig.colorbar(im, ax=ax, fraction=0.038, pad=0.035) cbar.set_label("req/s/GPU") # ---- right panel: why the red path stops (trap neighbourhood zoom) ---- ax2 = axes[1] ax2.set_xlim(-0.55, 3.55) ax2.set_ylim(-0.65, 3.7) ax2.set_aspect("equal") ax2.set_axis_off() ax2.set_title("Why the red path stops here", fontsize=12, loc="left") # 3x3 neighbourhood of the trap (TP4,MNS16). Rows match left panel: # top=TP2, middle=TP4(trap), bottom=TP8(not measured). Cols: MNS 8/16/32. # (col, row) with row 0 at bottom. zoom_cells = { (1, 2): ("2.275", "TP2", "dead"), # up neighbour (0, 1): ("1.28", "TP4", "dead"), # left neighbour (1, 1): ("2.44", "TP4", "trap"), # the trap (2, 1): ("2.44", "TP4", "flat"), # right neighbour (flat, not strictly improving) (1, 0): ("—", "TP8", "oob"), # down neighbour (not measured) } for (col, row), (val, tplabel, kind) in zoom_cells.items(): x, y = col, row if kind == "trap": fc, ec, lw = "#FDECEA", "#C0392B", 3.2 elif kind == "oob": fc, ec, lw = "#F2F2F2", "#CCCCCC", 1.0 else: fc, ec, lw = "#FDF2F2", "#E6B0AA", 1.4 ax2.add_patch(plt.Rectangle((x, y), 1, 1, facecolor=fc, edgecolor=ec, linewidth=lw)) if kind == "oob": ax2.text(x + 0.5, y + 0.5, "no data", ha="center", va="center", fontsize=9, color="#999", style="italic") else: val_color = "#C0392B" if kind in ("dead", "flat") else "#222" ax2.text(x + 0.5, y + 0.62, val, ha="center", va="center", fontsize=13, weight="bold", color=val_color) sublabel = tplabel if kind == "trap": sublabel = f"{tplabel} · trap" elif kind == "flat": sublabel = f"{tplabel} · flat" ax2.text(x + 0.5, y + 0.28, sublabel, ha="center", va="center", fontsize=8.5, color="#666") if kind in ("dead", "flat"): ax2.text(x + 0.87, y + 0.87, "✗", ha="center", va="center", color="#C0392B", fontsize=18, weight="bold") # axis labels for the zoom ax2.text(-0.18, 2.5, "TP=2", ha="right", va="center", fontsize=9, color="#666") ax2.text(-0.18, 1.5, "TP=4", ha="right", va="center", fontsize=9, color="#666") ax2.text(-0.18, 0.5, "TP=8", ha="right", va="center", fontsize=9, color="#999") ax2.text(0.5, -0.18, "MNS=8", ha="center", va="top", fontsize=9, color="#666") ax2.text(1.5, -0.18, "MNS=16", ha="center", va="top", fontsize=9, color="#666") ax2.text(2.5, -0.18, "MNS=32", ha="center", va="top", fontsize=9, color="#666") ax2.text( 1.5, 3.45, "Every measured single-knob move from the trap\nis worse or flat → coordinate ascent is stuck", ha="center", va="center", fontsize=10.5, color="#222", bbox={"boxstyle": "round,pad=0.35", "facecolor": "white", "edgecolor": "#C0392B"}, ) fig.suptitle("One-knob-at-a-time tuning gets trapped: 25.6% throughput gap between two tuning orders", fontsize=14, y=1.02) fig.tight_layout() save(fig, "knob-oat-counterexample-c1-qwen30b") plt.close(fig) def plot_c1_interaction_residual() -> None: # If TP and MNS were independent additive effects, this residual matrix would be near zero. mns = [8, 16, 32, 64] tp = [1, 2, 4] values = np.array( [ [2.1000, 2.3500, 2.2833, 2.2833], [2.2750, 2.2750, 3.2833, 3.2583], [1.2833, 2.4417, 2.4417, 2.4417], ] ) residual = values - values.mean(axis=1, keepdims=True) - values.mean(axis=0, keepdims=True) + values.mean() fig, ax = plt.subplots(figsize=(7.2, 4.8)) limit = float(np.abs(residual).max()) im = ax.imshow(residual, cmap="RdBu", aspect="auto", vmin=-limit, vmax=limit) ax.set_xticks(range(len(mns)), labels=mns) ax.set_yticks(range(len(tp)), labels=[f"TP={x}" for x in tp]) ax.set_xlabel("max-num-seqs (MNS)") ax.set_ylabel("tensor-parallel-size") ax.set_title("C1 non-additive interaction residual") for i in range(residual.shape[0]): for j in range(residual.shape[1]): ax.text(j, i, f"{residual[i, j]:+.2f}", ha="center", va="center", fontsize=10) cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04) cbar.set_label("req/s/GPU residual") fig.suptitle("Independent-knob additive model leaves large structured residuals", fontsize=13, y=1.02) fig.tight_layout() save(fig, "knob-interaction-residual-c1-qwen30b") plt.close(fig) def plot_c3_lines() -> None: # Qwen235B decode C3, topology x MNS x MBT screen. # Source run: # interaction-qwen235b-decode-c3-topo-mns-mbt-fixed-dash1-d8899c5-20260703T022514Z data = { ("TP4/DP2/EP8", 64, 256): 0.05354166666666667, ("TP4/DP2/EP8", 64, 384): 0.05354166666666667, ("TP4/DP2/EP8", 128, 256): 0.058958333333333335, ("TP4/DP2/EP8", 128, 384): 0.058958333333333335, ("TP2/DP4/EP8", 64, 256): 0.058958333333333335, ("TP2/DP4/EP8", 64, 384): 0.05354166666666667, ("TP2/DP4/EP8", 128, 256): 0.058958333333333335, ("TP2/DP4/EP8", 128, 384): 0.058958333333333335, } mbt = [256, 384] topologies = ["TP4/DP2/EP8", "TP2/DP4/EP8"] fig, axes = plt.subplots(1, 2, figsize=(11.5, 4.6), sharey=True) for ax, topo in zip(axes, topologies): for mns, color in [(64, "#4E79A7"), (128, "#F28E2B")]: vals = [data[(topo, mns, b)] for b in mbt] ax.plot(mbt, vals, marker="o", linewidth=2.6, color=color, label=f"MNS={mns}") for x, y in zip(mbt, vals): ax.text(x, y + 0.0007, f"{y:.4f}", ha="center", fontsize=9) ax.set_title(topo) ax.set_xlabel("max-num-batched-tokens (MBT)") ax.set_xticks(mbt) ax.grid(True, axis="y", alpha=0.28) ax.set_ylim(0.050, 0.062) axes[0].set_ylabel("req/s/GPU") axes[1].legend(frameon=False, loc="lower right") fig.suptitle("C3: MBT effect depends on topology and MNS", fontsize=14, y=1.02) fig.tight_layout() save(fig, "knob-conditional-c3-qwen235b-decode-lines") plt.close(fig) def plot_delta_summary() -> None: c1_base = { "TP=1": (2.2833 - 2.1000) / 2.1000 * 100.0, "TP=2": (3.2833 - 2.2750) / 2.2750 * 100.0, "TP=4": (2.4417 - 1.2833) / 1.2833 * 100.0, } c3_mbt = { "TP4/DP2\nMNS=64": 0.0, "TP4/DP2\nMNS=128": 0.0, "TP2/DP4\nMNS=64": (0.05354166666666667 - 0.058958333333333335) / 0.058958333333333335 * 100.0, "TP2/DP4\nMNS=128": 0.0, } c3_mns = { "TP4/DP2\nMBT=256": (0.058958333333333335 - 0.05354166666666667) / 0.05354166666666667 * 100.0, "TP4/DP2\nMBT=384": (0.058958333333333335 - 0.05354166666666667) / 0.05354166666666667 * 100.0, "TP2/DP4\nMBT=256": 0.0, "TP2/DP4\nMBT=384": (0.058958333333333335 - 0.05354166666666667) / 0.05354166666666667 * 100.0, } panels = [ ("C1: MNS 8->32\nunder different TP", c1_base, "#59A14F"), ("C3: MBT 256->384\nunder different context", c3_mbt, "#E15759"), ("C3: MNS 64->128\nunder different context", c3_mns, "#4E79A7"), ] fig, axes = plt.subplots(1, 3, figsize=(16, 5.2)) for ax, (title, vals, color) in zip(axes, panels): labels = list(vals.keys()) y = np.arange(len(labels)) x = list(vals.values()) colors = [color if v >= 0 else "#B07AA1" for v in x] ax.barh(y, x, color=colors) ax.axvline(0, color="black", linewidth=0.8) lo = min(x) hi = max(x) pad = max(2.0, (hi - lo) * 0.12) ax.set_xlim(lo - pad, hi + pad) ax.set_yticks(y, labels=labels, fontsize=8) ax.invert_yaxis() ax.set_xlabel("relative change in req/s/GPU (%)") ax.set_title(title) ax.grid(True, axis="x", alpha=0.25) for yi, xi in zip(y, x): ha = "left" if xi >= 0 else "right" offset = 0.7 if xi >= 0 else -0.7 ax.text(xi + offset, yi, f"{xi:+.1f}%", va="center", ha=ha, fontsize=8) fig.suptitle("The same knob intervention has context-dependent effect size", fontsize=14, y=1.02) fig.tight_layout() save(fig, "knob-conditional-delta-summary") plt.close(fig) def main() -> None: plot_c1_oat_counterexample() plot_c1_interaction_residual() plot_c1_surface() plot_c3_lines() plot_delta_summary() if __name__ == "__main__": main()