PD-sep matrix results: C2/C3/C4 figures + empirical mechanism refined

Captures 5 runs from the experiment matrix (combined-ca x3 seeds,
pdsep-4p4d seed1, pdsep-6p2d seed1) on traces/w600_r0.0015_st30.jsonl
with cuda graphs enabled. The headline:

  combined-ca:  TTFT p50 0.91s   success 99.5%
  pdsep-4p4d:   TTFT p50 62.8s   success 52%   (69x worse, half dropped)
  pdsep-6p2d:   TTFT p50 51.1s   success 68%   (56x worse, third dropped)

C2 (fig_c2): headline bars per config with error bars.
C3 (fig_c3): per-instance KV utilization time-series. Both PD-sep
  splits hit the memory wall, but the side differs by P:D ratio --
  4P+4D pins the P-side, 6P+2D pins both sides (D-side back-pressures
  P-side).
C4 (fig_c4): TTFT stacked breakdown. 99% of PD-sep TTFT is P-side
  prefill compute; D-side wait + first token is <=1.2s. The bottleneck
  is P-side prefill queueing, not D-side decode wait as the original
  analytical model assumed.

system_analysis.md gains a Layer 5b that reconciles the analytical
KV-wall model (which considered D-side only) with the empirical
finding that the wall hits whichever side has fewer GPUs, and
co-saturates both at extreme splits via D-side back-pressure.

plot_pd_matrix.py ingests outputs/pd_matrix/* into all four figures.
bench.sh gained AGENTIC_STEP_LOG_DIR hooks for future runs (set during
this work but not used by the current matrix's data).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 16:23:52 +08:00
parent 25445e3d18
commit cd82b8c2a2
7 changed files with 606 additions and 5 deletions

View File

@@ -41,6 +41,7 @@ WITH_RR=false
WITH_EAGER=false
DRY_RUN=false
TAG_PREFIX="pd_matrix"
ONLY="" # comma-separated list of tags to run (subset of the matrix)
while [[ $# -gt 0 ]]; do
case "$1" in
@@ -50,6 +51,7 @@ while [[ $# -gt 0 ]]; do
--with-rr) WITH_RR=true; shift ;;
--with-eager) WITH_EAGER=true; shift ;;
--tag-prefix) TAG_PREFIX="$2"; shift 2 ;;
--only) ONLY="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
-h|--help)
sed -n '2,30p' "$0"; exit 0 ;;
@@ -57,6 +59,20 @@ while [[ $# -gt 0 ]]; do
esac
done
# Build set of allowed tags from --only (if provided).
declare -A ALLOWED
if [ -n "$ONLY" ]; then
IFS=',' read -ra _tags <<< "$ONLY"
for t in "${_tags[@]}"; do
ALLOWED["$(echo "$t" | xargs)"]=1
done
fi
is_allowed() {
# if ONLY not set, everything is allowed
[ -z "$ONLY" ] && return 0
[ -n "${ALLOWED[$1]:-}" ]
}
if [ ! -f "$TRACE" ]; then
echo "[ERROR] trace not found: $TRACE"
exit 1
@@ -141,13 +157,17 @@ for c in "${CONFIGS[@]}"; do
for m in "${MODES[@]}"; do
mode_name="${m%%|*}"; mode_args="${m##*|}"
for s in $(seq 1 $SEEDS); do
tag_name="${cfg_name}_${mode_name}_seed${s}"
if ! is_allowed "$tag_name"; then
continue
fi
if run_one "$cfg_name" "$cfg_args" "$mode_name" "$mode_args" "$s"; then
N_DONE=$((N_DONE + 1))
else
N_FAIL=$((N_FAIL + 1))
fi
ELAPSED=$(( $(date +%s) - START_TS ))
echo "[progress] $N_DONE done, $N_FAIL failed, $((N_TOTAL - N_DONE - N_FAIL)) remaining, ${ELAPSED}s elapsed"
echo "[progress] $N_DONE done, $N_FAIL failed, ${ELAPSED}s elapsed"
done
done
done