Skip to content

Commit 08df633

Browse files
committed
merge: integrate current main into release gate repairs
Preserve the reviewed #499/#500 release fixes while incorporating origin/main through 324603a. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Codex:GPT-5 [Codex]
2 parents 1a74d5c + 324603a commit 08df633

7 files changed

Lines changed: 178 additions & 85 deletions

File tree

.agents/benchmark-record.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19964,3 +19964,39 @@ num_tokens_past_padded (or per-call block count) on both sides for the same
1996419964
prompt and compare totals. Equal totals => our kernel is genuinely slower.
1996519965
Different totals => the gap is routing and the kernel comparison was never
1996619966
like-for-like.
19967+
19968+
## SPEC-DSPARK: routing REFUTED -- our Marlin MoE is 12.8% slower per unit of work (2026-08-12)
19969+
19970+
Measured on both sides (VT_MOE_PAD_STATS=1 ours; moe_align_block_size wrapped
19971+
upstream), same prompt, same k:
19972+
19973+
| | avg padded tokens / call | avg blocks / call | block size |
19974+
|---|---|---|---|
19975+
| ours | 311.2 | 38.9 | 8 |
19976+
| upstream | 324.8 | 40.6 | 8 |
19977+
19978+
Upstream loops 4.4% MORE blocks per launch and is still 8.2% faster, so the
19979+
divergent-routing explanation is dead. Normalising by the work performed makes
19980+
our deficit larger:
19981+
19982+
| | time | launches | blocks/launch | per block |
19983+
|---|---|---|---|---|
19984+
| ours | 249.2 ms | 1520 | 38.9 | 4.21 us |
19985+
| upstream | 230.4 ms | 1520 | 40.6 | 3.73 us |
19986+
19987+
~12.8% slower per unit of work. Both choose block_size 8, independently
19988+
confirming that upstream's >= 16 clamp does not bite on this shape.
19989+
19990+
Every input-side explanation is now eliminated: same kernel, same instantiation,
19991+
same grid rule, same scale layout, same alignment, same residency, and more work
19992+
on their side. What remains is how the kernel executes given identical inputs
19993+
(occupancy / shared-memory budget / max_shared_mem passed to the launcher).
19994+
19995+
Two diagnostic traps, both hit here: our probe read a device value inside the
19996+
verify, which W8 now CAPTURES ("cudaStreamSynchronize: operation not permitted
19997+
when stream is capturing"), and upstream's wrapper sat inside a torch.compile
19998+
region and broke compilation. Both counts are capture- and compile-independent,
19999+
so they run with VT_SPEC_DECODE_GRAPH=0 and enforce_eager respectively. A work
20000+
COUNT may be taken under different execution modes; a TIME may not.
20001+
20002+
Evidence: `dgx:~/work/dspark-w6/padcmp.log`, `oracle_pad.json`.

.agents/specs/dspark-spec-decode.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,51 @@ Recording this BEFORE acting, because every cheap explanation has now been
13791379
eliminated and the expensive one (rewrite the expert path) would be exactly the
13801380
wrong response to a routing difference.
13811381

1382+
## 6x. ROUTING REFUTED: our kernel is 12.8% slower PER UNIT OF WORK (2026-08-12)
1383+
1384+
§6w proposed that the 8.2% Marlin gap might not be a defect at all -- that our
1385+
divergent token stream routes to different experts, so the two engines execute
1386+
different amounts of expert work at the same launch count. Measured on both
1387+
sides (`VT_MOE_PAD_STATS=1` here; `moe_align_block_size` wrapped upstream), same
1388+
prompt, same k:
1389+
1390+
| | avg padded tokens / call | avg blocks / call | block size |
1391+
|---|---|---|---|
1392+
| ours | 311.2 | **38.9** | 8 |
1393+
| upstream | 324.8 | **40.6** | 8 |
1394+
1395+
**Upstream loops 4.4% MORE blocks per launch than we do, and is still 8.2%
1396+
faster.** The hypothesis is refuted, and it was protective: normalising time by
1397+
the work actually performed makes our deficit BIGGER, not smaller.
1398+
1399+
| | time | launches | blocks/launch | **per block** |
1400+
|---|---|---|---|---|
1401+
| ours | 249.2 ms | 1520 | 38.9 | **4.21 us** |
1402+
| upstream | 230.4 ms | 1520 | 40.6 | **3.73 us** |
1403+
1404+
**Our Marlin MoE is ~12.8% slower per unit of work.** Both also choose block_size 8,
1405+
which independently confirms §6v's conclusion that upstream's `>= 16` clamp does
1406+
not bite on this shape.
1407+
1408+
So the gap is a REAL in-kernel execution difference, now quantified per block and
1409+
with every input-side explanation eliminated (§6v, §6w): same kernel, same
1410+
instantiation, same grid rule, same scale layout, same alignment, same residency,
1411+
and now MORE work on their side. What remains is how the kernel executes given
1412+
identical inputs -- occupancy, shared-memory budget, or the `max_shared_mem`
1413+
value each side passes, which is the one launch input not yet compared.
1414+
1415+
**Two diagnostic traps recorded**, both hit while measuring this:
1416+
1417+
1. Our probe read a device value inside the verify, which W8 now CAPTURES:
1418+
`cudaStreamSynchronize: operation not permitted when stream is capturing`.
1419+
Our own capture work made the instrument illegal in that region; the count is
1420+
capture-independent, so it runs with `VT_SPEC_DECODE_GRAPH=0`.
1421+
2. Upstream's wrapper sat inside a `torch.compile` region and broke compilation;
1422+
the count is compile-independent, so it runs under `enforce_eager=True`.
1423+
1424+
Neither changes what is counted, and saying so is the point: a work COUNT may be
1425+
taken under different execution modes, a TIME may not.
1426+
13821427
## 7. Evidence, authority, stop conditions
13831428

13841429
- Evidence root: `dgx:~/work/vllm.cpp-dspark-<slice>/`, one `flock`, named tmux.

docs/BENCHMARKS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ in the tree, default-OFF, for reproducibility; detail in the benchmark record.
335335
| MTP | Qwen3.6-27B NVFP4 | token-identical to vLLM MTP, **~4% faster at c1**; on-par at c2-c8 | `DONE` |
336336
| DFlash | Qwen3.6-27B NVFP4 | **2.9x over spec-off** (10.16 → 29.32 tok/s), at/above vLLM DFlash-on (**1.003x**, non-overlapping bands) | `DONE` |
337337
| n-gram | Qwen3.6-27B NVFP4 | draft-free (`SPEC-NGRAM`); 27B 5/5 STRICT our-ngram-ON == vLLM-ngram-ON, 180/180 drafts accepted (correctness only, no speed row yet) | `DONE` |
338-
| DSpark | 27B NVFP4 dense k=15; 35B-A3B MoE k=8 | MoE **0.975x** code / **1.012x** prose vs the pinned graphed oracle (PINNED CLOCKS, non-overlapping). NOT parity: 8.2% sits in the SAME Marlin MoE kernel (others match to 0.2%); routing is the open suspect (#442) | `ACTIVE` |
338+
| DSpark | 27B NVFP4 dense k=15; 35B-A3B MoE k=8 | MoE **0.975x** code / **1.012x** prose vs the pinned graphed oracle (PINNED CLOCKS, non-overlapping). NOT parity: our Marlin MoE is **12.8% slower per unit of work** (routing refuted) (#442) | `ACTIVE` |
339339
| Breadth (EAGLE1/3, suffix, ngram-gpu, dynamic-k, ...) | n/a | enumerated from vLLM source + `INVENTORIED` 2026-08-06 (`.agents/specs/spec-decode-inventory.md`), unmeasured | `INVENTORIED` |
340340

341341
## How we measure

docs/FEATURES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ HTTP are not started.
201201
| EAGLE / EAGLE3 ||||
202202
| DFlash block diffusion | ✅ 2.9x over spec-off, at/above vLLM DFlash-on |||
203203
| n-gram / prompt lookup | ✅ 27B 5/5 strict vs vLLM |||
204-
| DSpark (semi-autoregressive block drafter) |**both gate models** ([spec](../.agents/specs/dspark-spec-decode.md)): token-identical to spec-off; the T=1+k verify is CAPTURED (`VT_SPEC_DECODE_GRAPH`). MoE **0.975x-1.012x** of the pinned oracle (pinned clocks) |||
204+
| DSpark (semi-autoregressive block drafter) |**both gate models** ([spec](../.agents/specs/dspark-spec-decode.md)): token-identical to spec-off; the T=1+k verify is CAPTURED. MoE **0.975x-1.012x** of the pinned oracle; residual is the Marlin MoE kernel |||
205205
| Other methods (ngram-gpu, suffix, custom-class, dynamic-k, mlp-speculator) | ☐ inventoried |||
206206

207207
## Structured output and tool calling

docs/STATUS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,11 +506,11 @@ upstream 230.39 ms -- **8.2% slower inside one kernel**, which at ~34% of wall i
506506
geometry either: the full template arguments match, `determine_exec_config` is
507507
byte-identical to the pinned upstream copy, and every OTHER kernel matches to
508508
0.2%. The inputs match too (scale bytes per expert,
509-
256-byte alignment, cudaMalloc residency), so the likeliest remaining cause is
510-
that the engines do not execute the same WORK: our token stream diverges from the
511-
oracle's by a near-tie, and different tokens route to different experts, which
512-
changes the kernel's block count at a fixed launch count. That must be measured
513-
before any kernel work. (The repack kernels that appear to take 40% of a long run are
509+
256-byte alignment, cudaMalloc residency), and the work counts were MEASURED:
510+
upstream loops 4.4% MORE blocks per launch (40.6 vs 38.9) and is still faster, so
511+
routing is refuted and normalising by work makes our deficit bigger -- **4.21 vs
512+
3.73 us per block, ~12.8% slower per unit of work**. The remaining unknown is how
513+
the kernel executes on identical inputs (occupancy / shared-memory budget). (The repack kernels that appear to take 40% of a long run are
514514
LOAD-TIME.) NOT parity. The Gemma4 `1 + N` layout is coded and unit-tested but has
515515
never run on real weights.
516516
Multimodal

scripts/env-doc-allowlist.txt

Lines changed: 60 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
1-
# Kernel-internal env vars (deferred from docs/ENVIRONMENT.md).
2-
# These are kernel implementation / micro-tuning / bisect switches whose
3-
# meaning is tied to a specific kernel; they are recorded in the ledger and
4-
# docs/BENCHMARKS.md, not on the deployment surface. scripts/check-env-doc.py
5-
# treats a name here as a known kernel-internal knob. A NEW production env
6-
# var must be documented in docs/ENVIRONMENT.md OR added here.
7-
# Inherited ROCm/Gemma-4 bring-up tactics. These are default-off diagnostic,
8-
# fallback, or experimental kernel behavior, not supported deployment knobs.
9-
VT_GEMMA4_BATCH_EXPERTS
10-
VT_GEMMA4_CUSTOM_EXPERT
11-
VT_GEMMA4_FP8_NATIVE
12-
VT_GEMMA4_FUSED_EXPERTS
13-
VT_GEMMA4_HOST_AXPY
14-
VT_GEMMA4_PROFILE
15-
VT_ROCM_GEMM_COMPUTE
16-
VT_ROCM_GEMV
17-
VT_ROCM_HIPBLASLT
1+
VLLM_CPP_QWEN3_DENSE_DECODE_GRAPH
2+
VLLM_GEMMA4_MM_DEBUG
183
VLLM_MM_TOWER_PROFILE
194
VT_ARCH_TACTIC_STATS
5+
VT_ASYNC_EXECUTOR_NO_DBUF
6+
VT_ASYNC_EXECUTOR_POISON
7+
VT_ASYNC_EXECUTOR_TRACE
208
VT_ATTN_DECODE_D128
219
VT_ATTN_DECODE_GQA
2210
VT_ATTN_DECODE_OPT
@@ -37,6 +25,7 @@ VT_DEEPSEEK_GRAPH_VERIFY
3725
VT_DENSE_CUBLASLT_FP8
3826
VT_DENSE_NATIVE
3927
VT_DIRECT_DEVICE_LOAD
28+
VT_DUMP_ACT
4029
VT_FA2_DECODE_35B
4130
VT_FA2_DECODE_QWEN3
4231
VT_FA2_NSPLITS_CAP
@@ -123,9 +112,29 @@ VT_GLUE_FUSE
123112
VT_INTERNLM2_WRONG_SPLIT
124113
VT_KDA_CHUNK_TRITON
125114
VT_KV_ALLOC_LOG
115+
VT_LAGUNA_DECODE_GRAPH
116+
VT_LAGUNA_FAST_NORM
117+
VT_LAGUNA_GLUE_FUSED
118+
VT_LAGUNA_GROUPED_MOE
119+
VT_LAGUNA_KV_BF16
120+
VT_LAGUNA_KV_HEADROOM
121+
VT_LAGUNA_MARLIN_MOE
122+
VT_LAGUNA_MOE_ADDNORM_FUSED
123+
VT_LAGUNA_MOE_ONECAST
124+
VT_LAGUNA_ONDEV_SAMPLE
125+
VT_LAGUNA_PREAMBLE_FUSED
126+
VT_LAGUNA_RESIDENT_BF16W
127+
VT_LAGUNA_RESIDENT_DECODE
128+
VT_LAGUNA_RESIDENT_MOE
129+
VT_LAGUNA_SHARED_AUX
130+
VT_LAGUNA_SHARED_FP4
131+
VT_LAGUNA_SWA_WINDOW
132+
VT_LAGUNA_TAIL_FUSED
133+
VT_LAGUNA_TOPK_SHFL
126134
VT_LOAD_WINDOWED_RELEASE
127135
VT_LOGITS_GATHER
128136
VT_MARLIN_WS_POOL
137+
VT_MLA_FUSED_NORM_ROPE
129138
VT_MLA_SPLIT_FILL
130139
VT_MOE_BF16_FAST
131140
VT_MOE_BF16_FUSED_GATEUP
@@ -134,16 +143,19 @@ VT_MOE_DECODE
134143
VT_MOE_FUSED_W13
135144
VT_MOE_GLUE_FUSE
136145
VT_MOE_HOST_FREE
146+
VT_MOE_PAD_STATS
137147
VT_MOE_SHARED_AUX_STREAM
138148
VT_MOE_SHARED_AUX_THRESHOLD
139149
VT_MOE_SPLIT_K
140150
VT_NVFP4_CUTLASS
151+
VT_NVFP4_FP4_GEMV
141152
VT_NVFP4_FP4_NATIVE
142153
VT_NVFP4_MARLIN
143154
VT_NVFP4_WMMA
144155
VT_PAGED_FLASH
145156
VT_POOL_EXACT
146157
VT_POOL_STATS
158+
VT_QWEN35_GROUPED_MOE
147159
VT_QWEN3MOE_CUDAGRAPH
148160
VT_QWEN3_ATTN_F32
149161
VT_QWEN3_QKV_MERGE
@@ -155,81 +167,51 @@ VT_ROCM_GEMM_COMPUTE
155167
VT_ROCM_GEMV
156168
VT_ROCM_HIPBLASLT
157169
VT_SILU_FP4_FAST
158-
VT_SWIZZLE_IN_QUANT
159-
VT_W4A4_TRUE
160-
VLLM_GEMMA4_MM_DEBUG
161170
VT_SPEC_TRACE
162-
VT_DUMP_ACT
163-
VT_V4_PROF
164-
VT_V4_GROUPED_MOE
171+
VT_SWIZZLE_IN_QUANT
172+
VT_V4_DECODE_GRAPH
165173
VT_V4_DEVICE_ATTN
166174
VT_V4_DEVICE_GLUE
167-
VT_V4_RESIDENT_DECODE
168-
VT_V4_DECODE_GRAPH
169-
VT_V4_Q8_0_ALIGN
170175
VT_V4_FUSED_MOE
171176
VT_V4_FUSED_ROPE
177+
VT_V4_GROUPED_MOE
172178
VT_V4_MHC_FUSED
173179
VT_V4_MHC_LEAN
174180
VT_V4_MHC_SINK4
175-
VT_V4_Q8_PREQ_QUANT
176181
VT_V4_PREQ_FUSED
177-
VT_V4_ROPE_FLOAT
178-
VT_V4_ROUTE_WARP_TOPK
179-
VT_V4_Q8_SUBWARP
180-
VT_V4_Q8_PAIR
181-
VT_V4_Q8_PROBE
182+
VT_V4_PROF
183+
VT_V4_Q8_0_ALIGN
182184
VT_V4_Q8_ILP
185+
VT_V4_Q8_PAIR
183186
VT_V4_Q8_PREFETCH
184-
VT_V4_RESIDENT_W
187+
VT_V4_Q8_PREQ_QUANT
188+
VT_V4_Q8_PROBE
189+
VT_V4_Q8_SUBWARP
190+
VT_V4_RESIDENT_DECODE
185191
VT_V4_RESIDENT_EXPERTS
186-
VT_MLA_FUSED_NORM_ROPE
187-
VT_LAGUNA_GROUPED_MOE
188-
VT_QWEN35_GROUPED_MOE
189-
VT_LAGUNA_RESIDENT_DECODE
190-
VT_LAGUNA_RESIDENT_MOE
191-
VT_LAGUNA_RESIDENT_BF16W
192-
VT_NVFP4_FP4_GEMV
193-
VT_LAGUNA_DECODE_GRAPH
194-
VT_LAGUNA_MARLIN_MOE
195-
VT_LAGUNA_GLUE_FUSED
196-
VT_LAGUNA_ONDEV_SAMPLE
197-
VT_LAGUNA_MOE_ADDNORM_FUSED
198-
VT_LAGUNA_SHARED_FP4
199-
VT_LAGUNA_SHARED_AUX
200-
VT_LAGUNA_PREAMBLE_FUSED
201-
VT_LAGUNA_MOE_ONECAST
202-
VT_LAGUNA_TAIL_FUSED
203-
VT_LAGUNA_FAST_NORM
204-
VT_LAGUNA_TOPK_SHFL
205-
VT_LAGUNA_SWA_WINDOW
206-
VT_LAGUNA_KV_BF16
207-
VT_LAGUNA_KV_HEADROOM
208-
VLLM_CPP_QWEN3_DENSE_DECODE_GRAPH
209-
# Test-only escape hatch: skip the depth-2 drain (VT_ASYNC_EXECUTOR=1) while
210-
# forcing the decode-graph parity ring OFF (single slot), so the async-serving gate
211-
# SEES the logits/input reuse hazard (a RED arm). Never set in production.
212-
VT_ASYNC_EXECUTOR_NO_DBUF
213-
# Test-only: deterministic RED for Option A — poison the PINNED H2D source right
214-
# after StageStepInputs enqueues the async copy (a true-async DMA reads the garbage),
215-
# proving the input-staged event boundary is load-bearing. Also a drain-skip counter
192+
VT_V4_RESIDENT_W
193+
VT_V4_ROPE_FLOAT
194+
VT_V4_ROUTE_WARP_TOPK
195+
VT_W4A4_TRUE
216196
# (VT_ASYNC_EXECUTOR_TRACE). Never set in production.
217-
VT_ASYNC_EXECUTOR_POISON
218-
VT_ASYNC_EXECUTOR_TRACE
219-
220197
# Gemma-4 MoE expert-execution tuning (#154, gemma4_moe.cpp / gemma4.cpp). Each
221-
# selects a kernel or a batching strategy for the expert GEMMs and each
222-
# defaults to the measured-best path; none changes an API contract or an output.
198+
# Inherited ROCm/Gemma-4 bring-up tactics. These are default-off diagnostic,
199+
# Kernel-internal env vars (deferred from docs/ENVIRONMENT.md).
223200
# Kernel-internal, so allowlisted rather than documented as user knobs.
224-
VT_GEMMA4_BATCH_EXPERTS
225-
VT_GEMMA4_CUSTOM_EXPERT
226-
VT_GEMMA4_FP8_NATIVE
227-
VT_GEMMA4_FUSED_EXPERTS
228-
VT_GEMMA4_HOST_AXPY
229-
VT_GEMMA4_PROFILE
230201
# ROCm GEMM/GEMV tactic selection (rocm_matmul_hipblaslt.hip). Same class: they
231-
# pick between hipBLASLt and our own kernels, all defaulting to the faster arm
202+
# SEES the logits/input reuse hazard (a RED arm). Never set in production.
203+
# Test-only escape hatch: skip the depth-2 drain (VT_ASYNC_EXECUTOR=1) while
204+
# Test-only: deterministic RED for Option A — poison the PINNED H2D source right
205+
# These are kernel implementation / micro-tuning / bisect switches whose
206+
# after StageStepInputs enqueues the async copy (a true-async DMA reads the garbage),
207+
# defaults to the measured-best path; none changes an API contract or an output.
208+
# docs/BENCHMARKS.md, not on the deployment surface. scripts/check-env-doc.py
209+
# fallback, or experimental kernel behavior, not supported deployment knobs.
210+
# forcing the decode-graph parity ring OFF (single slot), so the async-serving gate
211+
# meaning is tied to a specific kernel; they are recorded in the ledger and
232212
# measured on gfx1201.
233-
VT_ROCM_GEMM_COMPUTE
234-
VT_ROCM_GEMV
235-
VT_ROCM_HIPBLASLT
213+
# pick between hipBLASLt and our own kernels, all defaulting to the faster arm
214+
# proving the input-staged event boundary is load-bearing. Also a drain-skip counter
215+
# selects a kernel or a batching strategy for the expert GEMMs and each
216+
# treats a name here as a known kernel-internal knob. A NEW production env
217+
# var must be documented in docs/ENVIRONMENT.md OR added here.

src/vllm/model_executor/models/qwen3_5.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5519,6 +5519,36 @@ DBuf MoeBlockFusedMarlinCuda(Dev d, const MoeBlockWeights& w, const HfConfig& cf
55195519
static_cast<int32_t*>(sorted_ids.t().data), static_cast<int32_t*>(expert_ids.t().data),
55205520
static_cast<int32_t*>(num_pad.t().data));
55215521

5522+
// SPEC-DSPARK #442 diagnostic (VT_MOE_PAD_STATS=1, DEFAULT OFF, adds a D2H
5523+
// sync so it must never be on for a timing run). The Marlin MoE kernel loops
5524+
// div_ceil(num_tokens_past_padded, block) blocks PER LAUNCH, so two engines can
5525+
// launch it the same number of times and still do different amounts of work if
5526+
// their tokens route to different numbers of experts. Ours and upstream's token
5527+
// streams DIVERGE by a near-tie, so this is what decides whether the measured
5528+
// 8.2% kernel gap is an implementation defect or just a different token path.
5529+
static const bool pad_stats = [] {
5530+
const char* v = std::getenv("VT_MOE_PAD_STATS");
5531+
return v != nullptr && v[0] == '1';
5532+
}();
5533+
if (pad_stats) {
5534+
int32_t npad = 0;
5535+
d.b.Copy(d.q, &npad, num_pad.t().data, sizeof(int32_t));
5536+
d.b.Synchronize(d.q);
5537+
static int64_t calls = 0, sum_pad = 0, sum_blocks = 0;
5538+
++calls;
5539+
sum_pad += npad;
5540+
sum_blocks += (npad + block - 1) / block;
5541+
if (calls % 500 == 0)
5542+
std::fprintf(stderr,
5543+
"[MOE-PAD] calls=%lld padded_tokens_total=%lld blocks_total=%lld "
5544+
"avg_pad=%.1f avg_blocks=%.1f (block=%d T=%d topk=%d E=%d)\n",
5545+
static_cast<long long>(calls), static_cast<long long>(sum_pad),
5546+
static_cast<long long>(sum_blocks),
5547+
static_cast<double>(sum_pad) / calls,
5548+
static_cast<double>(sum_blocks) / calls, block, static_cast<int>(T),
5549+
static_cast<int>(top_k), static_cast<int>(E));
5550+
}
5551+
55225552
Tensor wd = MakeTensor(mr.w_down, DType::kI32, d.q.device, {E, I / 16, H * 2});
55235553
Tensor sd = MakeTensor(mr.s_down, DType::kI8, d.q.device, {E, I / 16, H});
55245554
Tensor gd = MakeTensor(mr.g_down, DType::kF32, d.q.device, {E});

0 commit comments

Comments
 (0)