Download offload/dspark/native/NATIVE.md from ProprietaryLegal/dsv41-offload: direct link, hf CLI and curl.
- Browser
- Download file 25.9 kB
-
https://huggingface.co/ProprietaryLegal/dsv41-offload/resolve/main/offload/dspark/native/NATIVE.md
- Command line
-
hf download hf://ProprietaryLegal/dsv41-offload/offload/dspark/native/NATIVE.md
-
curl -L -o NATIVE.md https://huggingface.co/ProprietaryLegal/dsv41-offload/resolve/main/offload/dspark/native/NATIVE.md
Status 2026-10-23: Native representation/semantics record; later N4 official arithmetic and S20 assessment govern readiness. Old timing/acceptance tables are historical evidence. See live roadmap and measured record; campaign review decisions are in LANES.md / lane reports outside the repo.
Native 1017 DSpark draft on the NVLink pair (N1-NATIVE)
In short. The official DeepSeek-V4.1-Flash-1017 draft (mtp.0-2, 2,401 tensors) is stored as MXFP4 routed experts,
FP8 E4M3 dense matrices with E8M0 32x32 block scales, and BF16 / FP32 small tensors; it shares the target's BF16
embedding and BF16 head. This directory serves those official values on x86host's two RTX 3090s without any lossy
re-quantization: either packed (the official bytes, decoded in the GEMM) or expanded (decoded once to BF16, exact).
NATIVE_MANIFEST.json lists every tensor (official format, bytes, sha256, value checks, what the deployed worker
holds instead). Source: deepseek-ai/DeepSeek-V4.1-Flash-1017 @ 1bae0e1088993b9b82de08f59de5be5a34e42170,
shards 44-46 (draft), 2 (embed), 43 (head + final norm), sha256-verified (/opt/dsv41/x86host-data/native-1017/ RECEIPT.txt on x86host); official inference code alongside (inference/, SHA256SUMS).
1. Tensors: native vs decoded vs EXL3 vs shared
| tensor family (per stage s = 0..2 unless noted) | official | supply | deployed worker (TENSORS.json) | native arms |
|---|---|---|---|---|
embed.weight [129,280 x 5,120] |
BF16 | shared with target | official bytes (HeNryous copy; sha256 compared in the manifest) | unchanged |
head.weight [129,280 x 5,120] |
BF16 | shared with target | EXL3 K6 | K6 (control) / official BF16 per vocab shard (head arm) |
mtp.s.ffn.experts.{0..127}.w1/w3 [2,304 x 5,120] |
MXFP4 (I8 [2,304 x 2,560] + E8M0 [2,304 x 160]) | draft-only | EXL3 K2 | packed MXFP4 / expanded BF16 (exact) |
mtp.s.ffn.experts.{0..127}.w2 [5,120 x 2,304] |
MXFP4 (I8 [5,120 x 1,152] + E8M0 [5,120 x 72]) | draft-only | EXL3 K2 | packed / expanded |
mtp.s.ffn.shared_experts.w1/w3 [2,304 x 5,120], w2 [5,120 x 2,304] |
FP8 E4M3 + E8M0 32x32 | draft-only | EXL3 K5 | FP8 packed / BF16 expanded (exact) |
mtp.s.attn.wq_a [1,280 x 5,120], wkv [512 x 5,120], wq_b [32,768 x 1,280], wo_b [5,120 x 8,192] |
FP8 + E8M0 | draft-only | EXL3 K5 | FP8 / BF16 expanded |
mtp.s.attn.wo_a [8,192 x 4,096] |
FP8 + E8M0 (the official runtime dequantizes it to BF16: convert.py) | draft-only | official FP8 bytes, scales decoded to fp32 at load | same, or BF16 expanded (exact) |
mtp.0.main_proj [5,120 x 15,360] |
FP8 + E8M0 | draft-only | EXL3 K5 (fp32-accumulating build) | FP8 / BF16 expanded |
mtp.s.ffn.gate.weight [128 x 5,120] |
BF16 (used as fp32) | draft-only | official BF16 | unchanged |
mtp.s.ffn.gate.bias [128] |
FP32 | draft-only | official FP32 | unchanged, never through fp16 |
mtp.s.ffn.gate.bias_vl [128] |
FP32 | draft-only | not loaded (vision-only bias; drafts are text) | not loaded |
norms (attn_norm, ffn_norm, q_norm, kv_norm, mtp.0.main_norm, mtp.2.norm) |
BF16 | draft-only | official | unchanged |
mtp.s.hc_{attn,ffn}_{fn,base,scale}, mtp.s.attn.attn_sink |
FP32 | draft-only | official | unchanged |
mtp.2.markov_head.{embed,head}.weight [129,280 x 256] |
BF16 | draft-only | official (+ an 8,192-row bias cache) | official; cache / factorized / hot-row arms |
mtp.2.confidence_head.proj.weight [1 x 5,376] |
BF16 (used as fp32) | draft-only | official | unchanged |
"Shared" means the draft reads the target's own tensor (Transformer.__init__: self.mtp[-1].embed = self.embed; self.mtp[-1].head = self.head; convert.py drops any mtp.*.embed/head copy). The Spark target's embed / head and
sampler never change; the draft keeps its own copy on the 3090s (it must compute logits locally). The per-tensor
truth (sha256 of the official bytes vs the worker's bytes) is in NATIVE_MANIFEST.json (worker field).
2. Official semantics (inference/model.py, kernel.py)
Quantized linear (model.linear): a weight of dtype float4_e2m1fn_x2 or float8_e4m3fn takes an FP8 activation:
act_quant(x, 32, "ue8m0", e8m0) per 32 consecutive inputs: amax = max(max|x|, 1e-4) (fp32),
s = 2^ceil(log2(fp32(amax * fp32(1/448)))) by exponent bits, q = e4m3_rne(clamp(x / s, ±448)). The GEMM forms,
per 32-wide K block, the exact FP8 x FP8 (FP4 weights are cast to FP8 through fp32, losslessly) products summed in fp32,
multiplies the block sum by s_a * s_w and accumulates in fp32; the output is bf16. FP4 weight scales: one E8M0
per 32 inputs of each output row ([out, in/32]); FP8 weight scales: one per 32x32 block ([ceil(out/32), ceil(in/32)]). Packed FP4: byte j of a row holds input 2j in the low nibble, 2j+1 in the high nibble; E2M1 table
0, .5, 1, 1.5, 2, 3, 4, 6 with bit 3 the sign (0b1000 = -0). E8M0 byte b = 2^(b-127); 255 = NaN.
On SM86 (no FP8 tensor cores) the same arithmetic is reproduced exactly: a QDQ'd bf16 activation equals q * s
exactly (4 significant bits, power-of-two scale), a decoded weight code * 2^(b-127) is exact in bf16 (range checked
for every tensor in the manifest), and bf16 x bf16 products are exact in the fp32 accumulator. A native kernel
therefore differs from the official one only in fp32 summation order. The activation QDQ is part of the model
(trained with it): it must run before every FP8/FP4 linear, never be dropped as "lossy".
Other QDQ points (act_quant(..., inplace=True), bf16 in place): the window KV after kv_norm + RoPE (both
the context rows main_kv and the block rows kv), and the attention output o per 32 before the wo_a einsum.
wo_a: dequantized to bf16 at load (convert.py); o (QDQ'd) einsum("bsgd,grd->bsgr") in bf16 (fp32 acc), per
group g of 8, then wo_b (FP8 linear).
RMSNorm: fp32 x * rsqrt(mean(x^2) + 1e-20), times the bf16 weight (fp32 product), cast back to bf16.
Gate (text tokens): scores = linear(x.float(), W.float()) (fp32, no TF32) / gate_temp (1.0) ->
sqrt(softplus(scores)); ids = topk(scores + bias, 3) (fp32 bias; it only selects); w = scores[ids],
w /= sum(w) + 1e-20, w *= 1.5.
Expert (routed: FP4; shared: FP8): gate = w1(x).float(), up = w3(x).float() (each linear's bf16 output),
up = clamp(up, -10, 10), gate = clamp(gate, max=10), h = silu(gate) * up (fp32), routed: h = w * h (fp32),
w2(h.to(bf16)) (QDQ of h per 32, bf16 output).
MoE: y = 0 (fp32); for expert ids in ascending order y[rows] += expert(x[rows], w) (bf16 output added in
fp32); y += shared(x); out = y.to(bf16).
Block / mHC: hc_mixes(stream, fn, scale, base): flatten the 4 copies (fp32), `F.linear(x, fn) * rsqrt(mean(x^2)
- 1e-20)
,hc_split_sinkhorn(20 iterations, eps 1e-6) -> pre / post / comb;hc_precollapses with the previous sub-block's pre-mix (fp32 sum, bf16 out);hc_post = post * x + sum(comb * residual)`. Attention uses the pre-mix the previous FFN produced, the FFN the one this attention produced.
DSpark stage: stage 0 main_x = main_norm(main_proj(cat(taps 37, 38, 39))); block input ids [anchor, noise x 4]
(noise 128799) embedded and replicated over the 4 copies; attention over the 128-row window of main_x KV plus the
block's own 5 rows (sink per head); after stage 2: logits = head(norm(hc_pre(x))) in fp32 (bf16 weight used as
fp32); position i: logits[:, i] += markov.head(markov.embed(prev_id)) (rank 256), prev = argmax (temperature 0);
confidence = proj(cat(hidden, markov_embed).float()).
reference.py implements the linear / expert / gate / MoE semantics as oracles (acc="f64": exact products summed
in float64; acc="blocked": the official block order).
3. TP2 split of the native tensors (rank r = 0, 1)
The cuts are the deployed TP2 worker's (TP2.md), now on 32-element scale groups:
| tensor | rank r holds | scale groups |
|---|---|---|
| routed w1 / w3 | output rows [1152r, 1152r + 1152) | rows' own scales [1152, 160] |
| routed w2 | inputs [1152r, 1152r + 1152): packed bytes [576r, 576r + 576), scales [36r, 36r + 36) | 36 whole groups; h's QDQ blocks never straddle the cut |
| shared w1 / w3 | output rows [1152r, ...): FP8 scale rows [36r, 36r + 36) | whole 32x32 blocks |
| shared w2 | inputs [1152r, ...): scale cols [36r, ...) | whole blocks |
| wq_b | output rows (heads 32r..32r+31) [16384r, ...): scale rows [512r, ...) | whole blocks |
| wo_a | groups 4r..4r+3: rows [4096r, ...) | whole blocks |
| wo_b | inputs [4096r, ...): scale cols [128r, ...) | whole blocks; o's QDQ blocks never straddle |
| head (all arms) | tile-aligned vocabulary split: rank 0 [0, 64768), rank 1 [64768, 129280), via vocab_split() |
— |
| everything else | replicated | — |
Where the official single-device model rounds a FULL sum to bf16 (each routed expert's w2 output, the shared w2, wo_b), a rank holds only a partial sum. Two combine modes, both measured: exact-official — all-reduce the fp32 partials per (row, expert slot) and per shared expert, then round each to bf16 and add in ascending expert id as the official MoE does; fused — each rank sums its slots in fp32, one fp32 all-reduce, one bf16 rounding (fewer roundings than the official model; differs from it by at most the per-expert bf16 roundings it skips).
4. Kernel contract (KX-MXFP4, KX-GROUPED)
See the "From N1" sections of KX-MXFP4.progress.md / KX-GROUPED.progress.md (campaign folder) for the
lane-facing copy; this is the binding text.
Routed experts, one stage, one rank:
- inputs:
xbf16 [T, 5120], already act_qdq'd (one QDQ per row, shared by all three experts and the shared expert;formats.act_qdq/ N1's device op),idsint32 [T, 3] (0..127, device-resident, never read back),rwfp32 [T, 3]; T = 5 x requests (5, 10, 15, 20; up to 32 supported). - packed weights (KX-MXFP4):
w13uint8 [128, 2, 1152, 2560] (w1 rows then w3 rows of the rank),s13uint8 [128, 2, 1152, 160];w2uint8 [128, 5120, 576],s2uint8 [128, 5120, 36]. Low nibble = even input. E8M0 bias 127. - expanded weights (KX-GROUPED):
w13bf16 [128, 2, 1152, 5120],w2bf16 [128, 5120, 1152], values exactlycode * 2^(b-127). - math per (t, j), e = ids[t, j]:
g = bf16(sum_k x·w1),u = bf16(sum_k x·w3)(fp32 accumulation, ROUNDED TO BF16: the official linear returns bf16);u = clamp(u, -10, 10),g = min(g, 10);h = (g / (1 + expf(-g))) * u(fp32, full-precision expf, as torch's silu);h = rw[t, j] * h;h16 = bf16(h);hq = act_qdq(h16)per 32 over the rank's 1152 (36 blocks);y = sum_k hq·w2fp32 (the rank's partial over its 1152 inputs). - outputs (preallocated, graph-safe): mode SLOT: fp32 [T, 3, 5120] per-slot partials (exact-official combine is done
after the all-reduce by N1's epilogue); mode COMBINE: fp32 [T, 5120] = slot partials summed in fp32 in ascending
expert-id order per row (+ optional fp32
addinput, e.g. the shared expert's partial). No host sync, no allocation, no data-dependent launch dimensions. - exactness test: against
reference.pyon the real tensors (native-1017), every element within fp32 summation-order noise ofacc="f64"; bf16 roundings of g / u bit-identical to the reference's for > 99.9 % of elements (the rest: fp32 order flipping a bf16 tie, listed).
Dense (KX-GROUPED "dense native"): y = bf16(sum_k act_qdq(x)·W) with W FP8 + 32x32 E8M0 (packed) or exact BF16
(expanded); shapes (rank-local, N x K): wq_a 1280 x 5120, wkv 512 x 5120, wq_b 16384 x 1280, wo_b 5120 x 4096 (fp32
partial out), shared w1/w3 1152 x 5120, shared w2 5120 x 1152 (fp32 partial out), main_proj 5120 x 15360 (insert
rows 8-128 only), head 64640 x 5120 bf16 weight with fp32 logits out (the official head is fp32 x fp32; bf16 x bf16 ->
fp32 is exact here because the normed hidden is bf16), wo_a 4 groups x (1024 x 4096) bf16 einsum.
5. Memory per card (TP2), computed from the real shapes; measured values replace these in N1-NATIVE.report.md
Weights per rank in MiB (rank 0; rank 1 holds 0.9 MiB less head). Shared by every arm, as lane E measured them (TP2.md): embedding 1,262.5 (bf16, replicated), Markov embedding 63.1 + head shard 31.6 + bias cache 1,012.5, RoPE 80.5 at 327,680 positions (256.5 at 1,048,576), norms / mHC / router 18.8, windows 3.4: 2,472.4.
| part | K2 control | native packed | native expanded | source of the native number |
|---|---|---|---|---|
| routed experts (3 stages x 128) | 1,633.8 (EXL3 K2) | 3,442.5 | 12,960.0 | per stage: w13 128x2x1152x2560 B + s13 128x2x1152x160 B + w2 128x5120x576 B + s2 128x5120x36 B = 1,147.5 MiB; expanded 128x3x1152x5120x2 B = 4,320 MiB |
| dense (wq_a, wkv repl.; wq_b, wo_a, wo_b, shared shards; main_proj repl.) | 218.5 (K5 + FP8 wo_a) | 321.1 (FP8 + fp32 scale values) | 639.8 (bf16) | 335,413,248 FP8 bytes per rank |
| head shard | 237.3 (K6) | 237.3 (K6) or 632.5 (bf16 arm) | same | 64,768 x 5,120 x 2 B |
Totals (weights + fixed state, before activations / graph pool ~210 MiB and the CUDA context ~410 MiB, E's measured overheads): control 4,562; native-experts-packed (K5 dense) 6,371; native-packed 6,473; native-hybrid (packed experts, bf16 dense) 6,792; native-expanded 16,310 MiB (15.9 GiB) -> ~17.0 GiB per card in nvidia-smi, ~7 GiB under the 24 GiB card. BF16 head arm +395 MiB; the exact factorized Markov drops the 1,012.5 MiB bias cache. 1M-token RoPE +176 MiB.
Load peak: the loader streams one matrix at a time (expanded: one decode, ~0.15 GB of temporaries; packed: one 6 MB copy), so the device peak is the serving footprint + ~0.15 GB plus whatever torch's caching allocator keeps reserved from those temporaries; the host peak is lane E's (identity verification of the K2/K5/K6 delivery, 6.9 GB RSS) plus one matrix; the official shards are memory-mapped (page cache, not process memory).
6. FP16 or BF16 (decided from the real values)
- Weights: every decoded FP4 / FP8 value of the draft is exact in BOTH fp16 and bf16 (manifest: |w| 2^-21..6).
- Activations: the QDQ'd activation
q * smust be bf16 (or the kernel keeps the e4m3 code q, exact in fp16, and applies s in fp32). The captured taps (main_proj's input, 2,749 rows of A-capture-20261022) reach |x| = 280,576 with per-32 scales up to 2^10, so QDQ'd values reach 448 x 2^10 = 458,752: an fp16 overflow (max 65,504). main_x (after main_norm) stays below 0.38. Downstream activations are normed (attention / FFN inputs) or clamped (SwiGLU: |h| <= silu(10) x 10 x route weight); measured per-layer ranges come with the GPU parity runs. - Choice: bf16 operands everywhere (both exact for the weights; bf16 has the range for the activations); fp16 only for code-domain operands with fp32 scale application. Router bias, gate scores and confidence projection: fp32. In the official BF16-head arms, base logits and Markov bias/sum are fp32. The four K6 serving arms retain the inherited engine policy: base logits, Markov bias and final sum round to BF16 (see §9); the K6 label is not an FP32-logit claim.
7. Measured (2026-10-23 04:19-04:55Z, GPU-7744b44b, 325 W owner cap, SM 1695-1980 MHz; results in offload/results/n1/)
Per card, one TP2 rank alone (solo rank 0: the rank's real shards and kernels, collectives replaced by same-shape stand-ins), 8 slots, 327,680 positions, graphs for B 1-4 x n_out 4/5 + inserts 8-128:
| arm | torch peak during load (MiB) | nvidia-smi after load / serving (MiB) | graphed step p50 B1 / B2 / B3 / B4 (us) |
|---|---|---|---|
| k2-tp2 (control) | 4,604 | 4,950 / 5,218 | 1,752 / 2,243 / 2,520 / 3,341 |
| native-hybrid-kx (MXFP4 experts, KX regfed; bf16 dense, cuBLAS) | 6,833 | 7,182 / 7,578 | 2,143 / 2,502 / 2,790 / 3,394 |
| native-packed-kx (MXFP4 experts KX; FP8 dense, N1 Triton) | 6,509 | 6,870 / 7,136 | 2,134 / 2,532 / 2,776 / 3,661 |
| native-expanded (bf16 experts + dense, N1 Triton experts) | 16,344 | 16,686 / 17,068 | 2,864 / 3,858 / 4,669 / 5,677 |
| native-hybrid (N1 Triton packed experts) | 6,836 | 7,176 / 7,560 | 5,584 / 9,600 / 12,963 / 17,158 |
| native-hybrid-head (+ bf16 head, exact fp32 Markov, no cache) | 6,218 | 6,560 / 6,950 | 6,157 / 10,242 / 13,648 / 17,700 |
| native-hybrid-head-hot (+ 4,096 exact fp32 hot rows) | 7,230 | 7,570 / 7,948 | 6,082 / 10,248 / 13,615 / 17,575 |
Host: max RSS during start-up 14.8 GB (native-hybrid / -expanded) and 15.3 GB (-kx, host shards per stage), including the file-backed pages of the memory-mapped official shards and lane E's checkpoint verification. Load: 9-11 s (N1 kernels), 135-140 s with KX regfed (per-expert admission + fragment prepack).
Fidelity on the live captures (A-capture-20261022, 453 rounds, 542 live blocks; TP2 emulated on one card; windows A = captured main_x, B = main_x from taps): blocks exact vs the engine's (K2) drafts: control 92.6 / 93.4 % (= lane E), native arms 58-63 % (they are different weights, as intended). Realized acceptance against the TARGET's own tokens (538 live blocks where it is determined; temperature 1.0: P(match) = p_target(draft), an unbiased per-position estimate): engine 1.810; k2-tp2 1.801 / 1.805; native-hybrid-kx 1.823 / 1.825 (vs control +0.022 +- 0.021 / +0.020 +- 0.027); native-hybrid 1.820 / 1.825; native-packed 1.823 / 1.820; native-experts-packed 1.822 / 1.818; k2-head 1.803 / 1.809; native-hybrid-head 1.807 / 1.805. Native arms trend +0.01-0.02 tokens per block over the control, within ~1 standard error: not established on 538 blocks; the in-engine A/B decides. Exactness checks: KX regfed vs N1 kernels 99.47 % identical blocks (fp32 order near-ties), hot-row vs factorized Markov 100 % identical, graph replay == eager for native-hybrid and native-hybrid-kx (B 1-4, n_out 4/5).
8. N2 native-hybrid-kx2 (experimental, opt-in)
native-hybrid-kx2 preserves native-hybrid-kx's official QDQ, FP32 router,
post-TP per-slot BF16 rounding and ascending-expert combination, and deployed
K6 draft head. It uses KXFusedBank with KX-FUSEDMOE's published
select_variant(stage, rows) / dispatch.json: mode 131072, except stage 1
at ten rows uses qualified mode 256. Workspaces and SLOT buffers are owned
by each rank, allocated before capture and reused on its ordered capture
stream. They cannot be shared across simultaneous independent streams.
KXSelectiveDense uses the delivered FP8 configuration(M) for the
measured draft operations at M5/M10/M15 and main_proj M8. The final preset
selects dense_profile="measured-small"; M20 and unlisted shapes use BF16. Both source representations are verified lossless at load;
activation QDQ remains the caller's responsibility. Candidate outputs and
split scratch are preallocated. Existing graph-captured PyTorch operations
elsewhere retain their previous allocation behavior. This is not a claim
that the entire eager drafter has become allocation-free. No head epilogue
is added; the grouped native head epilogue's FIX1 FP32 default is unchanged.
N2 tools live in native/tools/n2/. On X86host, stage the source into
~/dsv41-offload/n2/repo, then run queue.sh in detached tmux. Every job
uses run_locked.sh, pins only GPU-7744b44b, retains the inherited exclusive
lock and times out at 830s with at most 5s teardown. Logs include clocks,
power, temperature and the unchanged owner power limit. dense_screen
compares same-shard FP8/BF16 paths; inmodel_check audits actual model-call
activations against decoded-value FP64 and the prior register pipeline.
Detailed differences and captured parity dumps stay outside git.
pair.sh is for the coordinator only: it refuses execution unless PAIR_OK
names N2 or N2_PAIR_BY_COORD=1, locks both cards separately for every job,
and runs bench plus capture parity for K2, kx and kx2. This lane never runs
it. Solo timings do not establish the pair/engine performance objective.
Serving integration still needs worker.server native-arm construction,
V1-schema kv_window/s*.attn_out/main_x_P dumps and classification gates,
RX pair-safety qualification and the coordinator's E2/E3 engine window.
N2's selected dense_profile="measured-small" extends FP8 to every
measured draft dense operation at M5/M10/M15, including four-group wo_a. It
retains BF16 M20, main_proj M32/M128 and unlisted shapes. At T20 the shared
w1/w3 BF16 matrices are concatenated by output row and projected together;
each output still rounds to BF16. This removes a poor cuBLAS shape choice,
without changing weight values, scale alignment, activation QDQ or FP32
accumulation. The extra verified BF16 copy is 67.5 MiB per rank across stages.
The experiment also uses allocation-free shared SwiGLU+QDQ and post-TP ascending-ID combine epilogues under kernels/fp8dense/ and kernels/fusedmoe/. Both preserve the original arithmetic and rounding points and have exact old-pipeline/changed-input graph tests. Shared paired-GEMM rounding can differ from separate GEMMs; the model oracle lists those projection/HQ differences separately and checks the same BF16/FP64 gates. No FP16 narrowing, approximate exponential, atomic accumulation, host routing readback or missing QDQ is added.
For reproducible timing, native_bench now settles each B/n_out shape for 0.5s without changing clocks, then uses the original 200 event samples. It records per-case telemetry and all kernel names for both output counts. Historical first-case values with only ten warmups can include automatic-boost ramping; keep them separate from the settled repeated comparison. The N2 in-model oracle streams all detailed element differences to a local JSONL and stores aggregate metrics plus record references in its JSON. Both files remain outside git.
The final native-hybrid-kx2 preset selects measured-small. The original
wq_b5/main8-only experiment remains reproducible with an explicit
ArmConfig replacement dense_profile="initial"; native-hybrid-kx remains
the unchanged comparison/rollback arm. Final gates: 171 component tests,
all-shape full-emulated model FP64/N1 dense and expert-projection oracles,
and all eight graph/eager cases. Pair/engine qualification remains separate.
Final N2 repeated solo result (three interleaved repetitions, each 200 events):
all 16 rank/B/output-count targets pass, 3.45–10.91% below K2 by median p50.
For every case, the slowest observed kx2 run is below the fastest observed K2
run. See tools/n2/evidence/repeated-summary.json for all values/ranges, full
kernel-name medians, telemetry, memory and frozen-source hashes, and that
directory's README for reproduction. These are solo channel-shard timings;
physical pair, V1 causal/state and E2/E3 serving results remain unqualified.
9. N3 native serving and the V1 entry gate
worker.server --tp 2 accepts DSPARK_WORKER_ARM=native-packed|native-expanded|native-hybrid-kx|native-hybrid-kx2.
K2 remains the default. Native identities cover official shard provenance, exact arm config, retained K6 head provenance
and runtime/kernel source hashes; spark/tools/identity.py --arm ARM RECEIPT computes the matching Spark value.
The registered four active slots, negotiated max length, graph prewarm, status and RX poison/failure handling remain.
Missing shards, identity mismatch and failed prepack refuse; there is no implicit K2 fallback.
All four native serving arms keep the target-shared EXL3 K6 head. N4 corrects the inherited arithmetic: head outputs, Markov bias and their sum remain FP32. Native arms do not use the incompatible BF16 Markov cache. Attention uses the official online 64-key schedule, per-block BF16 probabilities, FP32 running state and sink last. It reads physical ring order, compacting short windows before the draft keys, into preallocated rank output storage. The pinned official TileLang CUDA uses full-precision expf/division and a contracted denominator update; the native port uses libdevice.exp, div_rn and explicit FMA. K2 retains its deployed arithmetic. K6 weights remain a representation difference from the official BF16 head; "native" does not imply universal bit identity across GPU reduction schedules.
N3 adds opt-in serving dumps (DSPARK_V1_DUMP_DIR, selected DSPARK_V1_ROUNDS) with actual insertion-graph main_x,
live window KV, routing and layer/head outputs. Each selected traced eager replay must equal its graph reply. The
independent V1 classifier remains unchanged, comparing mirror/mirror64 with strict state, attention and KL gates.
N3's historical 12-key packed pilot failed: two own-logit flags, s0 attention median excess600.402x and KL3.41x band.
Its BF16 policy reproduced those drafts; official FP32 recomposition caused the flags. N4's corrected packed/kx/kx2 pilots
clear state flags, unexplained disagreements and KL, but still fail strict stage-0 attention excess. A component
control using unmodified official GPU attention at stage0 and the official CPU reference elsewhere also fails that
attention gate (55.34x on these 12 samples); this is a calibration question, not a worker waiver. The real worker has
additional residual arithmetic differences. Do not classify the whole discrepancy as harmless or promote on graph
parity alone. A passing V1 verdict and physical-pair qualification remain prerequisites before GB10 promotion.
See the campaign N4 report for current verdicts and same-card cost measurements; historical N2/N3 timings used a
different GPU and power cap.
Current N4 solo/reproduction commands and memory scopes: tools/n4/README.md. Historical N3 serving/fake-client/V1/pair commands and depth recipe: tools/n3/README.md. The N3 solo wrapper pins the former development card; N4 uses its reassigned bc wrapper.
The pair script is coordinator-only and never changes a service or Spark. Expanded full TP2 emulation does not fit a
24GiB solo card; measure each real shard separately, then run the full serving/dump equality checks on the physical pair.