analytical-viz: compound tiebreaker — fewer PEs / lower HBM% when latency ties

Every place that picks a single "best" config from the Pareto set now
uses a compound sort key: (latency_ns ↑, pes_used ↑, hbm_utilization ↑).
Primary = latency; when configs tie on latency (common — cp_ring
variants, some placement variants often produce identical numbers),
prefer smaller-footprint picks.

Places updated:
  - app.py:  sidebar Apply Attn/FFN/Attn+FFN button
  - app.py:  Physical Layout tab Attn/FFN/Attn+FFN button
  - app.py:  Auto Suggest tab "Best latency" metric
  - app.py:  Auto Hardware tab "Best latency" metric (uses parallelism.pes_used
             + parallelism.hbm_utilization since JointScore wraps ConfigScore)
  - auto_hardware.py:  _best_parallelism_for_hw iteration key

No behavior change when there's a strict latency winner. When there are
ties, the picked config uses fewer PEs and lower HBM utilization.

Verified: all 24 pytest tests pass (default include_attention=True and
include_ffn=True paths unchanged).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 22:16:02 -07:00
parent 6f61657ba4
commit 2a0bc26db0
2 changed files with 22 additions and 5 deletions
+16 -4
View File
@@ -237,8 +237,12 @@ with st.sidebar.expander("Parallelism", expanded=True):
"`pe_hbm_gb` or reducing `s_kv`." "`pe_hbm_gb` or reducing `s_kv`."
) )
else: else:
# Compound key: min latency, then fewer PEs, then lower HBM %.
# Prefer smaller-footprint configs when they tie on latency.
_sb_best = min(_sb_res.pareto_scores, _sb_best = min(_sb_res.pareto_scores,
key=lambda s: s.total_latency_ns) key=lambda s: (s.total_latency_ns,
s.pes_used,
s.hbm_utilization))
st.session_state["cp"] = _snap(_sb_best.cp, _CP_OPTS) st.session_state["cp"] = _snap(_sb_best.cp, _CP_OPTS)
st.session_state["tp"] = _snap(_sb_best.tp, _TP_OPTS) st.session_state["tp"] = _snap(_sb_best.tp, _TP_OPTS)
st.session_state["pp"] = _snap(_sb_best.pp, _PP_OPTS) st.session_state["pp"] = _snap(_sb_best.pp, _PP_OPTS)
@@ -580,8 +584,11 @@ with tab_layout:
"`s_kv`." "`s_kv`."
) )
else: else:
# Compound tiebreaker: min latency, then fewer PEs, then lower HBM %.
_pl_best = min(_pl_res.pareto_scores, _pl_best = min(_pl_res.pareto_scores,
key=lambda s: s.total_latency_ns) key=lambda s: (s.total_latency_ns,
s.pes_used,
s.hbm_utilization))
# Load the winning config into the sidebar's session state. # Load the winning config into the sidebar's session state.
st.session_state["cp"] = _pl_best.cp st.session_state["cp"] = _pl_best.cp
st.session_state["tp"] = _pl_best.tp st.session_state["tp"] = _pl_best.tp
@@ -1587,7 +1594,10 @@ def _render_auto_explore_tab():
_m2.metric("Feasible", f"{_res.total_feasible:,}") _m2.metric("Feasible", f"{_res.total_feasible:,}")
_m3.metric("Pareto configs", len(_res.pareto_scores)) _m3.metric("Pareto configs", len(_res.pareto_scores))
if _res.pareto_scores: if _res.pareto_scores:
_best = min(_res.pareto_scores, key=lambda s: s.total_latency_ns) _best = min(_res.pareto_scores,
key=lambda s: (s.total_latency_ns,
s.pes_used,
s.hbm_utilization))
_m4.metric("Best latency", f"{_best.latency_ms:.2f} ms") _m4.metric("Best latency", f"{_best.latency_ms:.2f} ms")
if not _res.pareto_scores: if not _res.pareto_scores:
@@ -1884,7 +1894,9 @@ def _render_auto_hardware_tab():
_hm3.metric("Pareto configs", len(_hw_res.pareto_scores)) _hm3.metric("Pareto configs", len(_hw_res.pareto_scores))
if _hw_res.pareto_scores: if _hw_res.pareto_scores:
_best = min(_hw_res.pareto_scores, _best = min(_hw_res.pareto_scores,
key=lambda s: s.total_latency_ns) key=lambda s: (s.total_latency_ns,
s.parallelism.pes_used,
s.parallelism.hbm_utilization))
_hm4.metric("Best latency", f"{_best.latency_ms:.2f} ms") _hm4.metric("Best latency", f"{_best.latency_ms:.2f} ms")
if not _hw_res.pareto_scores: if not _hw_res.pareto_scores:
@@ -245,14 +245,19 @@ def _best_parallelism_for_hw(
matches the caller's attention/FFN/full choice. matches the caller's attention/FFN/full choice.
""" """
best: ConfigScore | None = None best: ConfigScore | None = None
best_key: tuple | None = None
for topo in _iter_reduced_parallelism(model, s_kv, mode): for topo in _iter_reduced_parallelism(model, s_kv, mode):
cfg = FullConfig(model=model, topo=topo, machine=machine) cfg = FullConfig(model=model, topo=topo, machine=machine)
s = score_config(cfg, include_attention=include_attention, s = score_config(cfg, include_attention=include_attention,
include_ffn=include_ffn) include_ffn=include_ffn)
if not (s.fits_memory and s.placement_valid): if not (s.fits_memory and s.placement_valid):
continue continue
if best is None or s.total_latency_ns < best.total_latency_ns: # Compound tiebreaker: prefer fewer PEs and lower HBM % when latency
# ties across variant knobs (cp_ring, placement, kv_shard_mode, etc.).
_k = (s.total_latency_ns, s.pes_used, s.hbm_utilization)
if best is None or _k < best_key:
best = s best = s
best_key = _k
return best return best