Add files using upload-large-folder tool
Browse files- README.md +2 -2
- code/models/autoports/qwen_qwen3_5_122b_a10b/tt/moe_dispatch.py +76 -4
- code/models/autoports/qwen_qwen3_5_122b_a10b/tt/optimized_decoder.py +65 -4
- image/index.json +1 -1
- image/manifest.json +1 -1
- requirements.lock +13 -13
- tt_kernel_manifest.json +11 -11
README.md
CHANGED
|
@@ -54,6 +54,6 @@ The exact sources the image was built from — `code/` in this repo is byte-iden
|
|
| 54 |
| tt-metal | a local checkout — commit not published *(dirty tree — the image includes uncommitted changes)* |
|
| 55 |
| vLLM | [`v0.26.0`](https://github.com/vllm-project/vllm/releases/tag/v0.26.0) |
|
| 56 |
| vllm-tt-plugin | a local checkout — commit not published |
|
| 57 |
-
| `code/` digest | `
|
| 58 |
-
| built | 2026-09-
|
| 59 |
|
|
|
|
| 54 |
| tt-metal | a local checkout — commit not published *(dirty tree — the image includes uncommitted changes)* |
|
| 55 |
| vLLM | [`v0.26.0`](https://github.com/vllm-project/vllm/releases/tag/v0.26.0) |
|
| 56 |
| vllm-tt-plugin | a local checkout — commit not published |
|
| 57 |
+
| `code/` digest | `3e629a797061595a` (sha256, first 16 hex digits) |
|
| 58 |
+
| built | 2026-09-29T16:25:00+00:00 by tt-model 0.1.0 |
|
| 59 |
|
code/models/autoports/qwen_qwen3_5_122b_a10b/tt/moe_dispatch.py
CHANGED
|
@@ -21,6 +21,8 @@ from __future__ import annotations
|
|
| 21 |
|
| 22 |
import os
|
| 23 |
|
|
|
|
|
|
|
| 24 |
import ttnn
|
| 25 |
|
| 26 |
TILE = 32
|
|
@@ -47,7 +49,12 @@ def dispatch_rows(T: int, k: int, E: int, group: int = TILE) -> int:
|
|
| 47 |
# "sort_u16": ttnn.sort on uint16 ids (DRAM multi-core factory; hang-free but ~4 ms per 512-token chunk);
|
| 48 |
# "sort_fp32": the original fp32 ttnn.sort (cross-core-exchange factory; its sort_barrier deadlocks intermittently on
|
| 49 |
# one device of the (1,4) mesh - the 48-layer warm-up hang, doc/full_model/triage/warm_hang_*.txt).
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
SORT_ON_UINT16 = DISPATCH_MODE == "sort_u16"
|
| 52 |
|
| 53 |
|
|
@@ -85,13 +92,71 @@ class SortedDispatch:
|
|
| 85 |
"zeros_g": ttnn.zeros((1, 1, 1, G), dtype=u32, layout=RM, device=dev),
|
| 86 |
"zeros_rp": ttnn.zeros((1, 1, 1, Rp), dtype=u32, layout=RM, device=dev),
|
| 87 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
if len(self._const) >= CONST_CACHE_ENTRIES: # bounded: drop the oldest length's constants
|
| 89 |
oldest = next(iter(self._const))
|
| 90 |
for t in self._const.pop(oldest).values():
|
| 91 |
-
|
|
|
|
| 92 |
self._const[T] = c
|
| 93 |
return c
|
| 94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
@staticmethod
|
| 96 |
def _f32(t):
|
| 97 |
return t if t.dtype == ttnn.float32 else ttnn.typecast(t, ttnn.float32)
|
|
@@ -134,7 +199,7 @@ class SortedDispatch:
|
|
| 134 |
f32_ckc = ttnn.WormholeComputeKernelConfig(
|
| 135 |
math_fidelity=ttnn.MathFidelity.HiFi4, math_approx_mode=False, fp32_dest_acc_en=True, packer_l1_acc=False
|
| 136 |
)
|
| 137 |
-
if DISPATCH_MODE in ("counting", "counting_h"):
|
| 138 |
# ---- counting sort (no ttnn.sort): every token-major row i keeps its position; its destination is
|
| 139 |
# offsets[e_i] + (rank of i among the rows of expert e_i). The rank is the running count of the one-hot
|
| 140 |
# along the token axis, picked through the one-hot. All integers stay exact: counts/cumsum in fp32,
|
|
@@ -209,7 +274,10 @@ class SortedDispatch:
|
|
| 209 |
off_i = ttnn.add(ttnn.multiply(sel_hi, 256.0), sel_lo) # [1,1,Rp,1]
|
| 210 |
ttnn.deallocate(sel_hi)
|
| 211 |
ttnn.deallocate(sel_lo)
|
| 212 |
-
|
|
|
|
|
|
|
|
|
|
| 213 |
cs_hi = ttnn.floor(ttnn.multiply(cs, 1.0 / 256.0))
|
| 214 |
cs_lo = ttnn.subtract(cs, ttnn.multiply(cs_hi, 256.0))
|
| 215 |
ttnn.deallocate(cs)
|
|
@@ -337,6 +405,9 @@ class SortedDispatch:
|
|
| 337 |
ttnn.deallocate(grp_of_row)
|
| 338 |
if src_ids is not sorted_ids:
|
| 339 |
ttnn.deallocate(src_ids)
|
|
|
|
|
|
|
|
|
|
| 340 |
grp_f = self._f32(ttnn.to_layout(grp_expert, ttnn.TILE_LAYOUT))
|
| 341 |
ttnn.deallocate(grp_expert)
|
| 342 |
group_mask = ttnn.eq(ttnn.reshape(grp_f, (1, G, 1, 1)), self.arange_E) # [1,G,1,E] fp32 one-hot
|
|
@@ -362,6 +433,7 @@ class SortedDispatch:
|
|
| 362 |
"src_tok": src_tok_rm,
|
| 363 |
"weights": weights,
|
| 364 |
"group_mask": group_mask,
|
|
|
|
| 365 |
"undispatch": undispatch,
|
| 366 |
"Rd": Rd,
|
| 367 |
"G": G,
|
|
|
|
| 21 |
|
| 22 |
import os
|
| 23 |
|
| 24 |
+
import torch
|
| 25 |
+
|
| 26 |
import ttnn
|
| 27 |
|
| 28 |
TILE = 32
|
|
|
|
| 49 |
# "sort_u16": ttnn.sort on uint16 ids (DRAM multi-core factory; hang-free but ~4 ms per 512-token chunk);
|
| 50 |
# "sort_fp32": the original fp32 ttnn.sort (cross-core-exchange factory; its sort_barrier deadlocks intermittently on
|
| 51 |
# one device of the (1,4) mesh - the 48-layer warm-up hang, doc/full_model/triage/warm_hang_*.txt).
|
| 52 |
+
# "counting_mm" (default, stage 12): counting sort whose running count is a BLOCK-TRIANGULAR MATMUL (fp32 accumulate, exact
|
| 53 |
+
# integers) instead of ttnn.cumsum on the [Rp, E] one-hot: the dim-2 cumsum ran on ~4 cores and needed two full-tensor
|
| 54 |
+
# permutes (25 of the 53 ms MoE device time per 2048-token layer, stage-12 profile); the matmuls use the whole grid.
|
| 55 |
+
DISPATCH_MODE = os.environ.get(
|
| 56 |
+
"QWEN35_DISPATCH_MODE", "counting_mm"
|
| 57 |
+
) # "counting_mm" | "counting_h" | "counting" | "sort_u16" | "sort_fp32"
|
| 58 |
SORT_ON_UINT16 = DISPATCH_MODE == "sort_u16"
|
| 59 |
|
| 60 |
|
|
|
|
| 92 |
"zeros_g": ttnn.zeros((1, 1, 1, G), dtype=u32, layout=RM, device=dev),
|
| 93 |
"zeros_rp": ttnn.zeros((1, 1, 1, Rp), dtype=u32, layout=RM, device=dev),
|
| 94 |
}
|
| 95 |
+
if DISPATCH_MODE == "counting_mm":
|
| 96 |
+
# block-triangular running count: rows in blocks of Bk (the smallest tile multiple giving at most 32
|
| 97 |
+
# blocks, so the block prefix is one 32 x 32 tile); Rp is zero-padded up to nb * Bk when Bk does not
|
| 98 |
+
# divide it (e.g. T=500: Rp=4000 -> Bk=128, 32 blocks, Rp_pad=4096). L = lower-triangular ones incl. the
|
| 99 |
+
# diagonal (within-block inclusive count), P = strictly-lower-triangular ones over the (up to 32) blocks
|
| 100 |
+
Bk = TILE * (-(-Rp // (32 * TILE)))
|
| 101 |
+
nb = -(-Rp // Bk)
|
| 102 |
+
assert nb <= 32 and nb * Bk >= Rp, (Rp, Bk, nb)
|
| 103 |
+
c["Rp_pad"] = nb * Bk
|
| 104 |
+
L = torch.tril(torch.ones(Bk, Bk, dtype=torch.float32))
|
| 105 |
+
P = torch.tril(torch.ones(32, 32, dtype=torch.float32), diagonal=-1)
|
| 106 |
+
c["Bk"] = Bk
|
| 107 |
+
c["nb"] = nb
|
| 108 |
+
c["L_tri"] = ttnn.from_torch(L.reshape(1, 1, Bk, Bk), dtype=f32, layout=ttnn.TILE_LAYOUT, device=dev)
|
| 109 |
+
c["P_excl"] = ttnn.from_torch(P.reshape(1, 1, 32, 32), dtype=f32, layout=ttnn.TILE_LAYOUT, device=dev)
|
| 110 |
+
c["ones_row_bk"] = ttnn.full((1, 1, TILE, Bk), 1.0, dtype=f32, layout=ttnn.TILE_LAYOUT, device=dev)
|
| 111 |
if len(self._const) >= CONST_CACHE_ENTRIES: # bounded: drop the oldest length's constants
|
| 112 |
oldest = next(iter(self._const))
|
| 113 |
for t in self._const.pop(oldest).values():
|
| 114 |
+
if not isinstance(t, int):
|
| 115 |
+
ttnn.deallocate(t)
|
| 116 |
self._const[T] = c
|
| 117 |
return c
|
| 118 |
|
| 119 |
+
def _running_count_mm(self, oh, consts, Rp, E, f32_ckc):
|
| 120 |
+
"""Inclusive running count of the one-hot rows along the token axis (== ttnn.cumsum(oh, dim=2)) as matmuls:
|
| 121 |
+
within each block of Bk rows ``L_tri @ oh_block`` (batched over the blocks), plus the exclusive prefix of the
|
| 122 |
+
block totals (``P_excl @ totals``) broadcast over the block's rows. All operands are 0/1 or small integers, the
|
| 123 |
+
accumulation is fp32, so every count is exact."""
|
| 124 |
+
Bk, nb, Rp_pad = consts["Bk"], consts["nb"], consts["Rp_pad"]
|
| 125 |
+
f32 = ttnn.float32
|
| 126 |
+
dram = ttnn.DRAM_MEMORY_CONFIG
|
| 127 |
+
oh_src = oh
|
| 128 |
+
if Rp_pad > Rp: # zero rows appended: they add nothing to any count and are sliced off below
|
| 129 |
+
oh_src = ttnn.pad(oh, [(0, 0), (0, 0), (0, Rp_pad - Rp), (0, 0)], value=0.0)
|
| 130 |
+
oh_b = ttnn.reshape(oh_src, (1, nb, Bk, E)) # tile-aligned view: Bk % 32 == 0
|
| 131 |
+
cs_local = ttnn.matmul(consts["L_tri"], oh_b, compute_kernel_config=f32_ckc, dtype=f32, memory_config=dram)
|
| 132 |
+
if nb > 1:
|
| 133 |
+
tot = ttnn.matmul(consts["ones_row_bk"], oh_b, compute_kernel_config=f32_ckc, dtype=f32, memory_config=dram)
|
| 134 |
+
tot = ttnn.slice(tot, (0, 0, 0, 0), (1, nb, 1, E)) # [1,nb,1,E]: block totals (row 0 of every 32-row block)
|
| 135 |
+
tot_rows = ttnn.reshape(ttnn.to_layout(tot, ttnn.ROW_MAJOR_LAYOUT), (1, 1, nb, E))
|
| 136 |
+
ttnn.deallocate(tot)
|
| 137 |
+
if nb < 32:
|
| 138 |
+
tot_rows = ttnn.pad(tot_rows, [(0, 0), (0, 0), (0, 32 - nb), (0, 0)], value=0.0)
|
| 139 |
+
tot_rows = ttnn.to_layout(tot_rows, ttnn.TILE_LAYOUT)
|
| 140 |
+
pre = ttnn.matmul(consts["P_excl"], tot_rows, compute_kernel_config=f32_ckc, dtype=f32, memory_config=dram)
|
| 141 |
+
ttnn.deallocate(tot_rows) # [1,1,32,E]: exclusive block prefix in rows 0..nb-1
|
| 142 |
+
pre_rows = ttnn.reshape(
|
| 143 |
+
ttnn.to_layout(ttnn.slice(pre, (0, 0, 0, 0), (1, 1, nb, E)), ttnn.ROW_MAJOR_LAYOUT), (1, nb, 1, E)
|
| 144 |
+
)
|
| 145 |
+
ttnn.deallocate(pre)
|
| 146 |
+
pre_rows = ttnn.to_layout(pre_rows, ttnn.TILE_LAYOUT)
|
| 147 |
+
cs = ttnn.add(cs_local, pre_rows, memory_config=dram) # broadcast over the Bk rows of every block
|
| 148 |
+
ttnn.deallocate(cs_local)
|
| 149 |
+
ttnn.deallocate(pre_rows)
|
| 150 |
+
else:
|
| 151 |
+
cs = cs_local
|
| 152 |
+
cs = ttnn.reshape(cs, (1, 1, Rp_pad, E))
|
| 153 |
+
if Rp_pad > Rp:
|
| 154 |
+
ttnn.deallocate(oh_src)
|
| 155 |
+
full = cs
|
| 156 |
+
cs = ttnn.slice(full, (0, 0, 0, 0), (1, 1, Rp, E), memory_config=dram)
|
| 157 |
+
ttnn.deallocate(full)
|
| 158 |
+
return cs
|
| 159 |
+
|
| 160 |
@staticmethod
|
| 161 |
def _f32(t):
|
| 162 |
return t if t.dtype == ttnn.float32 else ttnn.typecast(t, ttnn.float32)
|
|
|
|
| 199 |
f32_ckc = ttnn.WormholeComputeKernelConfig(
|
| 200 |
math_fidelity=ttnn.MathFidelity.HiFi4, math_approx_mode=False, fp32_dest_acc_en=True, packer_l1_acc=False
|
| 201 |
)
|
| 202 |
+
if DISPATCH_MODE in ("counting", "counting_h", "counting_mm"):
|
| 203 |
# ---- counting sort (no ttnn.sort): every token-major row i keeps its position; its destination is
|
| 204 |
# offsets[e_i] + (rank of i among the rows of expert e_i). The rank is the running count of the one-hot
|
| 205 |
# along the token axis, picked through the one-hot. All integers stay exact: counts/cumsum in fp32,
|
|
|
|
| 274 |
off_i = ttnn.add(ttnn.multiply(sel_hi, 256.0), sel_lo) # [1,1,Rp,1]
|
| 275 |
ttnn.deallocate(sel_hi)
|
| 276 |
ttnn.deallocate(sel_lo)
|
| 277 |
+
if DISPATCH_MODE == "counting_mm":
|
| 278 |
+
cs = self._running_count_mm(oh, consts, Rp, E, f32_ckc) # [1,1,Rp,E] fp32, == cumsum(oh, dim=2)
|
| 279 |
+
else:
|
| 280 |
+
cs = ttnn.cumsum(oh, dim=2, dtype=f32) # [1,1,Rp,E]
|
| 281 |
cs_hi = ttnn.floor(ttnn.multiply(cs, 1.0 / 256.0))
|
| 282 |
cs_lo = ttnn.subtract(cs, ttnn.multiply(cs_hi, 256.0))
|
| 283 |
ttnn.deallocate(cs)
|
|
|
|
| 405 |
ttnn.deallocate(grp_of_row)
|
| 406 |
if src_ids is not sorted_ids:
|
| 407 |
ttnn.deallocate(src_ids)
|
| 408 |
+
# expert id of every group as the uint16 ROW_MAJOR stick the group-parallel sparse matmul (`indices=`) reads;
|
| 409 |
+
# padding groups carry expert 0 (their rows are zero-weighted and never read back)
|
| 410 |
+
group_ids = ttnn.reshape(ttnn.typecast(grp_expert, ttnn.uint16), (1, G)) # uint32 RM -> uint16 RM [1, G]
|
| 411 |
grp_f = self._f32(ttnn.to_layout(grp_expert, ttnn.TILE_LAYOUT))
|
| 412 |
ttnn.deallocate(grp_expert)
|
| 413 |
group_mask = ttnn.eq(ttnn.reshape(grp_f, (1, G, 1, 1)), self.arange_E) # [1,G,1,E] fp32 one-hot
|
|
|
|
| 433 |
"src_tok": src_tok_rm,
|
| 434 |
"weights": weights,
|
| 435 |
"group_mask": group_mask,
|
| 436 |
+
"group_ids": group_ids,
|
| 437 |
"undispatch": undispatch,
|
| 438 |
"Rd": Rd,
|
| 439 |
"G": G,
|
code/models/autoports/qwen_qwen3_5_122b_a10b/tt/optimized_decoder.py
CHANGED
|
@@ -74,6 +74,13 @@ class OptimizationConfig:
|
|
| 74 |
sorted_gate_up_in0: int = 32
|
| 75 |
sorted_down_cores: int = 64
|
| 76 |
sorted_down_in0: int = 32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
# --- decode matmul program configs (round 2, from the stage-2 profile) ---
|
| 78 |
# router gate matmul [32,H]x[H,256]: "ttnn" (auto), "derived" (TTMoEGate 2D-mcast derivation), "1d8" (1D, 8 cores)
|
| 79 |
router_decode_pc: str = "derived"
|
|
@@ -397,14 +404,22 @@ class Qwen35MoEOptimized(Qwen35MoEFused):
|
|
| 397 |
x_disp = gather_rows(x4, m["src_tok"], Rd, gs) # [1,G,gs,H]
|
| 398 |
ttnn.deallocate(m["src_tok"])
|
| 399 |
narrow = self.tile_gu.tile_shape[1] != 32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
out_gu = None if narrow else self._alloc_dev((1, G, gs, 2 * Nl), act)
|
| 401 |
fused = ttnn.sparse_matmul(
|
| 402 |
x_disp,
|
| 403 |
self.up_gate,
|
| 404 |
sparsity=m["group_mask"],
|
| 405 |
-
|
| 406 |
memory_config=ttnn.DRAM_MEMORY_CONFIG,
|
| 407 |
-
program_config=
|
| 408 |
**({"output_tile": self.tile_gu} if narrow else {"optional_output_tensor": out_gu}),
|
| 409 |
compute_kernel_config=self.routed_ckc,
|
| 410 |
dtype=act,
|
|
@@ -421,22 +436,68 @@ class Qwen35MoEOptimized(Qwen35MoEFused):
|
|
| 421 |
din,
|
| 422 |
self.down,
|
| 423 |
sparsity=m["group_mask"],
|
| 424 |
-
|
| 425 |
optional_output_tensor=out_dn,
|
| 426 |
is_input_a_sparse=False,
|
| 427 |
is_input_b_sparse=True,
|
| 428 |
memory_config=ttnn.DRAM_MEMORY_CONFIG,
|
| 429 |
-
program_config=
|
| 430 |
compute_kernel_config=self.routed_ckc,
|
| 431 |
dtype=act,
|
| 432 |
) # compact [1,G,32,H]
|
| 433 |
ttnn.deallocate(din)
|
| 434 |
ttnn.deallocate(m["group_mask"])
|
|
|
|
| 435 |
y = undispatch_rows(down, None, m["undispatch"], T, k, H)
|
| 436 |
ttnn.deallocate(down)
|
| 437 |
ttnn.deallocate(m["undispatch"])
|
| 438 |
return y
|
| 439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
def _route(self, x4):
|
| 441 |
if self._gate_pc_decode is not None:
|
| 442 |
self.gate.matmul_program_config = self._gate_pc_decode if _is_single_tile_rows(x4) else None
|
|
|
|
| 74 |
sorted_gate_up_in0: int = 32
|
| 75 |
sorted_down_cores: int = 64
|
| 76 |
sorted_down_in0: int = 32
|
| 77 |
+
# stage 12: group-parallel sparse matmul (MatmulMultiCoreReuseProgramConfig + `indices`): the expert groups are split
|
| 78 |
+
# across the whole core grid (each core reads its groups' rows and the whole [K, N] expert block) instead of every
|
| 79 |
+
# core walking every group with only the small per-device N split. in0_block_w per projection (K tiles per step).
|
| 80 |
+
sorted_grouped: bool = os.environ.get("QWEN35_SORTED_GROUPED", "1") == "1"
|
| 81 |
+
grouped_gate_up_in0: int = 4
|
| 82 |
+
grouped_down_in0: int = 4
|
| 83 |
+
grouped_subblock_w: int = 8
|
| 84 |
# --- decode matmul program configs (round 2, from the stage-2 profile) ---
|
| 85 |
# router gate matmul [32,H]x[H,256]: "ttnn" (auto), "derived" (TTMoEGate 2D-mcast derivation), "1d8" (1D, 8 cores)
|
| 86 |
router_decode_pc: str = "derived"
|
|
|
|
| 404 |
x_disp = gather_rows(x4, m["src_tok"], Rd, gs) # [1,G,gs,H]
|
| 405 |
ttnn.deallocate(m["src_tok"])
|
| 406 |
narrow = self.tile_gu.tile_shape[1] != 32
|
| 407 |
+
grouped = bool(getattr(opt, "sorted_grouped", False))
|
| 408 |
+
if grouped:
|
| 409 |
+
# indexed/gather mode: the id list drives the weight reads, `sparsity` is unused (kept for the op signature)
|
| 410 |
+
sparse_kw = {"indices": m["group_ids"]}
|
| 411 |
+
cfg_gu, cfg_dn = self._grouped_configs(gs, H, Nl)
|
| 412 |
+
else:
|
| 413 |
+
sparse_kw = {"nnz": G}
|
| 414 |
+
cfg_gu, cfg_dn = self._cfg_sorted_gu, self._cfg_sorted_dn
|
| 415 |
out_gu = None if narrow else self._alloc_dev((1, G, gs, 2 * Nl), act)
|
| 416 |
fused = ttnn.sparse_matmul(
|
| 417 |
x_disp,
|
| 418 |
self.up_gate,
|
| 419 |
sparsity=m["group_mask"],
|
| 420 |
+
**sparse_kw,
|
| 421 |
memory_config=ttnn.DRAM_MEMORY_CONFIG,
|
| 422 |
+
program_config=cfg_gu,
|
| 423 |
**({"output_tile": self.tile_gu} if narrow else {"optional_output_tensor": out_gu}),
|
| 424 |
compute_kernel_config=self.routed_ckc,
|
| 425 |
dtype=act,
|
|
|
|
| 436 |
din,
|
| 437 |
self.down,
|
| 438 |
sparsity=m["group_mask"],
|
| 439 |
+
**sparse_kw,
|
| 440 |
optional_output_tensor=out_dn,
|
| 441 |
is_input_a_sparse=False,
|
| 442 |
is_input_b_sparse=True,
|
| 443 |
memory_config=ttnn.DRAM_MEMORY_CONFIG,
|
| 444 |
+
program_config=cfg_dn,
|
| 445 |
compute_kernel_config=self.routed_ckc,
|
| 446 |
dtype=act,
|
| 447 |
) # compact [1,G,32,H]
|
| 448 |
ttnn.deallocate(din)
|
| 449 |
ttnn.deallocate(m["group_mask"])
|
| 450 |
+
ttnn.deallocate(m["group_ids"])
|
| 451 |
y = undispatch_rows(down, None, m["undispatch"], T, k, H)
|
| 452 |
ttnn.deallocate(down)
|
| 453 |
ttnn.deallocate(m["undispatch"])
|
| 454 |
return y
|
| 455 |
|
| 456 |
+
def _grouped_configs(self, gs, H, Nl):
|
| 457 |
+
"""MatmulMultiCoreReuseProgramConfig pair (gate/up, down) for the group-parallel sparse matmul: whole groups per
|
| 458 |
+
core (per_core_M = gs/32, per_core_N = all N tiles), K stepped in in0_block_w tiles, subblock 1 x w."""
|
| 459 |
+
if getattr(self, "_cfg_grouped", None) is None:
|
| 460 |
+
opt = self.opt
|
| 461 |
+
grid = self.device.compute_with_storage_grid_size()
|
| 462 |
+
|
| 463 |
+
def cfg(k, n_tiles, in0_cap, w_tile_bytes):
|
| 464 |
+
k_tiles = k // 32
|
| 465 |
+
ib = max(1, min(int(in0_cap), k_tiles))
|
| 466 |
+
while k_tiles % ib:
|
| 467 |
+
ib -= 1
|
| 468 |
+
# L1 budget of the grouped factory per core: double-buffered in0 [M, ib] + in1 [ib, N] blocks and one
|
| 469 |
+
# bf16 output block. Shrink the K block until it fits (a too-large block is a program-build TT_THROW).
|
| 470 |
+
m_tiles = gs // 32
|
| 471 |
+
while (
|
| 472 |
+
ib > 1
|
| 473 |
+
and 2 * m_tiles * ib * 2048 + 2 * n_tiles * ib * w_tile_bytes + m_tiles * n_tiles * 2048 > 1_300_000
|
| 474 |
+
):
|
| 475 |
+
ib -= 1
|
| 476 |
+
while k_tiles % ib:
|
| 477 |
+
ib -= 1
|
| 478 |
+
sw = max(1, min(int(opt.grouped_subblock_w), n_tiles))
|
| 479 |
+
while n_tiles % sw:
|
| 480 |
+
sw -= 1
|
| 481 |
+
if getattr(self.routed_ckc, "fp32_dest_acc_en", False):
|
| 482 |
+
while sw > 4:
|
| 483 |
+
sw -= 1
|
| 484 |
+
return ttnn.MatmulMultiCoreReuseProgramConfig(
|
| 485 |
+
compute_with_storage_grid_size=ttnn.CoreCoord(grid.x, grid.y),
|
| 486 |
+
in0_block_w=ib,
|
| 487 |
+
out_subblock_h=1,
|
| 488 |
+
out_subblock_w=sw,
|
| 489 |
+
per_core_M=gs // 32,
|
| 490 |
+
per_core_N=n_tiles,
|
| 491 |
+
)
|
| 492 |
+
|
| 493 |
+
gu_tiles = -(-(2 * Nl) // self.tile_gu.tile_shape[1])
|
| 494 |
+
tile_bytes = {ttnn.bfloat4_b: 576, ttnn.bfloat8_b: 1088}
|
| 495 |
+
self._cfg_grouped = (
|
| 496 |
+
cfg(H, gu_tiles, opt.grouped_gate_up_in0, tile_bytes.get(self.up_gate.dtype, 2048)),
|
| 497 |
+
cfg(Nl, H // 32, opt.grouped_down_in0, tile_bytes.get(self.down.dtype, 2048)),
|
| 498 |
+
)
|
| 499 |
+
return self._cfg_grouped
|
| 500 |
+
|
| 501 |
def _route(self, x4):
|
| 502 |
if self._gate_pc_decode is not None:
|
| 503 |
self.gate.matmul_program_config = self._gate_pc_decode if _is_single_tile_rows(x4) else None
|
image/index.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:
|
|
|
|
| 1 |
+
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:5eba8ab305a32cfd16dd1b0e4a95e16511eb5d65a4bb15480145d32343ab87a7","size":856,"annotations":{"io.containerd.image.name":"docker.io/tt-model/qwen3-5-122b-a10b-blackholex4:5eba8ab305a3","org.opencontainers.image.ref.name":"5eba8ab305a3"}}]}
|
image/manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
[{"Config":"blobs/sha256/
|
|
|
|
| 1 |
+
[{"Config":"blobs/sha256/fa8c0c6f2e72626f40f8729615d5ee939cc3aaaabfaaaaba13f66c5dbc291c7c","RepoTags":["tt-model/qwen3-5-122b-a10b-blackholex4:5eba8ab305a3"],"Layers":["blobs/sha256/20c3783cc497b5b0df1fc5f92bd64c3d2fbb24057c88692c8fda205b6ea8a2f2","blobs/sha256/78815c488d38ee90bad5e99fec6c732ab7da586982ce87ddedccc9ff0a9aa816","blobs/sha256/035bde8561dd66df090fd80af6ebc54431c4c261619fe21403d8f290eeafc870","blobs/sha256/2eddd918ff6c02569610b5da36ed3f178c8f0ee1ddf0603a3a6c569e192e23c9","blobs/sha256/c854f847de74423cd1f1af2b563665f89337c0d2804b41267365e151f9f0461e","blobs/sha256/4820d8f261faee9be0a6acd0450e16b8d61234cf6487b22b6bcf0c62fdfafae8","blobs/sha256/9f04092f7a343f595eb45f3e4a104139020bb8adccdabd44d2fdaf387d839c96","blobs/sha256/aae6bb6c9aedbe9e83a25b770c86c3001011fea226706fcdf9ce82236b3b6a9e","blobs/sha256/14f7cbfb67bf9b4d82b081176395cd0e8c2a571d282ebf92e005f9f4bdc37f95","blobs/sha256/f3fcfe98dabc1c03cab56f823e2234331c1f5f1ede82c632047eb02668e8c037","blobs/sha256/97cd366873414f4c22d9ef218bde71134a3a0b8ed5e365805065292ed8973b35","blobs/sha256/bce398621f84b70dda369f251b3081f845d7e227051233751d3385b50c94c3fd","blobs/sha256/26a79ed154b4569c6305b329add28623bd8f8b2a38e0c477e64ed1faf8257a7b","blobs/sha256/a7cfd2eb195796a51d66401b624da093e82ef15c02192d6e564b1ce7df512562","blobs/sha256/eb8a185622509cc112e65d9d9648570d7f398e503944dd99dc140662ea67944c","blobs/sha256/e363d35c5fff386aaa991575332fc542a5ffc22036ad2d77796ed723f2d17068","blobs/sha256/7a019a88b8e38115a9885e604af3c441d1934e2c13d09133a4161d3ab450239b","blobs/sha256/9b72b5c978c392fcbd09e2962d3e6c099d8eee5d305cdd6e61c9137db3c44cb4","blobs/sha256/4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1","blobs/sha256/c80293f68187a74e7f1c75d3775f7481deb58205d67d41814a35ed3ff3ba96f7","blobs/sha256/ecb21a85d0f8992726659678c047f7521a7a4b5b60ba17ab7644e6c2aa04729e","blobs/sha256/83c8dc56544d4dd8b1e3abd53cdac3e01d14657d11f1e131aaf37c3a8309ce07"]}]
|
requirements.lock
CHANGED
|
@@ -4,12 +4,12 @@ aiohttp==3.14.3
|
|
| 4 |
aiosignal==1.4.0
|
| 5 |
annotated-doc==0.0.5
|
| 6 |
annotated-types==0.8.0
|
| 7 |
-
anthropic==1.
|
| 8 |
anyio==4.15.1
|
| 9 |
apache-tvm-ffi==0.1.10
|
| 10 |
astor==0.8.1
|
| 11 |
attrs==26.1.0
|
| 12 |
-
blake3==1.0.
|
| 13 |
cachetools==7.2.0
|
| 14 |
cbor2==6.1.4
|
| 15 |
certifi==2026.7.22
|
|
@@ -43,9 +43,9 @@ fastapi-cli==0.0.32
|
|
| 43 |
fastapi-cloud-cli==0.26.0
|
| 44 |
fastar==0.12.0
|
| 45 |
fastsafetensors==0.4.0
|
| 46 |
-
filelock==4.0.
|
| 47 |
flashinfer-python==0.6.14
|
| 48 |
-
fonttools==4.66.
|
| 49 |
frozenlist==1.8.0
|
| 50 |
fsspec==2026.9.0
|
| 51 |
googleapis-common-protos==1.75.4
|
|
@@ -60,7 +60,7 @@ httpx==0.28.1
|
|
| 60 |
httpx2==2.13.1
|
| 61 |
huggingface_hub==1.33.0
|
| 62 |
humming-kernels==0.1.10
|
| 63 |
-
identify==2.6.
|
| 64 |
idna==3.20
|
| 65 |
ijson==3.5.1
|
| 66 |
interegular==0.3.3
|
|
@@ -87,7 +87,7 @@ mistral_common==1.12.0
|
|
| 87 |
ml_dtypes==0.5.4
|
| 88 |
model-hosting-container-standards==0.1.16
|
| 89 |
mpmath==1.3.0
|
| 90 |
-
msgspec==0.
|
| 91 |
multidict==6.9.1
|
| 92 |
networkx==3.7
|
| 93 |
ninja==1.13.2
|
|
@@ -109,7 +109,7 @@ nvidia-cutlass-dsl-libs-cu13==4.6.0
|
|
| 109 |
nvidia-ml-py==13.615.71
|
| 110 |
nvidia-nvvm==13.4.92
|
| 111 |
nvtx==0.2.15
|
| 112 |
-
openai==3.
|
| 113 |
openai-harmony==0.0.8
|
| 114 |
opencv-python-headless==4.11.0.86
|
| 115 |
opentelemetry-api==1.45.0
|
|
@@ -128,7 +128,7 @@ packaging==26.3
|
|
| 128 |
pandas==3.0.6
|
| 129 |
partial-json-parser==0.2.1.1.post7
|
| 130 |
pillow==12.3.0
|
| 131 |
-
platformdirs==4.12.
|
| 132 |
pre_commit==4.6.2
|
| 133 |
prometheus-fastapi-instrumentator==8.1.0
|
| 134 |
prometheus_client==0.26.0
|
|
@@ -145,7 +145,7 @@ pydantic-settings==2.15.0
|
|
| 145 |
pydantic_core==2.46.5
|
| 146 |
pyelftools==0.33
|
| 147 |
Pygments==2.21.0
|
| 148 |
-
PyJWT==2.15.
|
| 149 |
pyluwen==0.9.0
|
| 150 |
pynvvideocodec==2.0.4
|
| 151 |
pyparsing==3.3.3
|
|
@@ -158,7 +158,7 @@ PyYAML==6.0.3
|
|
| 158 |
pyzmq==27.2.0
|
| 159 |
quack-kernels==0.6.3
|
| 160 |
referencing==0.37.0
|
| 161 |
-
regex==2026.9.
|
| 162 |
requests==2.34.2
|
| 163 |
rich==15.0.0
|
| 164 |
rich-toolkit==0.20.5
|
|
@@ -167,14 +167,14 @@ rpds-py==2026.6.3
|
|
| 167 |
safetensors==0.8.0
|
| 168 |
seaborn==0.13.2
|
| 169 |
sentencepiece==0.2.2
|
| 170 |
-
sentry-sdk==2.
|
| 171 |
setproctitle==1.3.7
|
| 172 |
setuptools==80.10.2
|
| 173 |
setuptools-scm==8.1.0
|
| 174 |
shellingham==1.5.4
|
| 175 |
six==1.17.0
|
| 176 |
sniffio==1.3.1
|
| 177 |
-
sse-starlette==3.
|
| 178 |
starlette==1.7.0
|
| 179 |
supervisor==4.3.0
|
| 180 |
sympy==1.14.0
|
|
@@ -198,7 +198,7 @@ truststore==0.10.4
|
|
| 198 |
tt-smi==6.6.0
|
| 199 |
tt-tools-common==1.6.0
|
| 200 |
tt-umd==0.9.11
|
| 201 |
-
ttnn==0.65.2.
|
| 202 |
typer==0.27.2
|
| 203 |
typing-inspection==0.4.4
|
| 204 |
typing_extensions==4.16.0
|
|
|
|
| 4 |
aiosignal==1.4.0
|
| 5 |
annotated-doc==0.0.5
|
| 6 |
annotated-types==0.8.0
|
| 7 |
+
anthropic==1.9.0
|
| 8 |
anyio==4.15.1
|
| 9 |
apache-tvm-ffi==0.1.10
|
| 10 |
astor==0.8.1
|
| 11 |
attrs==26.1.0
|
| 12 |
+
blake3==1.0.10
|
| 13 |
cachetools==7.2.0
|
| 14 |
cbor2==6.1.4
|
| 15 |
certifi==2026.7.22
|
|
|
|
| 43 |
fastapi-cloud-cli==0.26.0
|
| 44 |
fastar==0.12.0
|
| 45 |
fastsafetensors==0.4.0
|
| 46 |
+
filelock==4.0.6
|
| 47 |
flashinfer-python==0.6.14
|
| 48 |
+
fonttools==4.66.1
|
| 49 |
frozenlist==1.8.0
|
| 50 |
fsspec==2026.9.0
|
| 51 |
googleapis-common-protos==1.75.4
|
|
|
|
| 60 |
httpx2==2.13.1
|
| 61 |
huggingface_hub==1.33.0
|
| 62 |
humming-kernels==0.1.10
|
| 63 |
+
identify==2.6.20
|
| 64 |
idna==3.20
|
| 65 |
ijson==3.5.1
|
| 66 |
interegular==0.3.3
|
|
|
|
| 87 |
ml_dtypes==0.5.4
|
| 88 |
model-hosting-container-standards==0.1.16
|
| 89 |
mpmath==1.3.0
|
| 90 |
+
msgspec==0.22.0
|
| 91 |
multidict==6.9.1
|
| 92 |
networkx==3.7
|
| 93 |
ninja==1.13.2
|
|
|
|
| 109 |
nvidia-ml-py==13.615.71
|
| 110 |
nvidia-nvvm==13.4.92
|
| 111 |
nvtx==0.2.15
|
| 112 |
+
openai==3.20.0
|
| 113 |
openai-harmony==0.0.8
|
| 114 |
opencv-python-headless==4.11.0.86
|
| 115 |
opentelemetry-api==1.45.0
|
|
|
|
| 128 |
pandas==3.0.6
|
| 129 |
partial-json-parser==0.2.1.1.post7
|
| 130 |
pillow==12.3.0
|
| 131 |
+
platformdirs==4.12.1
|
| 132 |
pre_commit==4.6.2
|
| 133 |
prometheus-fastapi-instrumentator==8.1.0
|
| 134 |
prometheus_client==0.26.0
|
|
|
|
| 145 |
pydantic_core==2.46.5
|
| 146 |
pyelftools==0.33
|
| 147 |
Pygments==2.21.0
|
| 148 |
+
PyJWT==2.15.1
|
| 149 |
pyluwen==0.9.0
|
| 150 |
pynvvideocodec==2.0.4
|
| 151 |
pyparsing==3.3.3
|
|
|
|
| 158 |
pyzmq==27.2.0
|
| 159 |
quack-kernels==0.6.3
|
| 160 |
referencing==0.37.0
|
| 161 |
+
regex==2026.9.29
|
| 162 |
requests==2.34.2
|
| 163 |
rich==15.0.0
|
| 164 |
rich-toolkit==0.20.5
|
|
|
|
| 167 |
safetensors==0.8.0
|
| 168 |
seaborn==0.13.2
|
| 169 |
sentencepiece==0.2.2
|
| 170 |
+
sentry-sdk==2.71.0
|
| 171 |
setproctitle==1.3.7
|
| 172 |
setuptools==80.10.2
|
| 173 |
setuptools-scm==8.1.0
|
| 174 |
shellingham==1.5.4
|
| 175 |
six==1.17.0
|
| 176 |
sniffio==1.3.1
|
| 177 |
+
sse-starlette==3.5.0
|
| 178 |
starlette==1.7.0
|
| 179 |
supervisor==4.3.0
|
| 180 |
sympy==1.14.0
|
|
|
|
| 198 |
tt-smi==6.6.0
|
| 199 |
tt-tools-common==1.6.0
|
| 200 |
tt-umd==0.9.11
|
| 201 |
+
ttnn==0.65.2.dev9875
|
| 202 |
typer==0.27.2
|
| 203 |
typing-inspection==0.4.4
|
| 204 |
typing_extensions==4.16.0
|
tt_kernel_manifest.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
{
|
| 2 |
"schema_version": "5.1",
|
| 3 |
"name": "qwen3-5-122b-a10b-blackholex4",
|
| 4 |
-
"tt_metal_version": "0.65.2.
|
| 5 |
"arch": "blackhole",
|
| 6 |
"device_count": 4,
|
| 7 |
"producer": {
|
| 8 |
"tt_kernel_version": "0.1.0",
|
| 9 |
-
"created_at": "2026-09-
|
| 10 |
"hostname": "qb2-120-p11t05"
|
| 11 |
},
|
| 12 |
"weights": {
|
|
@@ -27,8 +27,8 @@
|
|
| 27 |
"image": {
|
| 28 |
"registry": "hf",
|
| 29 |
"repository": "qwen3-5-122b-a10b-blackholex4",
|
| 30 |
-
"tag": "tt-model/qwen3-5-122b-a10b-blackholex4:
|
| 31 |
-
"digest": "sha256:
|
| 32 |
},
|
| 33 |
"kind": "vllm-plugin",
|
| 34 |
"runtime": {
|
|
@@ -120,27 +120,27 @@
|
|
| 120 |
"import models.autoports.qwen_qwen3_5_122b_a10b.tt.decode_buckets as b; assert b.widths(32) == [1, 2, 4, 8, 16, 32]"
|
| 121 |
],
|
| 122 |
"built": {
|
| 123 |
-
"image": "tt-model/qwen3-5-122b-a10b-blackholex4:
|
| 124 |
"repo": "raahemnabeel/qwen3-5-122b-a10b-blackholex4",
|
| 125 |
"tt_model_version": "0.1.0",
|
| 126 |
-
"created_at": "2026-09-
|
| 127 |
"tt_metal": {
|
| 128 |
-
"sha": "
|
| 129 |
-
"describe": "v0.79.0-dev20260909-
|
| 130 |
"dirty": true,
|
| 131 |
-
"scm_version": "0.65.2.
|
| 132 |
"mode": "local",
|
| 133 |
"remote": "https://github.com/tenstorrent/tt-metal.git",
|
| 134 |
"branch": "qwen3_5_122b_a10b",
|
| 135 |
"pushed": false
|
| 136 |
},
|
| 137 |
-
"code_sha256": "
|
| 138 |
"plugin": {
|
| 139 |
"sha": "92403f3b0db48ac86aabf28159ea675c47a420e8",
|
| 140 |
"path": "/home/raahem/vllm-tt-plugin",
|
| 141 |
"dirty": false
|
| 142 |
},
|
| 143 |
-
"image_digest": "sha256:
|
| 144 |
}
|
| 145 |
}
|
| 146 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"schema_version": "5.1",
|
| 3 |
"name": "qwen3-5-122b-a10b-blackholex4",
|
| 4 |
+
"tt_metal_version": "0.65.2.dev9875",
|
| 5 |
"arch": "blackhole",
|
| 6 |
"device_count": 4,
|
| 7 |
"producer": {
|
| 8 |
"tt_kernel_version": "0.1.0",
|
| 9 |
+
"created_at": "2026-09-29T16:31:17.784121+00:00",
|
| 10 |
"hostname": "qb2-120-p11t05"
|
| 11 |
},
|
| 12 |
"weights": {
|
|
|
|
| 27 |
"image": {
|
| 28 |
"registry": "hf",
|
| 29 |
"repository": "qwen3-5-122b-a10b-blackholex4",
|
| 30 |
+
"tag": "tt-model/qwen3-5-122b-a10b-blackholex4:5eba8ab305a3",
|
| 31 |
+
"digest": "sha256:5eba8ab305a32cfd16dd1b0e4a95e16511eb5d65a4bb15480145d32343ab87a7"
|
| 32 |
},
|
| 33 |
"kind": "vllm-plugin",
|
| 34 |
"runtime": {
|
|
|
|
| 120 |
"import models.autoports.qwen_qwen3_5_122b_a10b.tt.decode_buckets as b; assert b.widths(32) == [1, 2, 4, 8, 16, 32]"
|
| 121 |
],
|
| 122 |
"built": {
|
| 123 |
+
"image": "tt-model/qwen3-5-122b-a10b-blackholex4:5eba8ab305a3",
|
| 124 |
"repo": "raahemnabeel/qwen3-5-122b-a10b-blackholex4",
|
| 125 |
"tt_model_version": "0.1.0",
|
| 126 |
+
"created_at": "2026-09-29T16:25:00+00:00",
|
| 127 |
"tt_metal": {
|
| 128 |
+
"sha": "6da58d94a83546bb02886bc8e2658919f76f1254",
|
| 129 |
+
"describe": "v0.79.0-dev20260909-72-g6da58d94a8",
|
| 130 |
"dirty": true,
|
| 131 |
+
"scm_version": "0.65.2.dev9875",
|
| 132 |
"mode": "local",
|
| 133 |
"remote": "https://github.com/tenstorrent/tt-metal.git",
|
| 134 |
"branch": "qwen3_5_122b_a10b",
|
| 135 |
"pushed": false
|
| 136 |
},
|
| 137 |
+
"code_sha256": "3e629a797061595a45db0ee745c31907e553b12f8745ae6ae3f6bd769a1ff774",
|
| 138 |
"plugin": {
|
| 139 |
"sha": "92403f3b0db48ac86aabf28159ea675c47a420e8",
|
| 140 |
"path": "/home/raahem/vllm-tt-plugin",
|
| 141 |
"dirty": false
|
| 142 |
},
|
| 143 |
+
"image_digest": "sha256:5eba8ab305a32cfd16dd1b0e4a95e16511eb5d65a4bb15480145d32343ab87a7"
|
| 144 |
}
|
| 145 |
}
|
| 146 |
}
|