1-card target: ThinkingCap-27B on ONE P150a (TP=1) - context ladder, accuracy, bf4 coverage, batching #69
Labels
No labels
human-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
bitpartner/tt-stack#69
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Target (owner, 2026-09-25): 1 card and 2 cards. This issue tracks the 1-card target (TP=1, one P150a). It carries forward what PR #15 (goal 4) left open. The PR is closed because its content is merged and its base branch is dead.
Measured so far (09-05 tree, QUASAR NVFP4,
goal4-single-card-nvfp4-2026-09-05.jsonl)Open, carried from #15
bfp-quant:bench/runs/bfp-quant-p1-20260925T0645Z.jsonl).Reopened by the 2026-09-25 rule (a closure needs an on-hardware record at its scope)
Each of these rests on a code read or a single observed failure, so each is engineering work, not a limit.
paged_fill_cache.model.pyblock it. The 09-05 run used max_num_seqs=1 by construction.num_devices == 1: this needs a degenerate-TP bypass.prefill_for_spec,verify_forwardandverify_tracedassertnum_devices > 1.Enablers already measured
mtp-thinkingcap:bench/runs/two-card-coexistence-20260925T0625Z.jsonl). Paired A/Bs can run one arm per card. Two full 27B loads at once are not yet shown to be safe for host RAM.The NVFP4 loader patches 0009/0010 were deleted as dead. Recover them with
git show 682dd38:patches/tt-metal/0009-qwen36-nvfp4-compressed-tensors-loader.patchand…/0010-qwen36-single-device-lazy-state-dict.patch.The scoreboard row is docs/STATUS.md, TP=1.
TP=1 MTP: interim status (2026-09-25 10:10Z). No new speed number in this update.
"Decode on one card is broken": there is no decode failure on record yet. No TP=1 run has reached decode.
g2-tp1-proberuns (cfx-llm2:/var/lib/models/ttx-runs/ttx-g2-tp1-probe-smoke-20260925T083748Z and thettx-ab-...-20260925T090800Z-r{0,1}-{A,B}runs) are load-only. Their phases are imports, open, ttnn_matmul, model_load, hold and done, and every one endsok: true. They show that G2 loads on one card: 20.96 GB of 33.1 GB DRAM, VmHWM 5.6–5.8 GB, and 32–34 MB RSS after load. They never prefill or decode.nlp_concat_headsover 48 heads needed 1.68 MB.TP1_L1_FIT: blocked prefill outputs and grouped concat-heads), and neither affects TP=2. Seebench/runs/mtp-tp1-attempts-20260925.jsonl.bench/mtp/tp1-card.sh). It is waiting for MemAvailable to reach 4 GB: tt-quant's GPTQ on card 0 holds 2 GB RSS, and a TP=1 load peaks at ~5.8 GB. If decode fails there, I will report the op, file and line.TP=2 byte-identity with the TP=1 code: whole-chunk prompts are unchanged; the tail-chunk difference is pre-existing (
bench/runs/mtp-tp1-tp2identity-20260925.jsonl).Docs moved to the new layout: LEDGER
R-2026-09-25-mtp-g2andD-2026-09-25-mtp-tp1, MTP.md and STATUS.md.TP=1 decode on one card now runs: G2 plain and MTP K3/K7 on a single P150a (card 1, ttx per-card slot). Label: TP=1 iteration, not production. Record:
bench/runs/mtp-tp1-smoke-20260925T1310Z.jsonl.Why decode looked broken. No TP=1 run had ever reached decode:
g2-tp1-proberuns are load-only.The root cause of the last failure (attempt 3, 13:08Z):
ttnn.experimental.nlp_concat_heads.tp_common.py:74 concat_heads_fit, called fromgdn/tp.py:761 forward_prefill(fused out: rms_norm, then concat heads), called frommodel.py:1798 _forward_prefill_chunk_tp, during the warmup prefill trace capture.TT_THROW dataflow_buffer.cpp:2617 "static dataflow buffers ... clash with L1 buffers ... L1 buffer at 860160, CB region ends at 898048".Fix (commit on
mtp-thinkingcap).tp_common.pf_l1()returns DRAM underTP1_L1_FIT(set only at one device) and L1 otherwise. It is applied at every short-lived prefill L1 site:At TP=2 every call returns what it did before. With prefill fixed, decode ran first time, with no decode-side change.
Smoke numbers (B=1, 4096-token prompts, G2, 64 engaged / 1 exempt banners):
Next: gate (c), two TP=1 containers at once (card 0 on the s2a arms, card 1 on the s2b arms, staggered, with watchdog and mem.tsv). That run also supplies the 20-prompt data for gate (a), identity plus logit PCC against TP=2, and gate (b), K3/K7 acceptance. After that comes the solo timed s1 run for TP=1 PP and TG. The pair is queued behind tt-quant's mesh run.
TP=1 MTP on one P150a: gates measured. G2, B=1, greedy, 256 tokens, ttx per-card slots. Label: TP=1 iteration, not production; rankings stay on TP=2 E2E. Records:
bench/runs/mtp-tp1-gates-20260925T1410Z.jsonl(plus.compare.json) onmtp-thinkingcap(d2e9fea). LEDGERR-2026-09-25-mtp-tp1.Speed (card 1 solo, timed arms with the probe off), ms/token:
Gate (b), acceptance: PASSED. Committed tokens per iteration, paired over 20 prompts:
Gate (c), two TP=1 containers at once: PASSED.
bench/mtp/tp1-pair.sh).Gate (a), identity vs TP=2: NOT PASSED under the owner rule (control p99: TP=2 1.94, TP=1 1.81).
TP=2 byte-identity with this code: whole-chunk prompts are bit-identical. The 2048+47 tail-chunk prompt varies with any process change, including the old overlay with a new harness. That is pre-existing (
bench/runs/mtp-tp1-tp2identity-20260925.jsonl).Code changes this round (all gated to one device):
tp_common.pf_l1(): DRAM for short-lived prefill activations that TP=2 keeps in L1. This is the fix that got prefill through and let decode run.run-mtp-ab.sh:SLOT_OWNERmode.tp1-card.shandtp1-pair.sh: the ttx-slot drivers.Docs updated: LEDGER, MTP.md, STATUS.md, and the mtp-tt and tt-card-slot skills.