power-cap-sweep: add SM/mem clock + throttle% + pstate sampling

Cross-rig contributors share charts with these informative columns we
couldn't previously produce. Adds five new fields per cap, computed from
the same in-load sample window (util>50% filter):

- SM clock (median MHz) — distinguishes compute-bound vs bandwidth-bound
  regimes (clock pinned at max while TPS climbs = compute; clock varying
  with cap while TPS plateaus = bandwidth).
- Memory clock (median MHz) — sanity check; should pin at card-spec max.
- Pwr-throttle % — fraction of in-load samples with sw_power_cap=Active.
  100% means power is the binding constraint at that cap.
- Thermal-throttle % — captured via [result] line, not table column.
- P-state — dominant firmware power state. Validates boost-state plateau
  observations on 3090 (caps 340-370W pin at P2 → 334W actual draw).

No flag changes, no acceptance-criteria regressions — smoke-tested on
3-cap decode-single sweep at 23.4s/cap (matches prior baseline).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
noonghunna
2026-05-07 21:55:19 +00:00
co-authored by Claude Opus 4.7
parent a7a1d591d5
commit ab2796dd6e
+62 -12
View File
@@ -91,6 +91,20 @@
# - Per-cap bench logs at /tmp/power-cap-N{wattage}.log
# - Markdown summary at /tmp/power-cap-summary.md (paste into GitHub issue/discussion)
#
# Per-cap summary columns:
# Cap | Narr TPS | Code TPS | Actual W | Temp °C | SM clk | Mem clk | Pwr-throttle % | P-state | TPS/W
#
# - SM clk / Mem clk = median compute / memory clocks during in-load samples (MHz). Together
# they distinguish compute-bound vs bandwidth-bound regimes: if SM clock varies with cap
# while TPS plateaus → bandwidth-bound; if SM clock is pinned at max while TPS still climbs
# → compute-bound.
# - Pwr-throttle % = % of in-load samples where firmware was actively capping draw at the
# set limit (sw_power_cap=Active). 100% means power is the binding constraint at that
# cap; <100% means workload undersupply or thermal-throttle taking over.
# - P-state = dominant firmware power state during in-load samples (P0=max boost,
# P2=sustained-load pinned, higher numbers=idle). Boost-state plateaus appear when
# adjacent caps share a P-state and draw the same wattage despite different cap settings.
#
# Requires sudo for `nvidia-smi -pl`. Auto-detects running container + URL +
# MODEL via the same logic as bench.sh.
#
@@ -1042,8 +1056,8 @@ RESULTS_FILE=/tmp/power-cap-summary.md
echo "> MTP at 100 TPS). The *shape* of the efficiency knee is the cross-rig signal; absolute"
echo "> numbers only compare like-to-like."
echo ""
echo "| Cap (W) | Narr wall TPS | Code wall TPS | Actual power (W) | GPU temp (°C) | TPS/W (narr) |"
echo "|--------:|--------------:|--------------:|-----------------:|--------------:|-------------:|"
echo "| Cap (W) | Narr wall TPS | Code wall TPS | Actual power (W) | GPU temp (°C) | SM clk (MHz) | Mem clk (MHz) | Pwr-throttle % | P-state | TPS/W (narr) |"
echo "|--------:|--------------:|--------------:|-----------------:|--------------:|-------------:|--------------:|---------------:|:-------:|-------------:|"
} > "$RESULTS_FILE"
IFS=',' read -ra CAP_ARRAY <<< "$CAPS"
@@ -1079,7 +1093,7 @@ for CAP in "${CAP_ARRAY[@]}"; do
SAMPLE_FILE="/tmp/power-cap-N${CAP}-samples.csv"
(
while true; do
nvidia-smi --query-gpu=index,utilization.gpu,power.draw,temperature.gpu \
nvidia-smi --query-gpu=index,utilization.gpu,power.draw,temperature.gpu,clocks.current.sm,clocks.current.memory,pstate,clocks_throttle_reasons.sw_power_cap,clocks_throttle_reasons.hw_thermal_slowdown \
--format=csv,noheader,nounits -i "$GPU_INDEX" 2>/dev/null | head -1
sleep 0.5
done
@@ -1217,28 +1231,55 @@ PY
if [ -s "$SAMPLE_FILE" ]; then
UNDER_LOAD_STATS=$(python3 -c "
import sys
from collections import Counter
samples = []
with open('$SAMPLE_FILE') as f:
for line in f:
try:
idx, util, power, temp = [x.strip() for x in line.strip().split(',')]
parts = [x.strip() for x in line.strip().split(',')]
if len(parts) < 9:
continue
idx, util, power, temp, sm_clk, mem_clk, pstate, pwr_thr, therm_thr = parts
if int(util) > 50:
samples.append((float(power), int(temp)))
samples.append((
float(power),
int(temp),
int(sm_clk),
int(mem_clk),
pstate,
pwr_thr == 'Active',
therm_thr == 'Active',
))
except Exception:
continue
if not samples:
print('? ?')
print('? ? ? ? ? ? ?')
else:
powers = sorted(s[0] for s in samples)
temps = [s[1] for s in samples]
sm_clks = sorted(s[2] for s in samples)
mem_clks = sorted(s[3] for s in samples)
pstates = [s[4] for s in samples]
n = len(samples)
pwr_thr_pct = sum(1 for s in samples if s[5]) / n * 100
therm_thr_pct = sum(1 for s in samples if s[6]) / n * 100
median_power = powers[len(powers)//2]
peak_temp = max(temps)
print(f'{median_power:.2f} {peak_temp}')
" 2>/dev/null || echo "? ?")
median_sm = sm_clks[len(sm_clks)//2]
median_mem = mem_clks[len(mem_clks)//2]
dom_pstate = Counter(pstates).most_common(1)[0][0]
print(f'{median_power:.2f} {peak_temp} {median_sm} {median_mem} {dom_pstate} {pwr_thr_pct:.0f} {therm_thr_pct:.0f}')
" 2>/dev/null || echo "? ? ? ? ? ? ?")
ACTUAL_POWER=$(echo "$UNDER_LOAD_STATS" | awk '{print $1}')
GPU_TEMP=$(echo "$UNDER_LOAD_STATS" | awk '{print $2}')
SM_CLK=$(echo "$UNDER_LOAD_STATS" | awk '{print $3}')
MEM_CLK=$(echo "$UNDER_LOAD_STATS" | awk '{print $4}')
PSTATE=$(echo "$UNDER_LOAD_STATS" | awk '{print $5}')
PWR_THR_PCT=$(echo "$UNDER_LOAD_STATS" | awk '{print $6}')
THERM_THR_PCT=$(echo "$UNDER_LOAD_STATS" | awk '{print $7}')
else
ACTUAL_POWER="?"; GPU_TEMP="?"
SM_CLK="?"; MEM_CLK="?"; PSTATE="?"; PWR_THR_PCT="?"; THERM_THR_PCT="?"
fi
# Fallback to bench.sh GPU-state line if sampler returned ?
@@ -1264,13 +1305,13 @@ print(f"{(end - start) / 1e9:.1f}")
PY
)
printf "[result] %sW cap → %s narr / %s code TPS @ %sW actual draw, %s°C, eff %s TPS/W\n" \
"$CAP" "$NARR_TPS" "$CODE_TPS" "$ACTUAL_POWER" "$GPU_TEMP" "$EFFICIENCY"
printf "[result] cap=%sW actual_W=%s temp=%s sm_clk=%s mem_clk=%s pstate=%s throttle_pwr=%s throttle_thermal=%s narr=%s code=%s tps_per_w=%s\n" \
"$CAP" "$ACTUAL_POWER" "$GPU_TEMP" "$SM_CLK" "$MEM_CLK" "$PSTATE" "$PWR_THR_PCT" "$THERM_THR_PCT" "$NARR_TPS" "$CODE_TPS" "$EFFICIENCY"
printf "[time] %sW cap wall=%ss start=%s end=%s\n\n" \
"$CAP" "$CAP_WALL_S" "$CAP_START_UTC" "$CAP_END_UTC"
printf "| %s | %s | %s | %s | %s | %s |\n" \
"$CAP" "$NARR_TPS" "$CODE_TPS" "$ACTUAL_POWER" "$GPU_TEMP" "$EFFICIENCY" \
printf "| %s | %s | %s | %s | %s | %s | %s | %s | %s | %s |\n" \
"$CAP" "$NARR_TPS" "$CODE_TPS" "$ACTUAL_POWER" "$GPU_TEMP" "$SM_CLK" "$MEM_CLK" "$PWR_THR_PCT" "$PSTATE" "$EFFICIENCY" \
>> "$RESULTS_FILE"
done
@@ -1311,6 +1352,15 @@ fi
esac
echo "- Actual power = **median** of 0.5s samples taken DURING the workload where util > 50% (i.e. under-load)."
echo "- GPU temp = **peak** during workload (not a single post-bench point sample)."
echo "- **SM clk / Mem clk** = **median** clock speeds during in-load samples. SM clock is the compute-tier clock; memory clock is the HBM/GDDR clock."
echo " - If SM clock varies with cap while TPS plateaus → workload is **bandwidth-bound** (more compute headroom unused)."
echo " - If SM clock is pinned at max (~1.9 GHz on 3090, ~2.5+ GHz on 4090/5090) while TPS still climbs → workload is **compute-bound**."
echo " - Memory clock should normally pin at the card's spec max (9501 MHz on 3090, 10501 MHz on 4090, 14001 MHz on 5090). If it drops, that's a memory power-state transition worth investigating."
echo "- **Pwr-throttle %** = % of in-load samples where firmware was actively capping draw at the set limit (\`clocks_throttle_reasons.sw_power_cap=Active\`)."
echo " - **100%** → power is the binding constraint at this cap; raising the cap would draw more and produce more TPS."
echo " - **<100%** → either workload is undersupplying the card (lift via concurrency/prefill), or thermal-throttle is taking over (check temp + cooling)."
echo "- **P-state** = dominant firmware power state during in-load samples. P0 = max boost, P2 = sustained-load pinned, higher numbers = idle/low-load."
echo " - Boost-state plateaus appear when several adjacent caps all sit in the same P-state and draw identical wattage despite different cap settings (e.g. 3090s pin P2 across ~340-370W, then escape to P0 at 380W cap)."
echo "- TPS/W efficiency lets you spot the knee — typically the highest cap before efficiency drops."
echo "- If actual power < cap consistently and TPS is flat, the workload is **under-loading** this hardware:"
echo " the card can't use the extra power because it's not the bottleneck (smaller models on bigger"