nbxtensor 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. nbxtensor/THIRD_PARTY_NOTICES.md +287 -0
  2. nbxtensor/__init__.py +17 -0
  3. nbxtensor/backend/__init__.py +1 -0
  4. nbxtensor/backend/capabilities.py +207 -0
  5. nbxtensor/backend/cpu/__init__.py +1 -0
  6. nbxtensor/backend/cpu/blas.py +102 -0
  7. nbxtensor/backend/cpu/pool.py +204 -0
  8. nbxtensor/backend/cpu_backend.py +162 -0
  9. nbxtensor/backend/device_facts.py +105 -0
  10. nbxtensor/backend/device_files.py +129 -0
  11. nbxtensor/backend/device_names.py +18 -0
  12. nbxtensor/backend/devices/amd/cdna.yml +228 -0
  13. nbxtensor/backend/devices/amd/cdna2.yml +228 -0
  14. nbxtensor/backend/devices/amd/cdna3.yml +227 -0
  15. nbxtensor/backend/devices/apple/apple_m1.yml +266 -0
  16. nbxtensor/backend/devices/apple/apple_m1_max.yml +266 -0
  17. nbxtensor/backend/devices/apple/apple_m1_pro.yml +266 -0
  18. nbxtensor/backend/devices/apple/apple_m1_ultra.yml +266 -0
  19. nbxtensor/backend/devices/apple/apple_m2.yml +266 -0
  20. nbxtensor/backend/devices/apple/apple_m2_max.yml +266 -0
  21. nbxtensor/backend/devices/apple/apple_m2_pro.yml +266 -0
  22. nbxtensor/backend/devices/apple/apple_m2_ultra.yml +266 -0
  23. nbxtensor/backend/devices/apple/apple_m3.yml +266 -0
  24. nbxtensor/backend/devices/apple/apple_m3_max.yml +266 -0
  25. nbxtensor/backend/devices/apple/apple_m3_pro.yml +266 -0
  26. nbxtensor/backend/devices/apple/apple_m3_ultra.yml +266 -0
  27. nbxtensor/backend/devices/apple/apple_m4.yml +266 -0
  28. nbxtensor/backend/devices/apple/apple_m4_max.yml +266 -0
  29. nbxtensor/backend/devices/apple/apple_m4_pro.yml +308 -0
  30. nbxtensor/backend/devices/apple/apple_m5.yml +269 -0
  31. nbxtensor/backend/devices/apple/apple_m5_max.yml +269 -0
  32. nbxtensor/backend/devices/apple/apple_m5_pro.yml +269 -0
  33. nbxtensor/backend/devices/apple/apple_m5_ultra.yml +269 -0
  34. nbxtensor/backend/devices/apple/apple_m6.yml +269 -0
  35. nbxtensor/backend/devices/apple/apple_silicon.yml +263 -0
  36. nbxtensor/backend/devices/nvidia/ampere.yml +214 -0
  37. nbxtensor/backend/devices/nvidia/hopper.yml +213 -0
  38. nbxtensor/backend/devices/nvidia/volta.yml +411 -0
  39. nbxtensor/backend/faults.py +151 -0
  40. nbxtensor/backend/host_memory.py +185 -0
  41. nbxtensor/backend/launcher.py +2350 -0
  42. nbxtensor/backend/launcher_contract.py +429 -0
  43. nbxtensor/backend/metal_backend.py +661 -0
  44. nbxtensor/backend/metal_device.py +1274 -0
  45. nbxtensor/backend/process_memory.py +73 -0
  46. nbxtensor/backend/replay_graph.py +322 -0
  47. nbxtensor/backend/runtime.py +409 -0
  48. nbxtensor/backend/triton_ext_driver.py +735 -0
  49. nbxtensor/dtype/__init__.py +1 -0
  50. nbxtensor/dtype/convert.py +107 -0
  51. nbxtensor/dtype/dtypes.yml +70 -0
  52. nbxtensor/dtype/itemsize.py +166 -0
  53. nbxtensor/dtype/nbx_dtype.py +72 -0
  54. nbxtensor/dtype/operands.py +158 -0
  55. nbxtensor/dtype/outputs.py +64 -0
  56. nbxtensor/dtype/policy.py +155 -0
  57. nbxtensor/dtype/policy.yml +51 -0
  58. nbxtensor/dtype/promotion.py +112 -0
  59. nbxtensor/host.py +55 -0
  60. nbxtensor/io/__init__.py +1 -0
  61. nbxtensor/io/read_rate.py +197 -0
  62. nbxtensor/io/safetensors.py +314 -0
  63. nbxtensor/memory/__init__.py +9 -0
  64. nbxtensor/memory/allocator.py +1988 -0
  65. nbxtensor/memory/arena.py +75 -0
  66. nbxtensor/memory/device_memory.py +150 -0
  67. nbxtensor/memory/device_transfer.py +154 -0
  68. nbxtensor/memory/layout.py +43 -0
  69. nbxtensor/memory/memory_pool.py +191 -0
  70. nbxtensor/memory/metal.py +96 -0
  71. nbxtensor/memory/oom_advice.py +91 -0
  72. nbxtensor/memory/pointer_tables.py +323 -0
  73. nbxtensor/memory/pool.py +507 -0
  74. nbxtensor/memory/shadow.py +43 -0
  75. nbxtensor/memory/slab.py +273 -0
  76. nbxtensor/memory/trace_replay.py +122 -0
  77. nbxtensor/memory/traces/sana-video-2b-720p.16g.2026-11-02.tsv +13610 -0
  78. nbxtensor/memory/vmm.py +118 -0
  79. nbxtensor/ops/__init__.py +1 -0
  80. nbxtensor/ops/_autotune_policy.py +90 -0
  81. nbxtensor/ops/_common.py +32 -0
  82. nbxtensor/ops/_configs.py +1041 -0
  83. nbxtensor/ops/_cost.py +231 -0
  84. nbxtensor/ops/abs.py +17 -0
  85. nbxtensor/ops/adaptive_avg_pool2d.py +161 -0
  86. nbxtensor/ops/add.py +96 -0
  87. nbxtensor/ops/addcdiv.py +29 -0
  88. nbxtensor/ops/addcmul.py +29 -0
  89. nbxtensor/ops/addmv_op.py +64 -0
  90. nbxtensor/ops/addr.py +68 -0
  91. nbxtensor/ops/all_reduce.py +83 -0
  92. nbxtensor/ops/amax.py +40 -0
  93. nbxtensor/ops/any_reduce.py +83 -0
  94. nbxtensor/ops/arange_op.py +27 -0
  95. nbxtensor/ops/argmax.py +107 -0
  96. nbxtensor/ops/argmin.py +93 -0
  97. nbxtensor/ops/atan2.py +71 -0
  98. nbxtensor/ops/attention_wrappers.py +1648 -0
  99. nbxtensor/ops/autotune_bucket.py +137 -0
  100. nbxtensor/ops/autotune_cache.py +430 -0
  101. nbxtensor/ops/autotune_certified.py +1262 -0
  102. nbxtensor/ops/autotune_refusals.py +380 -0
  103. nbxtensor/ops/autotune_settings.py +58 -0
  104. nbxtensor/ops/avg_pool2d.py +73 -0
  105. nbxtensor/ops/baddbmm_op.py +132 -0
  106. nbxtensor/ops/batch_norm.py +163 -0
  107. nbxtensor/ops/binary_strided.py +196 -0
  108. nbxtensor/ops/bitwise_and.py +26 -0
  109. nbxtensor/ops/bitwise_left_shift.py +47 -0
  110. nbxtensor/ops/bitwise_not.py +24 -0
  111. nbxtensor/ops/bitwise_or.py +26 -0
  112. nbxtensor/ops/bitwise_right_shift.py +47 -0
  113. nbxtensor/ops/bucketize.py +37 -0
  114. nbxtensor/ops/cat_op.py +87 -0
  115. nbxtensor/ops/celu.py +20 -0
  116. nbxtensor/ops/clamp.py +24 -0
  117. nbxtensor/ops/clamp_min.py +22 -0
  118. nbxtensor/ops/conv2d.py +265 -0
  119. nbxtensor/ops/conv2d_m8n8k4.py +165 -0
  120. nbxtensor/ops/conv_depthwise2d.py +154 -0
  121. nbxtensor/ops/conv_transpose2d.py +148 -0
  122. nbxtensor/ops/conv_wrappers.py +1482 -0
  123. nbxtensor/ops/copy.py +18 -0
  124. nbxtensor/ops/copy_op.py +39 -0
  125. nbxtensor/ops/cos.py +17 -0
  126. nbxtensor/ops/count_nonzero.py +64 -0
  127. nbxtensor/ops/cross_entropy.py +67 -0
  128. nbxtensor/ops/cummax.py +109 -0
  129. nbxtensor/ops/cummin.py +105 -0
  130. nbxtensor/ops/cumsum.py +244 -0
  131. nbxtensor/ops/decode_attn_vec.py +162 -0
  132. nbxtensor/ops/depthwise_conv2d.py +132 -0
  133. nbxtensor/ops/dequant_gemv.py +190 -0
  134. nbxtensor/ops/dft.py +67 -0
  135. nbxtensor/ops/dispatch.py +1228 -0
  136. nbxtensor/ops/div.py +75 -0
  137. nbxtensor/ops/dot_op.py +67 -0
  138. nbxtensor/ops/dropout.py +23 -0
  139. nbxtensor/ops/dtype_convert.py +42 -0
  140. nbxtensor/ops/elementwise_launch.py +81 -0
  141. nbxtensor/ops/elementwise_wrappers.py +2315 -0
  142. nbxtensor/ops/elu.py +20 -0
  143. nbxtensor/ops/embedding.py +69 -0
  144. nbxtensor/ops/eq.py +32 -0
  145. nbxtensor/ops/erf.py +18 -0
  146. nbxtensor/ops/exp.py +17 -0
  147. nbxtensor/ops/exp2.py +18 -0
  148. nbxtensor/ops/fft_op.py +125 -0
  149. nbxtensor/ops/fill_op.py +20 -0
  150. nbxtensor/ops/flash_attention.py +307 -0
  151. nbxtensor/ops/flash_attention_m8n8k4.py +384 -0
  152. nbxtensor/ops/flash_decode.py +78 -0
  153. nbxtensor/ops/flip_op.py +60 -0
  154. nbxtensor/ops/floor.py +90 -0
  155. nbxtensor/ops/full_op.py +24 -0
  156. nbxtensor/ops/fused_moe.py +417 -0
  157. nbxtensor/ops/fused_moe_m8n8k4.py +99 -0
  158. nbxtensor/ops/fused_upsample_conv.py +413 -0
  159. nbxtensor/ops/gather_op.py +52 -0
  160. nbxtensor/ops/ge.py +32 -0
  161. nbxtensor/ops/gelu.py +31 -0
  162. nbxtensor/ops/gemv_vec.py +80 -0
  163. nbxtensor/ops/glu.py +43 -0
  164. nbxtensor/ops/grid_sampler.py +145 -0
  165. nbxtensor/ops/group_norm_tiled.py +67 -0
  166. nbxtensor/ops/groupnorm.py +123 -0
  167. nbxtensor/ops/gt.py +32 -0
  168. nbxtensor/ops/hardsigmoid.py +18 -0
  169. nbxtensor/ops/hardswish.py +19 -0
  170. nbxtensor/ops/im2col.py +57 -0
  171. nbxtensor/ops/index_add.py +95 -0
  172. nbxtensor/ops/index_put_op.py +92 -0
  173. nbxtensor/ops/index_select.py +121 -0
  174. nbxtensor/ops/index_wrappers.py +770 -0
  175. nbxtensor/ops/isfinite.py +20 -0
  176. nbxtensor/ops/isinf.py +20 -0
  177. nbxtensor/ops/isnan.py +18 -0
  178. nbxtensor/ops/launch_keys.py +1054 -0
  179. nbxtensor/ops/launch_observer.py +54 -0
  180. nbxtensor/ops/layernorm.py +71 -0
  181. nbxtensor/ops/le.py +35 -0
  182. nbxtensor/ops/leaky_relu.py +19 -0
  183. nbxtensor/ops/lerp.py +76 -0
  184. nbxtensor/ops/linalg_wrappers.py +1370 -0
  185. nbxtensor/ops/linspace_op.py +47 -0
  186. nbxtensor/ops/log.py +17 -0
  187. nbxtensor/ops/log_sigmoid.py +23 -0
  188. nbxtensor/ops/logical_and.py +26 -0
  189. nbxtensor/ops/logical_not.py +24 -0
  190. nbxtensor/ops/logical_or.py +26 -0
  191. nbxtensor/ops/logical_xor.py +37 -0
  192. nbxtensor/ops/loss_wrappers.py +282 -0
  193. nbxtensor/ops/lt.py +32 -0
  194. nbxtensor/ops/masked_fill.py +21 -0
  195. nbxtensor/ops/matmul.py +377 -0
  196. nbxtensor/ops/matmul_m8n8k4.py +235 -0
  197. nbxtensor/ops/max_pool2d.py +74 -0
  198. nbxtensor/ops/max_pool3d.py +93 -0
  199. nbxtensor/ops/max_reduce.py +91 -0
  200. nbxtensor/ops/maximum.py +18 -0
  201. nbxtensor/ops/mean.py +40 -0
  202. nbxtensor/ops/min_reduce.py +91 -0
  203. nbxtensor/ops/minimum.py +18 -0
  204. nbxtensor/ops/mish.py +22 -0
  205. nbxtensor/ops/mma_m8n8k4.py +152 -0
  206. nbxtensor/ops/moe_align.py +195 -0
  207. nbxtensor/ops/moe_decode_vec.py +374 -0
  208. nbxtensor/ops/moe_device_residency.py +141 -0
  209. nbxtensor/ops/moe_wrappers.py +345 -0
  210. nbxtensor/ops/mse_loss.py +79 -0
  211. nbxtensor/ops/mul.py +51 -0
  212. nbxtensor/ops/nan_to_num.py +23 -0
  213. nbxtensor/ops/ne.py +32 -0
  214. nbxtensor/ops/neg.py +17 -0
  215. nbxtensor/ops/nllloss.py +124 -0
  216. nbxtensor/ops/nonzero.py +33 -0
  217. nbxtensor/ops/nonzero_op.py +62 -0
  218. nbxtensor/ops/norm_wrappers.py +579 -0
  219. nbxtensor/ops/ones_op.py +20 -0
  220. nbxtensor/ops/oracles/__init__.py +6 -0
  221. nbxtensor/ops/oracles/conv2d_fp64.py +450 -0
  222. nbxtensor/ops/pad_op.py +159 -0
  223. nbxtensor/ops/paged_decode_attn.py +215 -0
  224. nbxtensor/ops/pixel_shuffle.py +144 -0
  225. nbxtensor/ops/pixel_unshuffle.py +72 -0
  226. nbxtensor/ops/pow.py +137 -0
  227. nbxtensor/ops/prod.py +81 -0
  228. nbxtensor/ops/rand_op.py +52 -0
  229. nbxtensor/ops/random_wrappers.py +366 -0
  230. nbxtensor/ops/reciprocal.py +17 -0
  231. nbxtensor/ops/reduction_wrappers.py +845 -0
  232. nbxtensor/ops/relu.py +18 -0
  233. nbxtensor/ops/remainder.py +46 -0
  234. nbxtensor/ops/repeat_interleave.py +48 -0
  235. nbxtensor/ops/repeat_op.py +132 -0
  236. nbxtensor/ops/residual_chain.py +374 -0
  237. nbxtensor/ops/rmsnorm.py +68 -0
  238. nbxtensor/ops/rope.py +142 -0
  239. nbxtensor/ops/rsqrt.py +17 -0
  240. nbxtensor/ops/scaled_softmax.py +96 -0
  241. nbxtensor/ops/scatter_op.py +139 -0
  242. nbxtensor/ops/screen_oracle.py +479 -0
  243. nbxtensor/ops/selu.py +22 -0
  244. nbxtensor/ops/shape_wrappers.py +1032 -0
  245. nbxtensor/ops/sigmoid.py +19 -0
  246. nbxtensor/ops/silu.py +27 -0
  247. nbxtensor/ops/sin.py +17 -0
  248. nbxtensor/ops/softmax.py +169 -0
  249. nbxtensor/ops/softplus.py +27 -0
  250. nbxtensor/ops/sort_op.py +304 -0
  251. nbxtensor/ops/spectral_wrappers.py +481 -0
  252. nbxtensor/ops/sqrt.py +17 -0
  253. nbxtensor/ops/stack_op.py +84 -0
  254. nbxtensor/ops/std.py +113 -0
  255. nbxtensor/ops/strided_copy.py +200 -0
  256. nbxtensor/ops/sub.py +35 -0
  257. nbxtensor/ops/sum.py +40 -0
  258. nbxtensor/ops/tan.py +19 -0
  259. nbxtensor/ops/tanh.py +21 -0
  260. nbxtensor/ops/threshold.py +19 -0
  261. nbxtensor/ops/tiling.yml +91 -0
  262. nbxtensor/ops/tiling_policy.py +43 -0
  263. nbxtensor/ops/tiling_sizes.py +370 -0
  264. nbxtensor/ops/topk.py +267 -0
  265. nbxtensor/ops/trace_op.py +64 -0
  266. nbxtensor/ops/tril.py +64 -0
  267. nbxtensor/ops/triu.py +62 -0
  268. nbxtensor/ops/unfold_op.py +37 -0
  269. nbxtensor/ops/unique_op.py +97 -0
  270. nbxtensor/ops/upsample_bilinear2d.py +106 -0
  271. nbxtensor/ops/upsample_nearest2d.py +52 -0
  272. nbxtensor/ops/upsample_nearest3d.py +61 -0
  273. nbxtensor/ops/var.py +136 -0
  274. nbxtensor/ops/vector_norm.py +216 -0
  275. nbxtensor/ops/weight_norm.py +104 -0
  276. nbxtensor/ops/where.py +39 -0
  277. nbxtensor/ops/wrappers.py +825 -0
  278. nbxtensor/ops/zeros_op.py +20 -0
  279. nbxtensor/quant/__init__.py +1 -0
  280. nbxtensor/quant/quantized_tensor.py +187 -0
  281. nbxtensor/random/__init__.py +1 -0
  282. nbxtensor/random/mt_randn.py +154 -0
  283. nbxtensor/random/rng_pin.py +59 -0
  284. nbxtensor/random/rng_stream.py +118 -0
  285. nbxtensor/random/seeded_draw.py +223 -0
  286. nbxtensor/shape/__init__.py +157 -0
  287. nbxtensor/tensor.py +1867 -0
  288. nbxtensor-0.0.1.dist-info/METADATA +379 -0
  289. nbxtensor-0.0.1.dist-info/RECORD +291 -0
  290. nbxtensor-0.0.1.dist-info/WHEEL +4 -0
  291. nbxtensor-0.0.1.dist-info/licenses/LICENSE +189 -0
@@ -0,0 +1,141 @@
1
+ """The expert store's residency kept ON THE CARD for a decode token (S3, 2026-10-28).
2
+
3
+ An expert store serves the routed layers no card holds whole from a cache of device slots. Its host-side residency
4
+ (`core/runtime/expert_residency.ExpertResidency`) reads every call's routing back to the host, decides the misses, and
5
+ copies them — a host round trip per layer per token that also keeps the decode step from being replayed (Qwen3-30B-A3B
6
+ on 4 V100: 8 store layers ~32 ms of a ~80 ms token). For one token the same LRU runs here:
7
+
8
+ 1. `expert_slot_assign_kernel` — ONE program, deterministic: every routed expert already resident is a hit (its stamp
9
+ refreshed to the clock); every miss takes the free slot or the least recently stamped slot this call does not read
10
+ (a slot this call reads carries the current clock, so it is never the oldest), evicting its previous owner from
11
+ the slot map. Writes each routed expert's slot, and for a miss the expert to copy (-1 for a hit). The clock moves.
12
+ 2. `expert_miss_copy_kernel` — grid (TOP_K, 3 projections, chunks): a miss copies its expert's three projections from
13
+ page-locked host memory (read through its device-visible address) into its slot; a hit returns at once.
14
+
15
+ The decode band then reads the experts through the slots' fixed pointer table, indexed by slot (`moe_decode_vec` half
16
+ kernels). Every launch is the same at every token — pointers to persistent tables — so the step replays.
17
+ """
18
+
19
+ import triton
20
+ import triton.language as tl
21
+
22
+
23
+ @triton.jit
24
+ def expert_slot_assign_kernel(
25
+ ids_ptr, # [TOP_K] int64 — the routed experts of this token, the router's order
26
+ slot_of_ptr, # [L * E] int32 — slot holding (layer, expert), -1 when none
27
+ owner_ptr, # [S] int32 — the (layer * E + expert) a slot holds, -1 when free
28
+ stamp_ptr, # [S] int64 — the clock at a slot's last use, -1 when free
29
+ clock_ptr, # [1] int64
30
+ slot_out_ptr, # [TOP_K] int64 — the slot of each routed expert
31
+ miss_out_ptr, # [TOP_K] int64 — the expert to copy into that slot, -1 for a hit
32
+ layer_base, # layer index * E
33
+ S,
34
+ TOP_K: tl.constexpr,
35
+ BLOCK_S: tl.constexpr,
36
+ ):
37
+ clock = tl.load(clock_ptr)
38
+ offs = tl.arange(0, BLOCK_S)
39
+ in_range = offs < S
40
+ # hits first: their slots carry the current clock before any miss looks for a victim
41
+ for k in tl.static_range(TOP_K):
42
+ e = tl.load(ids_ptr + k)
43
+ s = tl.load(slot_of_ptr + layer_base + e)
44
+ if s >= 0:
45
+ tl.store(stamp_ptr + s, clock)
46
+ tl.store(slot_out_ptr + k, s.to(tl.int64))
47
+ tl.store(miss_out_ptr + k, -1)
48
+ tl.debug_barrier()
49
+ for k in tl.static_range(TOP_K):
50
+ e = tl.load(ids_ptr + k)
51
+ s = tl.load(slot_of_ptr + layer_base + e)
52
+ if s < 0:
53
+ stamps = tl.load(stamp_ptr + offs, mask=in_range, other=9223372036854775807)
54
+ victim = tl.argmin(stamps, axis=0)
55
+ old = tl.load(owner_ptr + victim)
56
+ if old >= 0:
57
+ tl.store(slot_of_ptr + old, -1)
58
+ tl.store(owner_ptr + victim, (layer_base + e).to(tl.int32))
59
+ tl.store(slot_of_ptr + layer_base + e, victim.to(tl.int32))
60
+ tl.store(stamp_ptr + victim, clock)
61
+ tl.store(slot_out_ptr + k, victim.to(tl.int64))
62
+ tl.store(miss_out_ptr + k, e)
63
+ tl.debug_barrier()
64
+ tl.store(clock_ptr, clock + 1)
65
+
66
+
67
+ @triton.jit
68
+ def expert_miss_copy_kernel(
69
+ miss_ptr, # [TOP_K] int64 — expert to copy, -1 for a hit
70
+ slot_ptr, # [TOP_K] int64 — its slot
71
+ host_g, host_u, host_d, # [L * E] int64 — device-visible addresses of the host experts' projections
72
+ slot_g, slot_u, slot_d, # [S] int64 — the slots' projection addresses
73
+ layer_base,
74
+ n_g, n_u, n_d, # elements per projection
75
+ BLOCK: tl.constexpr,
76
+ W_BF16: tl.constexpr,
77
+ ):
78
+ k = tl.program_id(0).to(tl.int64)
79
+ p = tl.program_id(1).to(tl.int64)
80
+ c = tl.program_id(2).to(tl.int64)
81
+ e_raw = tl.load(miss_ptr + k)
82
+ # a hit (-1) copies nothing: masked, not returned (a bare return is unstructured control flow some backends do
83
+ # not lower); its address loads read row 0 of the tables, a valid index, and the copy's mask is all false
84
+ miss = e_raw >= 0
85
+ e = tl.where(miss, e_raw, 0)
86
+ s = tl.where(miss, tl.load(slot_ptr + k), 0)
87
+ wty = tl.bfloat16 if W_BF16 else tl.float16
88
+ if p == 0:
89
+ src_a = tl.load(host_g + layer_base + e)
90
+ dst_a = tl.load(slot_g + s)
91
+ n = n_g
92
+ elif p == 1:
93
+ src_a = tl.load(host_u + layer_base + e)
94
+ dst_a = tl.load(slot_u + s)
95
+ n = n_u
96
+ else:
97
+ src_a = tl.load(host_d + layer_base + e)
98
+ dst_a = tl.load(slot_d + s)
99
+ n = n_d
100
+ src = tl.cast(src_a, tl.pointer_type(wty), bitcast=True)
101
+ dst = tl.cast(dst_a, tl.pointer_type(wty), bitcast=True)
102
+ offs = c * BLOCK + tl.arange(0, BLOCK)
103
+ m = (offs < n) & miss
104
+ tl.store(dst + offs, tl.load(src + offs, mask=m), mask=m)
105
+
106
+
107
+ def measure_miss_copy(nbytes: int, reps: int, blocks, warps, experts: int) -> dict:
108
+ """`expert_miss_copy_kernel` on this device, launched as the engine's expert store launches it: `nbytes` in
109
+ page-locked host memory as `experts` missed experts of three projections each, copied into device slots at every
110
+ candidate (block, warps), `reps` launches each after one; {"block", "warps", "gbps"} of the fastest, every
111
+ candidate's rate in "grid". On a V100-SXM2 (2026-11-03): 1024 x 16 at 5.4-5.5 GB/s, where a fixed 4096 x 4 gave
112
+ 3.35."""
113
+ import time
114
+ import numpy as np
115
+ from nbxtensor.memory.allocator import DeviceAllocator as DA
116
+ from nbxtensor.tensor import NBXTensor
117
+ from nbxtensor.dtype.nbx_dtype import NBXDtype
118
+ n = int(nbytes) // (2 * 3 * int(experts)) # fp16 elements per projection
119
+ host = [[NBXTensor.empty_cpu((n,), NBXDtype.float16, pinned=True) for _ in range(3)] for _ in range(experts)]
120
+ slots = [[NBXTensor.empty((n,), dtype=NBXDtype.float16, device="cuda:0") for _ in range(3)] for _ in range(experts)]
121
+ dev = lambda a: NBXTensor.from_numpy(np.asarray(a, dtype=np.int64)).to("cuda:0") # noqa: E731
122
+ host_tabs = [dev([host[e][p].data_ptr() for e in range(experts)]) for p in range(3)]
123
+ slot_tabs = [dev([slots[e][p].data_ptr() for e in range(experts)]) for p in range(3)]
124
+ miss = dev(list(range(experts)))
125
+ moved = experts * 3 * n * 2
126
+ grid = {}
127
+ for block in blocks:
128
+ for w in warps:
129
+ def launch(block=block, w=w):
130
+ expert_miss_copy_kernel[(experts, 3, triton.cdiv(n, block))](
131
+ miss, miss, *host_tabs, *slot_tabs, 0, n, n, n, BLOCK=block, W_BF16=False, num_warps=w)
132
+ launch()
133
+ DA.device_synchronize(0)
134
+ t0 = time.perf_counter()
135
+ for _ in range(reps):
136
+ launch()
137
+ DA.device_synchronize(0)
138
+ grid[f"{block}x{w}"] = round(moved * reps / (time.perf_counter() - t0) / 1e9, 2)
139
+ best = max(grid, key=grid.get)
140
+ block, w = (int(v) for v in best.split("x"))
141
+ return {"block": block, "warps": w, "gbps": grid[best], "grid": grid}
@@ -0,0 +1,345 @@
1
+ """Mixture-of-experts wrappers: the fused MoE launches (dense and wna16). Cut out of wrappers.py by family (M2, 2026-10-29), unchanged; shared launch layer and run context stay in wrappers.py."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import triton
7
+ from nbxtensor.ops.autotune_bucket import bucket_of as _bucket_of
8
+ from nbxtensor.ops import launch_keys as _lk
9
+ from nbxtensor.tensor import NBXTensor
10
+ from nbxtensor.dtype.nbx_dtype import NBXDtype, dtype_size
11
+ from nbxtensor.memory.allocator import DeviceAllocator
12
+ from nbxtensor.backend.runtime import set_device
13
+ from nbxtensor.shape import MAX_NDIM as _NBX_MAX_NDIM, broadcast_shapes, max_linear_offset
14
+ from nbxtensor.dtype.itemsize import canonical_name
15
+ from nbxtensor.dtype.promotion import binary_result, float_math_input
16
+ from nbxtensor.dtype.nbx_dtype import parse_dtype
17
+ from nbxtensor.memory.allocator import DeviceOOMError
18
+ from nbxtensor.backend.capabilities import fa_min_tile as _fa_min_tile
19
+ from nbxtensor.backend.capabilities import reduce_tile_max as _reduce_tile_max
20
+ from nbxtensor.backend.faults import device_fault_buffer, device_fault_code_cached, fault_channel
21
+ from nbxtensor.tensor import _upload_int64_array as _nbx_upload_int64, _saturating_cast as _nbx_saturating_cast
22
+ from nbxtensor.ops._configs import sdpa_block_ceiling as _sdpa_block_ceiling
23
+ from nbxtensor.ops._configs import sdpa_launch_meta as _sdpa_launch_meta
24
+ from nbxtensor.ops._configs import matrix_unit as _matrix_unit, matrix_unit_mm_tile as _matrix_unit_mm_tile
25
+ from nbxtensor.ops._configs import largest_tile_within_smem as _largest_tile_within_smem
26
+ from nbxtensor.backend import launcher as _nbx_launcher
27
+ from nbxtensor.backend.launcher import install as _install_launcher
28
+ from nbxtensor.ops.relu import relu_forward_kernel
29
+ from nbxtensor.ops.silu import silu_forward_kernel
30
+ from nbxtensor.ops.gelu import gelu_forward_kernel
31
+ from nbxtensor.ops.sigmoid import sigmoid_forward_kernel
32
+ from nbxtensor.ops.tanh import tanh_forward_kernel
33
+ from nbxtensor.ops.hardsigmoid import hardsigmoid_forward_kernel
34
+ from nbxtensor.ops.hardswish import hardswish_forward_kernel
35
+ from nbxtensor.ops.leaky_relu import leaky_relu_forward_kernel
36
+ from nbxtensor.ops.elu import elu_forward_kernel
37
+ from nbxtensor.ops.mish import mish_forward_kernel
38
+ from nbxtensor.ops.selu import selu_forward_kernel
39
+ from nbxtensor.ops.neg import neg_forward_kernel
40
+ from nbxtensor.ops.exp import exp_forward_kernel
41
+ from nbxtensor.ops.sin import sin_forward_kernel
42
+ from nbxtensor.ops.cos import cos_forward_kernel
43
+ from nbxtensor.ops.rsqrt import rsqrt_forward_kernel
44
+ from nbxtensor.ops.sqrt import sqrt_forward_kernel
45
+ from nbxtensor.ops.abs import abs_forward_kernel
46
+ from nbxtensor.ops.log import log_forward_kernel
47
+ from nbxtensor.ops.reciprocal import reciprocal_forward_kernel
48
+ from nbxtensor.ops.pow import pow_forward_kernel
49
+ from nbxtensor.ops.clamp import clamp_forward_kernel
50
+ from nbxtensor.ops.erf import erf_forward_kernel
51
+ from nbxtensor.ops.copy import copy_forward_kernel
52
+ from nbxtensor.ops.add import add_forward_kernel, add_scalar_kernel, add_scalar_dev_kernel, add_bias_broadcast_kernel
53
+ from nbxtensor.ops.binary_strided import add_strided_nd_kernel, mul_strided_nd_kernel, sub_strided_nd_kernel, div_strided_nd_kernel, add_scalar_strided_nd_kernel, mul_scalar_strided_nd_kernel
54
+ from nbxtensor.ops.mul import mul_forward_kernel, mul_scalar_kernel, mul_scalar_dev_kernel
55
+ from nbxtensor.ops.div import div_forward_kernel, div_scalar_kernel, div_scalar_dev_kernel, int_div_kernel
56
+ from nbxtensor.ops.sub import sub_forward_kernel, rsub_forward_kernel
57
+ from nbxtensor.ops.where import where_forward_kernel
58
+ from nbxtensor.ops.maximum import maximum_forward_kernel
59
+ from nbxtensor.ops.minimum import minimum_forward_kernel
60
+ from nbxtensor.ops.masked_fill import masked_fill_forward_kernel
61
+ from nbxtensor.ops.gt import gt_forward_kernel, gt_scalar_kernel
62
+ from nbxtensor.ops.ge import ge_forward_kernel, ge_scalar_kernel
63
+ from nbxtensor.ops.lt import lt_forward_kernel, lt_scalar_kernel
64
+ from nbxtensor.ops.eq import eq_forward_kernel, eq_scalar_kernel
65
+ from nbxtensor.ops.ne import ne_forward_kernel, ne_scalar_kernel
66
+ from nbxtensor.ops.layernorm import layer_norm_forward_kernel
67
+ from nbxtensor.ops.rmsnorm import rms_norm_forward_kernel
68
+ from nbxtensor.ops.softmax import softmax_forward_kernel, softmax_forward_looped_kernel
69
+ from nbxtensor.ops.matmul import matmul_kernel, addmm_kernel
70
+ from nbxtensor.ops._autotune_policy import NBX_FORCE_FP32_ACCUM
71
+ from nbxtensor.ops.fused_moe import fused_moe_kernel, silu_and_mul_kernel, silu_mul_split_kernel
72
+ from nbxtensor.ops.dtype_convert import bf16_to_fp16_kernel
73
+ from nbxtensor.ops.embedding import embedding_kernel, EMBEDDING_OOB
74
+ from nbxtensor.ops.sum import sum_forward_kernel
75
+ from nbxtensor.ops.mean import mean_forward_kernel
76
+ from nbxtensor.ops.amax import amax_forward_kernel
77
+ from nbxtensor.ops.glu import glu_forward_kernel
78
+ from nbxtensor.ops.le import le_forward_kernel, le_scalar_kernel
79
+ from nbxtensor.ops.softplus import softplus_forward_kernel
80
+ from nbxtensor.ops.dropout import dropout_inference_kernel
81
+ from nbxtensor.ops.upsample_nearest2d import upsample_nearest2d_kernel
82
+ from nbxtensor.ops.groupnorm import group_norm_forward_kernel
83
+ from nbxtensor.ops.index_select import index_select_kernel, INDEX_SELECT_OOB
84
+ from nbxtensor.ops.triu import triu_kernel, triu_batch_kernel
85
+ from nbxtensor.ops.tril import tril_kernel, tril_batch_kernel
86
+ from nbxtensor.ops.argmax import argmax_kernel_1, argmax_kernel_2, argmax_kernel_inner
87
+ from nbxtensor.ops.argmin import argmin_kernel_1, argmin_kernel_2, argmin_kernel
88
+ from nbxtensor.ops.conv2d import conv2d_forward_kernel
89
+ from nbxtensor.ops.depthwise_conv2d import depthwise_conv2d_kernel
90
+ from nbxtensor.ops.batch_norm import batch_norm_forward_kernel
91
+ from nbxtensor.ops.cumsum import scan_part_sum_kernel, add_base_sum_kernel
92
+ from nbxtensor.ops.scatter_op import scatter_kernel, scatter_add_kernel, scatter_reduce_amax_kernel, scatter_reduce_amin_kernel
93
+ from nbxtensor.ops.gather_op import gather_kernel
94
+ from nbxtensor.ops.avg_pool2d import avg_pool2d_forward_kernel
95
+ from nbxtensor.ops.max_pool2d import max_pool2d_forward_kernel
96
+ from nbxtensor.ops.max_pool3d import max_pool3d_forward_kernel
97
+ from nbxtensor.ops.cross_entropy import cross_entropy_loss_forward_kernel
98
+ from nbxtensor.ops.exp2 import exp2_forward_kernel
99
+ from nbxtensor.ops.tan import tan_forward_kernel
100
+ from nbxtensor.ops.celu import celu_forward_kernel
101
+ from nbxtensor.ops.log_sigmoid import log_sigmoid_forward_kernel
102
+ from nbxtensor.ops.isfinite import isfinite_forward_kernel
103
+ from nbxtensor.ops.isinf import isinf_forward_kernel
104
+ from nbxtensor.ops.isnan import isnan_forward_kernel
105
+ from nbxtensor.ops.nan_to_num import nan_to_num_forward_kernel
106
+ from nbxtensor.ops.threshold import threshold_forward_kernel
107
+ from nbxtensor.ops.floor import floor_forward_kernel, ceil_forward_kernel, round_forward_kernel, trunc_forward_kernel
108
+ from nbxtensor.ops.addcdiv import addcdiv_forward_kernel
109
+ from nbxtensor.ops.addcmul import addcmul_forward_kernel
110
+ from nbxtensor.ops.all_reduce import all_kernel_mid, all_kernel_result, all_kernel_dim
111
+ from nbxtensor.ops.any_reduce import any_kernel_mid, any_kernel_result, any_kernel_dim
112
+ from nbxtensor.ops.bitwise_and import bitwise_and_forward_kernel
113
+ from nbxtensor.ops.bitwise_or import bitwise_or_forward_kernel
114
+ from nbxtensor.ops.bitwise_not import bitwise_not_forward_kernel
115
+ from nbxtensor.ops.logical_and import logical_and_forward_kernel
116
+ from nbxtensor.ops.logical_or import logical_or_forward_kernel
117
+ from nbxtensor.ops.logical_not import logical_not_forward_kernel
118
+ from nbxtensor.ops.lerp import lerp_tensor_forward_kernel, lerp_scalar_head_kernel, lerp_scalar_tail_kernel
119
+ from nbxtensor.ops.dot_op import dot_kernel_small, dot_kernel_partial, dot_kernel_reduce
120
+ from nbxtensor.ops.flip_op import flip_1d_kernel, flip_strided_kernel
121
+ from nbxtensor.ops.cat_op import cat_copy_kernel_4
122
+ from nbxtensor.ops.fill_op import fill_kernel
123
+ from nbxtensor.ops.arange_op import arange_kernel
124
+ from nbxtensor.ops.prod import prod_kernel_mid, prod_kernel_result, prod_kernel
125
+ from nbxtensor.ops.min_reduce import min_kernel_mid, min_kernel_result, min_kernel
126
+ from nbxtensor.ops.max_reduce import max_kernel_mid, max_kernel_result, max_kernel
127
+ from nbxtensor.ops.baddbmm_op import baddbmm_kernel
128
+ from nbxtensor.ops.addmv_op import addmv_kernel
129
+ from nbxtensor.ops.mse_loss import mse_loss_partial_kernel, mse_loss_reduce_kernel, mse_loss_none_kernel
130
+ from nbxtensor.ops.nllloss import nll_loss_forward_kernel
131
+ from nbxtensor.ops.std import std_map_kernel, std_reduce_kernel, std_dim_kernel
132
+ from nbxtensor.ops.var import var_kernel_1, var_kernel_2, var_welford_kernel
133
+ from nbxtensor.ops.index_add import index_add_gather_kernel
134
+ from nbxtensor.ops.index_put_op import index_put_kernel, INDEX_PUT_OOB
135
+ from nbxtensor.ops.sort_op import (radix_sort_histogram_kernel,
136
+ radix_sort_scatter_kernel,
137
+ radix_sort_tile_counts_kernel,
138
+ radix_sort_tile_prefix_kernel)
139
+ from nbxtensor.ops.rope import rope_forward_kernel
140
+ from nbxtensor.ops.pixel_shuffle import (
141
+ pixel_shuffle_kernel,
142
+ pixel_shuffle_broadcast_aware_kernel,
143
+ )
144
+ from nbxtensor.ops.pixel_unshuffle import pixel_unshuffle_kernel
145
+ from nbxtensor.ops.upsample_bilinear2d import upsample_bilinear2d_kernel
146
+ from nbxtensor.ops.adaptive_avg_pool2d import adaptive_avg_pool2d_kernel
147
+ from nbxtensor.ops.conv_depthwise2d import conv_depthwise2d_kernel
148
+ from nbxtensor.ops.scaled_softmax import scaled_softmax_kernel
149
+ from nbxtensor.ops.vector_norm import (
150
+ l2_norm_kernel, l1_norm_kernel, linf_norm_kernel, l0_norm_kernel, lp_norm_kernel,
151
+ l2_norm_pass1_kernel, l2_norm_pass2_kernel,
152
+ linf_norm_pass1_kernel, linf_norm_pass2_kernel,
153
+ )
154
+ from nbxtensor.ops.addr import addr_kernel
155
+ from nbxtensor.ops.logical_xor import logical_xor_kernel
156
+ from nbxtensor.ops.bitwise_left_shift import bitwise_left_shift_kernel
157
+ from nbxtensor.ops.bitwise_right_shift import bitwise_right_shift_kernel
158
+ from nbxtensor.ops.rand_op import rand_kernel, randn_kernel
159
+ from nbxtensor.ops.clamp_min import clamp_min_forward_kernel
160
+ from nbxtensor.ops.conv_transpose2d import conv_transpose2d_kernel
161
+ from nbxtensor.ops.cummax import scan_part_max_kernel
162
+ from nbxtensor.ops.cummin import scan_part_min_kernel
163
+ from nbxtensor.ops.count_nonzero import count_nonzero_kernel
164
+ from nbxtensor.ops.trace_op import trace_kernel
165
+ from nbxtensor.ops.linspace_op import linspace_kernel
166
+ from nbxtensor.ops.full_op import full_kernel
167
+ from nbxtensor.ops.stack_op import stack_copy_kernel
168
+ from nbxtensor.ops.repeat_op import repeat_1d_kernel
169
+ from nbxtensor.ops.upsample_nearest3d import upsample_nearest3d_kernel
170
+ from nbxtensor.ops.weight_norm import weight_norm_kernel_first, weight_norm_kernel_last
171
+ from nbxtensor.ops.repeat_interleave import repeat_interleave_tensor_kernel
172
+ from nbxtensor.ops.elementwise_launch import ew_meta as _ew_meta, ew_grid as _ew_grid
173
+ from nbxtensor.ops import tiling_sizes as _ts
174
+ import math
175
+
176
+
177
+
178
+ # ===========================================================================
179
+ # FUSED MOE WRAPPER
180
+ # ===========================================================================
181
+
182
+ # Block sizes for fused MoE kernel (tuned for decode batch=1)
183
+ _MOE_BM = 16
184
+ _MOE_BN = 64
185
+ _MOE_BK = 32
186
+ _MOE_GROUP = 8
187
+
188
+
189
+ def invoke_fused_moe(
190
+ hidden_states, # NBXTensor [M, K] — activations
191
+ expert_ptrs, # NBXTensor [E] int64 — absolute expert weight pointers
192
+ output, # NBXTensor [M * top_k, N] — pre-allocated output
193
+ topk_weights, # NBXTensor [M * top_k] — flat routing scores
194
+ sorted_token_ids, # NBXTensor [num_tokens_post_padded] — sorted indices
195
+ expert_ids, # NBXTensor [num_blocks] — expert per BLOCK_M group
196
+ num_tokens_post_padded, # NBXTensor [1] — total sorted entries
197
+ N, K, # output dim, reduction dim
198
+ stride_bk, stride_bn, # weight strides (shared by all experts)
199
+ top_k, # int
200
+ mul_routed_weight=False,
201
+ topk_divide=True,
202
+ ):
203
+ """Launch fused MoE grouped GEMM kernel (absolute pointer table).
204
+
205
+ One kernel launch handles ALL experts. Each expert's weight pointer is
206
+ stored as an absolute int64 in the table — no offset arithmetic.
207
+ """
208
+ M = hidden_states.shape[0]
209
+ # num_valid_tokens MUST be the true assignment count (tokens × top_k)
210
+ # — topk_weights is [M_tokens * top_k] on every pass. Deriving it
211
+ # from hidden_states.shape[0] was correct for the gate/up passes
212
+ # (input [M_tokens, K]) but WRONG for the down pass (input
213
+ # `activated` is [padded, N]): the inflated bound turned the
214
+ # sentinel lanes' token_mask TRUE, and the moe_weight load
215
+ # (mul_routed_weight, down pass only) read past the [n] routing
216
+ # buffer — a layout-dependent Warp Illegal Address, named by the
217
+ # CUDA coredump at fused_moe.py:107 on the Qwen3-Omni audio leg
218
+ # (immune to every sync barrier, hidden under CUDA_LAUNCH_BLOCKING
219
+ # because the heap layout — not timing — decided whether the OOB
220
+ # page was mapped).
221
+ grid, args, kwargs = _fused_moe_launch(hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids,
222
+ expert_ids, num_tokens_post_padded, N, K, stride_bk, stride_bn, top_k,
223
+ mul_routed_weight, topk_divide)
224
+ set_device(hidden_states)
225
+ fused_moe_kernel[grid](*args, **kwargs)
226
+
227
+
228
+ def _fused_moe_launch(hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids, expert_ids,
229
+ num_tokens_post_padded, N, K, stride_bk, stride_bn, top_k, mul_routed_weight, topk_divide):
230
+ """(grid, args, kwargs) of `fused_moe_kernel` for this launch — one definition for the launch and for the key its
231
+ route reads (`fused_moe_unit_tile`)."""
232
+ M = hidden_states.shape[0]
233
+ num_valid_tokens = topk_weights.shape[0]
234
+ EM = sorted_token_ids.shape[0]
235
+ if M < _MOE_BM:
236
+ EM = min(EM, M * top_k * _MOE_BM)
237
+ # the tile beyond the alignment's row block is the key's certified configuration (`fused_moe._FUSED_MOE_CONFIGS`)
238
+ grid = lambda META: (triton.cdiv(EM, _MOE_BM) * triton.cdiv(N, META['BLOCK_SIZE_N']),) # noqa: E731
239
+ args = (hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids, expert_ids, num_tokens_post_padded,
240
+ N, K, EM, num_valid_tokens, _lk.bucket_of("M", num_valid_tokens), expert_ptrs.numel(),
241
+ hidden_states.stride(0), hidden_states.stride(1), stride_bk, stride_bn, output.stride(0), output.stride(1))
242
+ kwargs = dict(BLOCK_SIZE_M=_MOE_BM, MUL_ROUTED_WEIGHT=mul_routed_weight, top_k=top_k,
243
+ compute_type=hidden_states.dtype, TOPK_DIVIDE=topk_divide)
244
+ return grid, args, kwargs
245
+
246
+
247
+ def fused_moe_unit_tile(hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids, expert_ids,
248
+ num_tokens_post_padded, N, K, stride_bk, stride_bn, top_k, mul_routed_weight=False,
249
+ topk_divide=True):
250
+ """The matrix unit's tile (a `matrix_unit.mm` row) a fused MoE launch runs at when its certificate measured the
251
+ unit faster than the FMA kernel (`autotune_certified.unit_choice`, the FMA launch's key), else None. The unit takes
252
+ experts of its operand dtype only (no split), and a launch with no certificate keeps the FMA kernel; a census
253
+ shadow and the certifier's sweep take the FMA kernel (the unit's tiles are measured beside it,
254
+ `matrix_unit_runs`). The arguments are `invoke_fused_moe`'s at the FMA alignment."""
255
+ from nbxtensor.ops._configs import matrix_unit
256
+ from nbxtensor.ops import autotune_certified as _cert
257
+ from nbxtensor.ops.launch_observer import launch_observer
258
+ if hidden_states.nbx_dtype != NBXDtype.float16 or not (matrix_unit() or {}).get("mm"):
259
+ return None
260
+ if launch_observer().active() or _cert.certifying():
261
+ return None
262
+ _grid, args, kwargs = _fused_moe_launch(hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids,
263
+ expert_ids, num_tokens_post_padded, N, K, stride_bk, stride_bn, top_k,
264
+ mul_routed_weight, topk_divide)
265
+ chosen = _cert.unit_choice(fused_moe_kernel, args, kwargs)
266
+ return chosen[1] if chosen is not None and chosen[0] == "unit" else None
267
+
268
+
269
+ def fused_moe_unit_tiles(hidden_states):
270
+ """The matrix-unit tiles a fused MoE launch on these activations can run at (`matrix_unit.mm` of the profile in
271
+ force, the unit's operand dtype only): the candidates its certification measures beside the FMA kernel."""
272
+ from nbxtensor.ops._configs import matrix_unit
273
+ from nbxtensor.ops.autotune_certified import _UNIT_TILE_FIELDS
274
+ if hidden_states.nbx_dtype != NBXDtype.float16:
275
+ return []
276
+ return [{f: int(row[f]) for f in _UNIT_TILE_FIELDS} for row in ((matrix_unit() or {}).get("mm") or [])]
277
+
278
+
279
+ def invoke_fused_moe_m8n8k4(hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids, expert_ids,
280
+ num_tokens_post_padded, N, K, stride_bk, stride_bn, top_k, tile, mul_routed_weight=False,
281
+ topk_divide=True):
282
+ """`invoke_fused_moe` on the m8n8k4 matrix unit (`fused_moe_m8n8k4_kernel`) at `tile`; the routing aligned at the
283
+ tile's rows (`moe_align_block_size(..., tile["block_m"], ...)`)."""
284
+ from nbxtensor.ops.fused_moe_m8n8k4 import fused_moe_m8n8k4_kernel
285
+ from nbxtensor.ops.matmul_m8n8k4 import mm_layouts
286
+ BM, BN, BK = int(tile["block_m"]), int(tile["block_n"]), int(tile["block_k"])
287
+ WM, WN = int(tile["warps_m"]), int(tile["warps_n"])
288
+ EM = sorted_token_ids.shape[0]
289
+ b_k_contig = stride_bk == 1 and N > 1
290
+ set_device(hidden_states)
291
+ fused_moe_m8n8k4_kernel[(triton.cdiv(EM, BM) * triton.cdiv(N, BN),)](
292
+ hidden_states, expert_ptrs, output, topk_weights, sorted_token_ids, expert_ids, num_tokens_post_padded,
293
+ N, K, EM, topk_weights.shape[0],
294
+ hidden_states.stride(0), hidden_states.stride(1), stride_bk, stride_bn, output.stride(0), output.stride(1),
295
+ MUL_ROUTED_WEIGHT=bool(mul_routed_weight), TOP_K=int(top_k), TOPK_DIVIDE=bool(topk_divide),
296
+ B_K_CONTIG=b_k_contig, MB=BM // 16, NB=BN // 16, BK=BK, GROUP_M=int(tile["group_m"]),
297
+ num_warps=WM * WN, **mm_layouts(BM // 16, BN // 16, WM, WN, BK, b_k_contig))
298
+
299
+
300
+ def invoke_fused_moe_wna16(
301
+ hidden_states, # NBXTensor [M, K] — activations
302
+ qw_ptrs, sc_ptrs, mn_ptrs, # NBXTensor [E] int64 — triplet tables
303
+ output,
304
+ topk_weights,
305
+ sorted_token_ids,
306
+ expert_ids,
307
+ num_tokens_post_padded,
308
+ N, K,
309
+ stride_qk, stride_qn, # packed int32 strides
310
+ stride_sg, stride_sn, # scales/mins strides
311
+ top_k,
312
+ mul_routed_weight=False,
313
+ topk_divide=True,
314
+ ):
315
+ """Launch the W4 fused MoE grouped GEMM (int4-g128-asym experts,
316
+ in-register dequant — byte-gated vs fused_moe_fp32b_kernel).
317
+ Same launch contract as invoke_fused_moe; _MOE_BK (32) divides the
318
+ quant group (128) so a K-tile never crosses a group boundary."""
319
+ from nbxtensor.ops.fused_moe import fused_moe_wna16_kernel
320
+ M = hidden_states.shape[0]
321
+ num_valid_tokens = topk_weights.shape[0]
322
+ EM = sorted_token_ids.shape[0]
323
+ if M < _MOE_BM:
324
+ EM = min(EM, M * top_k * _MOE_BM)
325
+ grid = (triton.cdiv(EM, _MOE_BM) * triton.cdiv(N, _MOE_BN),)
326
+ set_device(hidden_states)
327
+
328
+ fused_moe_wna16_kernel[grid](
329
+ hidden_states, qw_ptrs, sc_ptrs, mn_ptrs, output,
330
+ topk_weights,
331
+ sorted_token_ids, expert_ids, num_tokens_post_padded,
332
+ N, K, EM, num_valid_tokens,
333
+ hidden_states.stride(0), hidden_states.stride(1),
334
+ stride_qk, stride_qn,
335
+ stride_sg, stride_sn,
336
+ output.stride(0), output.stride(1),
337
+ BLOCK_SIZE_M=_MOE_BM, BLOCK_SIZE_N=_MOE_BN, BLOCK_SIZE_K=_MOE_BK,
338
+ GROUP_SIZE_M=_MOE_GROUP,
339
+ MUL_ROUTED_WEIGHT=mul_routed_weight,
340
+ top_k=top_k,
341
+ compute_type=hidden_states.dtype,
342
+ QGROUP=128, QPACK=8,
343
+ TOPK_DIVIDE=topk_divide,
344
+ num_warps=4, num_stages=2,
345
+ )
@@ -0,0 +1,79 @@
1
+ """MSE Loss kernels — extracted from FlagGems.
2
+
3
+ Pure Triton. ZERO PyTorch imports.
4
+
5
+ Two-pass reduction:
6
+ kernel_1: Per-block partial (input - target)^2, reduced by mean or sum.
7
+ kernel_2: Final reduction across blocks.
8
+
9
+ Reduction modes: 1 = mean, 2 = sum.
10
+ For reduction=0 (none), use a simple pointwise kernel instead.
11
+ """
12
+
13
+ import triton
14
+ import triton.language as tl
15
+
16
+ @triton.jit
17
+ def mse_loss_partial_kernel(
18
+ inp,
19
+ target,
20
+ mid,
21
+ M,
22
+ BLOCK_SIZE: tl.constexpr,
23
+ reduction: tl.constexpr,
24
+ ):
25
+ """Pass 1: per-block squared difference, reduced to partial sums.
26
+
27
+ For reduction==1 (mean): each block stores sum((inp-target)^2) / M.
28
+ For reduction==2 (sum): each block stores sum((inp-target)^2).
29
+ """
30
+ pid = tl.program_id(0).to(tl.int64)
31
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
32
+ mask = offset < M
33
+
34
+ inp_val = tl.load(inp + offset, mask=mask, other=0).to(tl.float32)
35
+ target_val = tl.load(target + offset, mask=mask, other=0).to(tl.float32)
36
+ sub = inp_val - target_val
37
+ pow_val = sub * sub
38
+
39
+ # reduction == 1: mean, reduction == 2: sum
40
+ if reduction == 1:
41
+ sum_val = tl.sum(pow_val) / M
42
+ else:
43
+ sum_val = tl.sum(pow_val)
44
+
45
+ tl.store(mid + pid, sum_val)
46
+
47
+ @triton.jit
48
+ def mse_loss_reduce_kernel(
49
+ mid,
50
+ out,
51
+ mid_size,
52
+ BLOCK_MID: tl.constexpr,
53
+ ):
54
+ """Pass 2: sum all partial results into a single scalar."""
55
+ offset = tl.arange(0, BLOCK_MID)
56
+ mask = offset < mid_size
57
+ mid_val = tl.load(mid + offset, mask=mask, other=0).to(tl.float32)
58
+ sum_val = tl.sum(mid_val)
59
+ tl.store(out, sum_val)
60
+
61
+ @triton.jit
62
+ def mse_loss_none_kernel(
63
+ inp_ptr,
64
+ target_ptr,
65
+ output_ptr,
66
+ n_elements,
67
+ BLOCK_SIZE: tl.constexpr,
68
+ ):
69
+ """Pointwise (no reduction): output[i] = (input[i] - target[i])^2."""
70
+ pid = tl.program_id(0).to(tl.int64)
71
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
72
+ mask = offset < n_elements
73
+
74
+ x = tl.load(inp_ptr + offset, mask=mask, other=0).to(tl.float32)
75
+ y = tl.load(target_ptr + offset, mask=mask, other=0).to(tl.float32)
76
+
77
+ diff = x - y
78
+ result = diff * diff
79
+ tl.store(output_ptr + offset, result, mask=mask)
nbxtensor/ops/mul.py ADDED
@@ -0,0 +1,51 @@
1
+ """Multiply — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def mul_forward_kernel(
8
+ x_ptr, y_ptr, output_ptr,
9
+ n_elements,
10
+ BLOCK_SIZE: tl.constexpr,
11
+ ):
12
+ """out = x * y (tensor * tensor)"""
13
+ pid = tl.program_id(0).to(tl.int64)
14
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
15
+ mask = offset < n_elements
16
+
17
+ x = tl.load(x_ptr + offset, mask=mask)
18
+ y = tl.load(y_ptr + offset, mask=mask)
19
+ tl.store(output_ptr + offset, x * y, mask=mask)
20
+
21
+ @triton.jit
22
+ def mul_scalar_kernel(
23
+ x_ptr, output_ptr,
24
+ n_elements,
25
+ scalar,
26
+ BLOCK_SIZE: tl.constexpr,
27
+ ):
28
+ """out = x * scalar"""
29
+ pid = tl.program_id(0).to(tl.int64)
30
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
31
+ mask = offset < n_elements
32
+
33
+ x = tl.load(x_ptr + offset, mask=mask)
34
+ tl.store(output_ptr + offset, x * scalar, mask=mask)
35
+
36
+
37
+ @triton.jit
38
+ def mul_scalar_dev_kernel(
39
+ x_ptr, s_ptr, output_ptr,
40
+ n_elements,
41
+ BLOCK_SIZE: tl.constexpr,
42
+ ):
43
+ """out = x * s where s is a 0-d DEVICE tensor. Bit-exact mirror
44
+ of mul_scalar_kernel (host float(s) -> f32 arg == load -> f64 ->
45
+ f32). Device-scalar increment 2026-08-15."""
46
+ pid = tl.program_id(0).to(tl.int64)
47
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
48
+ mask = offset < n_elements
49
+ s = tl.load(s_ptr).to(tl.float64).to(tl.float32)
50
+ x = tl.load(x_ptr + offset, mask=mask)
51
+ tl.store(output_ptr + offset, x * s, mask=mask)
@@ -0,0 +1,23 @@
1
+ """NanToNum — pure @triton.jit kernel. Logic from FlagGems."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def nan_to_num_forward_kernel(
8
+ input_ptr, output_ptr,
9
+ n_elements,
10
+ nan_val, posinf_val, neginf_val,
11
+ BLOCK_SIZE: tl.constexpr,
12
+ ):
13
+ pid = tl.program_id(0).to(tl.int64)
14
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
15
+ mask = offset < n_elements
16
+
17
+ x = tl.load(input_ptr + offset, mask=mask)
18
+ pos_inf = float('inf')
19
+ neg_inf = float('-inf')
20
+ out = tl.where(x != x, nan_val,
21
+ tl.where(x == pos_inf, posinf_val,
22
+ tl.where(x == neg_inf, neginf_val, x)))
23
+ tl.store(output_ptr + offset, out, mask=mask)
nbxtensor/ops/ne.py ADDED
@@ -0,0 +1,32 @@
1
+ """Not equal — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def ne_forward_kernel(
8
+ x_ptr, y_ptr, output_ptr,
9
+ n_elements,
10
+ BLOCK_SIZE: tl.constexpr,
11
+ ):
12
+ pid = tl.program_id(0).to(tl.int64)
13
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
14
+ mask = offset < n_elements
15
+
16
+ x = tl.load(x_ptr + offset, mask=mask)
17
+ y = tl.load(y_ptr + offset, mask=mask)
18
+ tl.store(output_ptr + offset, (x != y).to(tl.int1), mask=mask)
19
+
20
+ @triton.jit
21
+ def ne_scalar_kernel(
22
+ x_ptr, output_ptr,
23
+ n_elements,
24
+ scalar,
25
+ BLOCK_SIZE: tl.constexpr,
26
+ ):
27
+ pid = tl.program_id(0).to(tl.int64)
28
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
29
+ mask = offset < n_elements
30
+
31
+ x = tl.load(x_ptr + offset, mask=mask)
32
+ tl.store(output_ptr + offset, (x != scalar).to(tl.int1), mask=mask)