perf(decode): pack2 MMVQ for attention Q4_K Wq and O projections#272
perf(decode): pack2 MMVQ for attention Q4_K Wq and O projections#272claytonlin1110 wants to merge 3 commits into
Conversation
📊 sparkinfer auto-eval —
|
| metric | value |
|---|---|
| label | eval:BASELINE |
| scored decode (16384 ctx · 16k-context · Qwen3.6) | 0.0 tok/s |
| correctness (Qwen3.6 vs llama.cpp) | top-1 94.8% · KL 0.0138 |
| Qwen3.6 128-token no-regression gate | 387.15 tok/s · pass |
| Qwen3.6 512-context no-regression gate | 380.96 tok/s · pass |
| Qwen3.6 4k-context no-regression gate | 367.46 tok/s · pass |
| Qwen3-30B-A3B guard — accuracy | top-1 95.8% · KL 0.0175 · pass |
| Qwen3-30B-A3B guard — 128-token | 499.59 tok/s · pass |
| Qwen3-30B-A3B guard — 512-context | 474.87 tok/s · pass |
| Qwen3-30B-A3B guard — 4k-context | 396.83 tok/s · pass |
| Qwen3-30B-A3B guard — 16k-context | 332.66 tok/s · pass |
| Qwen3-30B-A3B guard — 32k-context | 262.4 tok/s · pass |
No same-box main baseline was set; this run establishes one.
RTX 5090 (sm_120) · 128/512/4k/16k/32k guarded · scored vs same-box main · strongest context scores · built from source · correctness vs llama.cpp. Automated — not merged; merge manually after review.
📊 sparkinfer auto-eval —
|
| metric | value |
|---|---|
| label | eval:BASELINE |
| scored decode (16384 ctx · 16k-context · Qwen3.6) | 0.0 tok/s |
| correctness (Qwen3.6 vs llama.cpp) | top-1 96.1% · KL 0.0231 |
| Qwen3.6 128-token no-regression gate | 387.07 tok/s · pass |
| Qwen3.6 512-context no-regression gate | 381.19 tok/s · pass |
| Qwen3.6 4k-context no-regression gate | 367.3 tok/s · pass |
| Qwen3-30B-A3B guard — accuracy | top-1 96.4% · KL 0.0192 · pass |
| Qwen3-30B-A3B guard — 128-token | 498.46 tok/s · pass |
| Qwen3-30B-A3B guard — 512-context | 473.25 tok/s · pass |
| Qwen3-30B-A3B guard — 4k-context | 395.39 tok/s · pass |
| Qwen3-30B-A3B guard — 16k-context | 331.93 tok/s · pass |
| Qwen3-30B-A3B guard — 32k-context | 262.24 tok/s · pass |
No same-box main baseline was set; this run establishes one.
RTX 5090 (sm_120) · 128/512/4k/16k/32k guarded · scored vs same-box main · strongest context scores · built from source · correctness vs llama.cpp. Automated — not merged; merge manually after review.
⚪ sparkinfer auto-eval —
|
| metric | value |
|---|---|
| label | eval:none |
| scored decode (4096 ctx · 4k-context · Qwen3.6) | 367.27 tok/s |
| vs same-box main | 367.0 tok/s → +0.1% (+0.3) |
| correctness (Qwen3.6 vs llama.cpp) | top-1 95.9% · KL 0.0214 |
| Qwen3.6 128-token no-regression gate | 386.9 tok/s vs main 386.9 tok/s · pass |
| Qwen3.6 512-context no-regression gate | 380.84 tok/s vs main 380.92 tok/s · pass |
| Qwen3.6 4k-context no-regression gate | 367.27 tok/s vs main 367.0 tok/s · pass |
| Qwen3-30B-A3B guard — accuracy | top-1 94.9% · KL 0.0211 · pass |
| Qwen3-30B-A3B guard — 128-token | 499.54 tok/s · pass |
| Qwen3-30B-A3B guard — 512-context | 475.11 tok/s · pass |
| Qwen3-30B-A3B guard — 4k-context | 396.83 tok/s · pass |
| Qwen3-30B-A3B guard — 16k-context | 332.78 tok/s · pass |
| Qwen3-30B-A3B guard — 32k-context | 262.6 tok/s · pass |
Within the significance gate — no verified speedup over same-box main.
RTX 5090 (sm_120) · 128/512/4k/16k/32k guarded · scored vs same-box main · strongest context scores · built from source · correctness vs llama.cpp. Automated — not merged; merge manually after review.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
92bffb5 to
e39923b
Compare
⚪ sparkinfer auto-eval —
|
| metric | value |
|---|---|
| label | eval:none |
| scored decode (128 ctx · 128-context · Qwen3.6) | 413.26 tok/s |
| vs same-box main | 412.63 tok/s → +0.2% (+0.6) |
| correctness (Qwen3.6 vs llama.cpp) | top-1 97.6% · KL 0.0194 |
| Qwen3.6 128-token no-regression gate | 413.26 tok/s vs main 412.63 tok/s · pass |
| Qwen3.6 512-context no-regression gate | 405.69 tok/s vs main 405.33 tok/s · pass |
| Qwen3.6 4k-context no-regression gate | 389.42 tok/s vs main 388.98 tok/s · pass |
| Qwen3.6 16k-context no-regression gate | 355.96 tok/s vs main 412.63 tok/s · pass |
| Qwen3.6 32k-context no-regression gate | 319.99 tok/s · pass |
| Qwen3-30B-A3B guard — accuracy | top-1 94.3% · KL 0.0141 · pass |
| Qwen3-30B-A3B guard — 128-token | 485.01 tok/s · pass |
| Qwen3-30B-A3B guard — 512-context | 462.9 tok/s · pass |
| Qwen3-30B-A3B guard — 4k-context | 385.08 tok/s · pass |
| Qwen3-30B-A3B guard — 16k-context | 320.55 tok/s · pass |
| Qwen3-30B-A3B guard — 32k-context | 255.33 tok/s · pass |
Within the significance gate — no verified speedup over same-box main.
RTX 5090 (sm_120) · 128/512/4k/16k/32k guarded · scored vs same-box main · strongest context scores · built from source · correctness vs llama.cpp. Automated — not merged; merge manually after review.
* feat(polaris): verifiable eval receipts with Ed25519 signatures Adds cryptographic attestation to the eval pipeline so third parties can verify results without re-running GPU jobs. New files under eval/polaris/: - receipt.py: schema, canonicalization, Ed25519 sign/verify, AttestationBuilder, ReceiptValidator, compute_build_hash - judge.py: assembles unsigned attestation on eval box (no key needed) - verify.py: standalone CLI verifier — no GPU required - test_receipt.py: 29 unit tests (building, signing, verification, tamper detection, edge cases) - sparkinfer_eval.pub: Ed25519 public key trust anchor Modified: - pr_eval_bot.py: --polaris flag, key loading, attestation signing, receipt upload to sparkinfer-log, dashboard fields - vast_eval.py: --polaris flag, SSH command pins eval/polaris/ from origin/main, runs judge.py, passes POLARIS_ATTESTATION through Trust model: judge assembles on eval box (pinned to origin/main), bot signs on trusted host. Private key never touches the eval box. * feat(polaris): upgrade to Intel TDX hardware attestation via Polaris API Replace Ed25519 software signatures with Polaris TDX hardware attestation for scoring integrity. The scoring step (correctness gate, guard gate, label computation) now runs inside an Intel TDX enclave with DCAP-quoted receipts. New files: - eval/polaris/scoring.py: self-contained scoring script (stdlib only) that runs inside the TDX enclave, replicating evaluate_dual.sh lines 148-212 - eval/polaris/client.py: PolarisClient for the /v1/attest API Modified files: - eval/polaris/receipt.py: add build_polaris_receipt() and ReceiptValidator.verify_tdx() for TDX receipt assembly and verification. verify() auto-detects receipt type (tdx-quote vs Ed25519). - eval/polaris/verify.py: auto-detect TDX receipts, show Intel DCAP verification status, distinguish TDX vs Ed25519 in output. - eval/pr_eval_bot.py: when POLARIS_API_KEY is set, submit scoring to Polaris TDX enclave and build TDX receipts. Ed25519 signing is preserved as fallback when only SPARKINFER_POLARIS_PRIVATE_KEY is set. The Ed25519 path and all 29 existing tests continue to pass unchanged. * docs: add Polaris verifiable eval receipts documentation * dashboard: PR #272 -> eval:none (413.26 tok/s) * fix(eval): 16k/32k guard baseline fallback — bash expansion bug + display Two bugs caused Qwen3.6 16k/32k guard baselines to show wrong values: 1. evaluate_dual.sh: ${SPARKINFER_P_GUARD_16K_BASELINE:-338.55} treats the explicit "0" passed by the bot as a valid non-empty string, so the :- expansion never fires and the hardcoded default is never used. Fix: two-step fallback — try env var, then hardcoded default if still 0. 2. pr_eval_bot.py: the display fallback for ctx_16384_tps used frontier_tps (the 128-context baseline, ~412) instead of a proper 16k default (~339). ctx_32768_tps had no fallback at all. Fix: _GUARD_BASE_FALLBACK dict with per-context defaults matching evaluate_dual.sh. * dashboard: PR #282 -> eval:XL (427.28 tok/s) * fix(eval): trigger Qwen3.6 baseline sweep when any context is missing Previously the 5-context sweep only ran when 128 baseline was 0. Since the bot always passes a non-zero 128 baseline, the sweep never ran and 16k/32k baselines were never measured fresh — falling through to broken ${VAR:-default} expansions and eventually to wrong display values. Now the sweep triggers when ANY of 128/512/4k/16k/32k is 0, so passing only 128/512/4k (with 16k/32k as 0) still gets a fresh measurement on the eval box. * fix(eval): resolve vastai CLI path and update default instance to 44206573 - vast_eval.py: resolve vastai binary via shutil.which / ~/.local/bin/vastai so subprocess.run works from bot/cron contexts where PATH may be limited. - pr_eval_bot.py: update hardcoded VAST_DEFAULT_INSTANCE fallback to 44206573. * fix(eval): measure Qwen3.6 16k/32k baselines in bot pre-sweep The same-box Qwen3.6 baseline sweep now covers all 5 contexts (128, 512, 4k, 16k, 32k) instead of just 3. The measured values are passed as --p-guard-16k/32k-baseline to vast_eval.py, which forwards them to the eval box via SPARKINFER_P_GUARD_16K/32K_BASELINE env vars. This gives evaluate_dual.sh real measured baselines to use (instead of falling through to hardcoded defaults). * dashboard: PR #282 -> eval:XL (427.05 tok/s) * fix(eval): point eval log repo and URL to main sparkinfer repo Previously logs were pushed to gittensor-ai-lab/sparkinfer-log.git which skyrocket2026 lacks permission to push to. Move to the main sparkinfer repo and update the log page URL accordingly. * dashboard: PR #283 -> eval:none (415.04 tok/s) --------- Co-authored-by: Skyrocket <>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
log tail |
Summary
Halve CUDA-graph node count for the two largest attention Q4_K MMVQ projections (Wq @ 4096 rows, Wo @ 2048 rows) by packing two output rows per CTA with the same faithful 4-warp kfixed dot loop. Reduces bs=1 launch/graph-replay overhead on the decode hot path.
Closes #271, related #141.
Proof of speedup
sm_120)Decode tok/s (end-to-end, from
bench/scripts/bench.sh— required for evaluation):