Skip to content

tenstorrent: f32-out matmul must not land on the bf16 grid; the kolibri residue is chain drift through a high-gain router - #3444

Merged
lu-zero merged 2 commits into
localai-org:mainfrom
lu-zero:row/tt-kolibri-l1moe
Oct 11, 2026
Merged

lu-zero merged 2 commits into
localai-org:mainfrom
lu-zero:row/tt-kolibri-l1moe

Conversation

@lu-zero

@lu-zero lu-zero commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator

Two results from the L1-moe localization (the ~3% relative divergence that remained after #3443's dequant fix).

A real contract defect, fixed: TT kMatmul/kMatmulBT produced a bf16-upcast tensor on commit for f32-out callers — all 384 kolibri router logits sat on the bf16 grid with bf16 partial sums. F32-out now requests dtype FLOAT32 with fp32_dest_acc_en (bf16grid 0/384 post-fix, instrumentation committed behind VT_KOLIBRI1_TT_STAGE_DUMP).

The residue classified — STOP class: with the router GEMM now correct (both arms match host-reference logits computed from their own inputs: CPU 1.4e-5, TT 0.15), the remaining hard flips are continuous precision drift driving discrete selection flips. The L0 input norm differs by 1 bf16 ULP class (substrate-adjudicated drift); by the L0 moe input that carries ~0.4% rms outliers; and the kolibri router (norm-weighted, K=2560, logits O(5)) amplifies that into O(1–5) absolute logit noise, flipping the near-tie top-6-of-384 selection at every layer. The hard flips (4 ON / 3 OFF, same positions) are this amplifier, not an op bug — the router gate weights are byte-identical across arms and both GEMMs are verifiably correct.

The endgame is therefore an adjudication decision, not a local patch: either the device attention/norm chain goes f32 (a perf and substrate-capability question), or the device gate's standard moves to the near-tie instrument's terms (band + zero-hard under teacher forcing, with a re-captured device golden), exactly mirroring the CPU #3438 discussion. The instrument to verify either path is merged (#3442).

Issue: ISSUE-LOCAL-01M4ER0E9HHM95YZYJB7T5FECN (full evidence chain; probes committed behind VT_KOLIBRI1_TT_STAGE_DUMP).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:zai/glm-5.3-flash [maki]

@localai-org-maint-bot localai-org-maint-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mudler @richiejp One source-level blocker in the added diagnostic path at 1bf1e5c:

In kolibri1_tt_forward.cpp::MoeBlock, the StageDumpOn() && l3dbg(layer) block indexes g_kolibri1_dbg_route_logits[k] unconditionally while iterating over href. That global starts empty and is populated only by the CPU forward path's RouteDump. Running TT alone with VT_KOLIBRI1_TT_STAGE_DUMP=1 therefore reads out of bounds; a prior CPU run with a shorter token batch also leaves it too small. The size check in TT RouteDump runs later and does not protect this earlier loop.

Please separate the same-input host-reference comparison from the optional CPU comparison, and require matching reference dimensions before reading the latter. The reference also needs to identify the same layer/prefix; a process-global last CPU layer cannot establish layer-by-layer parity by itself. A diagnostic test should cover TT-only execution and mismatched reference sizes.

This is a focused source finding, not acceptance of the stacked TT changes. I could not run the hardware/model gates on this host, so I have not pushed an unvalidated alteration to this branch.

@lu-zero
lu-zero force-pushed the row/tt-kolibri-l1moe branch 3 times, most recently from a0250cb to 456f6ee Compare October 11, 2026 08:00
amplification of the upstream bf16 drift class — and fix the f32-out GEMM
contract the instrument caught

The layer-1 moe divergence after the slot-dequant fix is NOT a
stride/staging/accounting defect. The teacher-forced instrument (stage
bit-hashes, the router dump on both arms, the router weight hash probe,
host-reference logits for both arms' router GEMMs, the element-level L0
dhn diff) proves the chain: the first diverging quantity is the L0 input
rms_norm output at step 0 (1 bf16 ULP class); by L0 dh2 the drift carries
outlier element diffs (~0.4% rms, 3 ULP on a 48-magnitude element); the
router gate weight is byte-identical across arms and BOTH router GEMMs
match host reference logits computed from their own inputs (CPU 1.4e-5,
TT 0.15 max) — and the kolibri router row has ||w||_2 ~ 1 over K=2560
against logits of scale O(5), so that sub-ULP-class drift injects O(1-5)
ABSOLUTE logit noise and flips the near-tie top-6-of-384 selection at
every layer including L0. The ~3% L1 moe divergence IS the flipped
mixture. Classification: selection flips DRIVEN by continuous precision
drift — the upstream adjudication decision, not a local patch.

The instrument did catch one contract defect, fixed here: the TT
kMatmul/kMatmulBT default produced a BF16 tensor upcast on commit for
f32-out callers — all 384 router logits sat on the bf16 grid
(bf16grid=384/384) with bf16 partial sums, violating the CPU row's
LinearBTRaw f32 contract. f32-out now requests dtype FLOAT32 plus
fp32_dest_acc_en; post-fix bf16grid=0/384. The device token gate (ON
arm, clean reset) keeps 4 HARD flips at the same positions (gaps -5.62 /
-3.85 / -14.76 / -3.75 vs -5.92 / -4.56 / -13.35 / -3.06) and the same
deterministic memoized-expert DRAM exhaustion abort: the contract fix
does not clear the flips because the drift class drives them. Recorded
in ISSUE-LOCAL-01M4ER0E9HHM95YZYJB7T5FECN with the full evidence chain;
the OFF arm was not re-gated (it aborts on the same OOM before
completing).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:zai/glm-5.3-flash [maki]
global unconditionally — TT-only execution with
VT_KOLIBRI1_TT_STAGE_DUMP=1 read an EMPTY process-global out of bounds

The maintainer review on 1bf1e5c was right, and the tree proves it: the
b2ii device token gate TT-only with the dump env set SEGFAULTS at layer 0,
immediately after the router_gate hash line and before any router_href
line (exit 139, /tmp/red-tt-only-prefix.log) — the MoeBlock dump block
iterated the host reference and indexed g_kolibri1_dbg_route_logits[k]
unconditionally, and the empty vector's null data derefs. A prior CPU run
with a SHORTER token batch left the global too small for the same
out-of-bounds read, and the size check in the TT RouteDump runs later and
cannot protect this earlier loop.

The fix separates the two comparisons the block conflated. The
HOST-REFERENCE leg (device logits vs host-computed reference logits for
the SAME inputs) stands on its own and is bounds-checked over the two
local vectors. The CPU leg is now OPTIONAL and runs only through
Kolibri1DebugRouteCompare (declared in kolibri1_tt_forward.h, defined out
of the TU's anonymous namespace so the host-side tests reach it) when the
stashed CPU reference's layer identity AND element size match the current
call — a process-global "last CPU layer" cannot establish layer-by-layer
parity, so the CPU arm now tags its stash with the layer
(g_kolibri1_dbg_route_layer, g_kolibri1_dbg_dhn_layer) and the TT side
checks identity before every global read (RouteDump's route_diff and the
layer-0 dhn diff included). TT-only, wrong-layer, and short-batch all
print cpu_ref=skipped and move on.

New device-free cases in test_kolibri1_tt_b2ii.cpp pin the guard: TT-only
execution with an empty CPU global (no read, cpu_compared false, the
device leg still computed), a shorter prior CPU batch (the exact pre-fix
OOB shape), and a different-layer reference (skipped; the same-layer
same-size case still compares and reports maxdiff_cpu). On device,
post-fix: the TT-only dump run completes the router_href leg on every
layer — 50 cpu_ref=skipped lines, no crash. Gate verdicts UNCHANGED (both
arms, clean reset per leg): ON 4 HARD flips at the same positions ('der
Mond' step 7, 'Australia' step 5, 'Wissen ist Macht' step 8, 'x1 = 3'
step 22) then the deterministic memoized-expert DRAM exhaustion abort;
host-free OFF 3 HARD flips then the same abort. TT unit suite: only the
two known failures (kGdnDecode, kMatmulBTQuantGrouped).

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:zai/glm-5.3-flash [maki]
@lu-zero
lu-zero force-pushed the row/tt-kolibri-l1moe branch from 456f6ee to 0ebb922 Compare October 11, 2026 09:29
@lu-zero
lu-zero merged commit b20dbfb into localai-org:main Oct 11, 2026
21 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants