Merge pull request #577 from noonghunna/feat/phase2-big-card-envelopes
Phase 2: PRO 6000 + DGX Spark envelopes, fix Blackwell GPU detector
This commit is contained in:
@@ -63,6 +63,14 @@ envelopes:
|
||||
target_ctx: 262144
|
||||
date: 2026-07-05
|
||||
note: "no-preemption ceiling (2x RTX 5090, 64 GB). Arithmetic, sm_120-calibrated (disc #571 paulp verify-stress PASS); awaiting a concurrency-soak to upgrade to validated."
|
||||
rtx-6000-pro-blackwell:
|
||||
max_num_seqs: 8 # 2 -> 8 on 2x96 GB (NVLink-bridged workstation)
|
||||
compose_default: 2
|
||||
computed:
|
||||
basis: "kv-calc pool ceiling is ~16 (--compose dual --vram 96 --tp 2 --max-ctx 262144 --mem-util 0.96: N=16 PASS, N=20 caps), but capped to 8 — BANDWIDTH, not pool, binds. PRO 6000 GDDR7 (~1.8 TB/s) ≈ a 5090's, so useful concurrency sits near the 5090's 4, lifted to 8 by the 3x pool (less preemption); the rest of the pool is context headroom."
|
||||
target_ctx: 262144
|
||||
date: 2026-07-05
|
||||
note: "operational cap, not the raw pool ceiling (see basis). 2x RTX PRO 6000 Blackwell, NVLink-bridged. No PRO 6000 on this rig — a concurrency-soak refines this and upgrades it to validated."
|
||||
|
||||
vllm/minimal:
|
||||
rtx-5090:
|
||||
@@ -73,15 +81,32 @@ envelopes:
|
||||
target_ctx: 32768
|
||||
date: 2026-07-05
|
||||
note: "no-preemption ceiling (1x RTX 5090, 32 GB). Arithmetic, sm_120-calibrated (disc #571 paulp verify-stress PASS); awaiting a concurrency-soak to upgrade to validated."
|
||||
rtx-6000-pro-blackwell:
|
||||
max_num_seqs: 16 # 1 -> 16 on 1x96 GB
|
||||
compose_default: 1
|
||||
computed:
|
||||
basis: "kv-calc pool ceiling is >56 (--compose minimal --vram 96 --tp 1 --max-ctx 32768 --mem-util 0.96: N=56 still PASS), but capped to 16 — bandwidth-bound. GDDR7 ≈ a 5090's, so 16 concurrent 32K streams (small per-stream KV) is a defensible operating point on the 3x pool; the raw >56 would over-batch into throughput collapse."
|
||||
target_ctx: 32768
|
||||
date: 2026-07-05
|
||||
note: "operational cap, not the raw pool ceiling (see basis). 1x RTX PRO 6000 Blackwell. Spec-derived, no PRO 6000 on this rig — a soak refines + upgrades to validated."
|
||||
dgx-spark:
|
||||
max_num_seqs: 8 # 1 -> 8 on 1x128 GB unified (bandwidth-capped)
|
||||
compose_default: 1
|
||||
computed:
|
||||
basis: "kv-calc pool ceiling is >80 (--compose minimal --vram 128 --tp 1 --max-ctx 32768 --mem-util 0.85: N=80 still PASS), but capped to 8 — Spark's ~273 GB/s LPDDR5X (≈1/7 of a 5090) HARD-binds concurrency. Useful streams sit near a 5090's (or below), NOT scaled by the 4x pool; the pool's value here is context headroom, not more streams."
|
||||
target_ctx: 32768
|
||||
date: 2026-07-05
|
||||
note: "operational cap, bandwidth-bound (see basis). 1x DGX Spark (GB10), single-unit. TP=2 across two units is ConnectX/RDMA (network-bound) — NOT seeded for dual. No Spark on this rig — a soak refines + upgrades to validated."
|
||||
|
||||
# ON BIG CARDS, POOL != CONCURRENCY. The rtx-6000-pro-blackwell and dgx-spark
|
||||
# rows above are OPERATIONAL CAPS, not raw kv-calc pool ceilings: past a point
|
||||
# decode concurrency is bound by memory BANDWIDTH, not pool size. PRO 6000
|
||||
# (~1.8 TB/s GDDR7 ≈ a 5090) lifts modestly above the 5090; Spark (~273 GB/s
|
||||
# LPDDR5X, ~1/7 of a 5090) does NOT — its huge pool buys context headroom, not
|
||||
# streams. Each row's `basis` cites the raw ceiling AND the bandwidth cap; a
|
||||
# soak on real hardware refines the operating point and upgrades to validated.
|
||||
#
|
||||
# NOT SEEDED yet (computable, deferred on purpose):
|
||||
# rtx-6000-pro-blackwell (96 GB): pool ceilings run very high (minimal ~40+,
|
||||
# dual 16+) — those need a latency-aware cap (concurrency past a point
|
||||
# trades single-stream TPS), not the raw pool ceiling. Seed once we pick
|
||||
# the policy. Rare card; 5090 is the realistic target first.
|
||||
# DGX Spark (GB10, sm_121, 128 GB): folds into the SAME framework, but has
|
||||
# no hardware profile yet — add scripts/lib/profiles/hardware/dgx-spark.yml
|
||||
# before a row can inject (the guard requires card ∈ hardware profiles).
|
||||
# MULTI-GPU (TP>2, e.g. vllm/qwen-27b-multi-fast/max @ TP=4): the injection
|
||||
# seam ALREADY handles homogeneous >2-card rigs — it collapses N identical
|
||||
# cards to one class, so `vllm/dual` on 4x5090 injects the dual ceiling and
|
||||
|
||||
44
scripts/lib/profiles/hardware/dgx-spark.yml
Normal file
44
scripts/lib/profiles/hardware/dgx-spark.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
schema_version: 1
|
||||
id: dgx-spark
|
||||
display_name: NVIDIA DGX Spark (GB10)
|
||||
sm: 12.1
|
||||
vram_gb: 128
|
||||
arch: blackwell-gb10
|
||||
# Unified LPDDR5X shared with the Grace CPU, so usable device memory is well
|
||||
# below the 128 GB spec — mem_util_safe is deliberately conservative (OS + CPU
|
||||
# reservation) rather than the 0.96 the discrete Blackwell SKUs carry.
|
||||
mem_util_safe: 0.85
|
||||
# NOTE: nvfp4 KV is DELIBERATELY NOT listed — like consumer Blackwell (sm_120),
|
||||
# GB10 (sm_121) has no trtllm-gen FP4 FMHA build (that kernel is datacenter
|
||||
# Blackwell sm_100/103 only). FP4 weights work; nvfp4 KV crashes. fp8_e4m3 is
|
||||
# the FP4-era KV here. The #574 nvfp4 gate already excludes sm_121.
|
||||
supported_kv_formats:
|
||||
- bf16
|
||||
- fp16
|
||||
- fp8_e5m2
|
||||
- fp8_e4m3
|
||||
- turboquant_3bit_nc
|
||||
- int8_per_token_head
|
||||
- q4_0
|
||||
- q5_0
|
||||
- q8_0
|
||||
- k8v4
|
||||
kv_format_default:
|
||||
long_context: fp8_e4m3
|
||||
multi_stream: fp8_e4m3
|
||||
balanced: fp8_e4m3
|
||||
cudagraph: full
|
||||
driver_pin_recommended:
|
||||
min: "580.0"
|
||||
notes: "GB10 ships on DGX OS with a 580.x-class (CUDA 13) driver."
|
||||
nvlink_capable: false
|
||||
power_cap_w_optimal: 120
|
||||
power_cap_w_max: 140
|
||||
# CRITICAL for concurrency envelopes: the 128 GB pool is huge but the ~273 GB/s
|
||||
# LPDDR5X bandwidth (~1/7 of a 5090's GDDR7) is the binding constraint on decode
|
||||
# concurrency — useful streams saturate near a 5090's, NOT scaled by the 4x pool
|
||||
# (the extra pool buys context headroom, not more streams). Two units cluster
|
||||
# over ConnectX (RDMA, not NVLink), so TP=2 across units is network-bound and
|
||||
# NOT recommended — single-unit serving is the realistic mode. Specs are from
|
||||
# public sheets; no DGX Spark on this rig (values not rig-measured).
|
||||
notes: "GB10 Grace-Blackwell superchip, 128 GB unified LPDDR5X (~273 GB/s). Bandwidth-bound for concurrency. Single-unit serving; ConnectX clustering is not low-latency TP. Spec-derived, not rig-measured."
|
||||
@@ -54,8 +54,14 @@ def _hardware_id_from_gpu(name: str, mem_mib: int, sm: float) -> str:
|
||||
vram_gb = round(mem_mib / 1024)
|
||||
|
||||
aliases = (
|
||||
("rtx 6000 pro blackwell", "rtx-6000-pro-blackwell"),
|
||||
("6000 pro blackwell", "rtx-6000-pro-blackwell"),
|
||||
# RTX PRO 6000 Blackwell reports as "RTX PRO 6000 Blackwell" -> normalizes
|
||||
# to "rtx pro 6000 blackwell" (PRO before 6000), so match "pro 6000".
|
||||
# ("6000" alone is avoided — it would swallow the sm_89 "RTX 6000 Ada".)
|
||||
("rtx pro 6000", "rtx-6000-pro-blackwell"),
|
||||
("pro 6000", "rtx-6000-pro-blackwell"),
|
||||
# DGX Spark's GB10 superchip reports as "GB10" / "NVIDIA GB10".
|
||||
("dgx spark", "dgx-spark"),
|
||||
("gb10", "dgx-spark"),
|
||||
("rtx 3090 ti", "rtx-3090-ti"),
|
||||
("3090 ti", "rtx-3090-ti"),
|
||||
("rtx 3090", "rtx-3090"),
|
||||
@@ -75,7 +81,16 @@ def _hardware_id_from_gpu(name: str, mem_mib: int, sm: float) -> str:
|
||||
if needle in normalized:
|
||||
return hardware_id
|
||||
|
||||
if sm >= 12 and vram_gb >= 32:
|
||||
# sm >= 12 Blackwell family, split by SM then VRAM (name aliases above are
|
||||
# the primary signal; these are the fallback when the name string is odd):
|
||||
# GB10 / DGX Spark = sm_121 (unified 128 GB)
|
||||
# RTX PRO 6000 Blackwell = sm_120, 96 GB
|
||||
# RTX 5090 = sm_120, 32 GB
|
||||
if 12.05 <= sm <= 12.2:
|
||||
return "dgx-spark"
|
||||
if sm >= 12 and vram_gb >= 64:
|
||||
return "rtx-6000-pro-blackwell"
|
||||
if sm >= 12 and vram_gb >= 24:
|
||||
return "rtx-5090"
|
||||
if sm >= 9 and vram_gb >= 80:
|
||||
return "h100-80gb"
|
||||
|
||||
@@ -122,6 +122,26 @@ assert_contains "$out" "VLLM_IMAGE=vllm/vllm-openai:v0.24.0"
|
||||
assert_not_contains "$out" "KV_CACHE_DTYPE"
|
||||
echo " ok: #246 arch-aware KV injection matrix (8 cases)"
|
||||
|
||||
# --- detector: Blackwell family must not collapse to rtx-5090 (#576 wrinkle) --
|
||||
# The sm>=12 bucket used to map every Blackwell to rtx-5090, so a 96 GB PRO 6000
|
||||
# and a 128 GB GB10 both mis-detected as a 32 GB 5090. Lock the split.
|
||||
det="$(python3 - <<'PY'
|
||||
import sys; sys.path.insert(0, "scripts/lib/profiles")
|
||||
from launch_compat import _hardware_id_from_gpu as m
|
||||
cases = [
|
||||
("NVIDIA RTX PRO 6000 Blackwell", 98304, 12.0, "rtx-6000-pro-blackwell"),
|
||||
("Unnamed Blackwell 96GB", 98304, 12.0, "rtx-6000-pro-blackwell"), # alias-miss fallback
|
||||
("NVIDIA GB10", 131072, 12.1, "dgx-spark"),
|
||||
("NVIDIA GeForce RTX 5090", 32607, 12.0, "rtx-5090"),
|
||||
("NVIDIA RTX 6000 Ada Generation",49140, 8.9, "rtx-4090"), # 'pro 6000' must NOT catch Ada
|
||||
]
|
||||
bad = [f"{n}->{m(n,v,s)} want {e}" for n, v, s, e in cases if m(n, v, s) != e]
|
||||
print("FAIL: " + " | ".join(bad) if bad else "OK")
|
||||
PY
|
||||
)"
|
||||
[[ "$det" == "OK" ]] || { echo " FAIL: detector: $det"; exit 1; }
|
||||
echo " ok: Blackwell detector split (PRO 6000 / GB10 / 5090 / Ada — 5 cases)"
|
||||
|
||||
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
|
||||
out="$(VLLM_NIGHTLY_SHA="$CLEAN_SHA" docker compose -f "$ROOT_DIR/models/qwen3.6-27b/vllm/compose/dual/autoround-int4/fp8-mtp.yml" config 2>/dev/null)"
|
||||
assert_contains "$out" "image: vllm/vllm-openai:v0.24.0"
|
||||
|
||||
@@ -23,7 +23,7 @@ run_test() {
|
||||
run_test "load_profiles parses all profile groups" <<'PY'
|
||||
from scripts.lib.profiles.compat import load_profiles
|
||||
p = load_profiles()
|
||||
assert len(p.hardware) == 9
|
||||
assert len(p.hardware) == 10 # +dgx-spark (#576 follow-up)
|
||||
assert len(p.models) == 11
|
||||
assert len(p.workloads) == 5
|
||||
assert len(p.engines) == 13
|
||||
|
||||
Reference in New Issue
Block a user