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,74 @@
1
+ """Max pooling 2D with indices — pure @triton.jit kernel.
2
+
3
+ Extracted from FlagGems max_pool2d_with_indices.py. Forward only (inference).
4
+ 2D blocked approach, returns both output values and indices of max elements.
5
+ Uses float('-inf') as min value instead of FlagGems get_dtype_min().
6
+ """
7
+
8
+ import triton
9
+ import triton.language as tl
10
+
11
+
12
+ @triton.jit
13
+ def max_pool2d_forward_kernel(
14
+ input_ptr,
15
+ output_ptr,
16
+ indices_ptr,
17
+ in_stride_n, in_stride_c, in_stride_h, in_stride_w,
18
+ in_c, in_h, in_w,
19
+ out_h, out_w,
20
+ kernel_h: tl.constexpr,
21
+ kernel_w: tl.constexpr,
22
+ stride_h: tl.constexpr,
23
+ stride_w: tl.constexpr,
24
+ padding_h: tl.constexpr,
25
+ padding_w: tl.constexpr,
26
+ dilation_h: tl.constexpr,
27
+ dilation_w: tl.constexpr,
28
+ BLOCK_H: tl.constexpr,
29
+ BLOCK_W: tl.constexpr,
30
+ ):
31
+ pid_nc = tl.program_id(0).to(tl.int64)
32
+ pid_hw = tl.program_id(1).to(tl.int64)
33
+ num_w_blocks = tl.cdiv(out_w, BLOCK_W)
34
+ h_block_idx = pid_hw // num_w_blocks
35
+ w_block_idx = pid_hw % num_w_blocks
36
+ n_idx = pid_nc // in_c
37
+ c_idx = pid_nc % in_c
38
+
39
+ h_out_offsets = h_block_idx * BLOCK_H + tl.arange(0, BLOCK_H)
40
+ w_out_offsets = w_block_idx * BLOCK_W + tl.arange(0, BLOCK_W)
41
+
42
+ min_val = float('-inf')
43
+ max_val_acc = tl.full((BLOCK_H, BLOCK_W), min_val, dtype=input_ptr.type.element_ty)
44
+ max_idx_acc = tl.full((BLOCK_H, BLOCK_W), -1, dtype=tl.int64)
45
+
46
+ input_base_ptr = input_ptr + n_idx * in_stride_n + c_idx * in_stride_c
47
+
48
+ for kh in tl.static_range(0, kernel_h):
49
+ for kw in tl.static_range(0, kernel_w):
50
+ h_in = h_out_offsets[:, None] * stride_h - padding_h + kh * dilation_h
51
+ w_in = w_out_offsets[None, :] * stride_w - padding_w + kw * dilation_w
52
+ in_mask = (h_in >= 0) & (h_in < in_h) & (w_in >= 0) & (w_in < in_w)
53
+ input_offset = h_in * in_stride_h + w_in * in_stride_w
54
+ current_val = tl.load(
55
+ input_base_ptr + input_offset, mask=in_mask, other=min_val
56
+ )
57
+ current_idx = h_in * in_w + w_in
58
+
59
+ is_new_max = current_val > max_val_acc
60
+ max_val_acc = tl.where(is_new_max, current_val, max_val_acc)
61
+ max_idx_acc = tl.where(is_new_max & in_mask, current_idx, max_idx_acc)
62
+
63
+ out_base_ptr = output_ptr + pid_nc * out_h * out_w
64
+ indices_base_ptr = indices_ptr + pid_nc * out_h * out_w
65
+ output_block_ptr = (
66
+ out_base_ptr + h_out_offsets[:, None] * out_w + w_out_offsets[None, :]
67
+ )
68
+ indices_block_ptr = (
69
+ indices_base_ptr + h_out_offsets[:, None] * out_w + w_out_offsets[None, :]
70
+ )
71
+
72
+ out_mask = (h_out_offsets[:, None] < out_h) & (w_out_offsets[None, :] < out_w)
73
+ tl.store(output_block_ptr, max_val_acc, mask=out_mask)
74
+ tl.store(indices_block_ptr, max_idx_acc, mask=out_mask)
@@ -0,0 +1,93 @@
1
+ """Max pooling 3D with indices — pure @triton.jit kernel.
2
+
3
+ 3D (temporal) extension of ops/max_pool2d.py (FlagGems-derived blocked
4
+ kernel): one program per (n, c, t_out) output plane block, with a
5
+ static kt x kh x kw window scan. Forward only (inference). Returns both
6
+ output values and int64 indices of the max elements; indices follow the
7
+ PyTorch max_pool3d_with_indices convention — flattened offset into the
8
+ (T, H, W) volume of each (n, c) plane, ties resolved to the FIRST
9
+ maximum in (t, h, w) window scan order (strict `>` update, same as the
10
+ 2D kernel). Uses float('-inf') as the identity like the 2D kernel.
11
+ """
12
+
13
+ import triton
14
+ import triton.language as tl
15
+
16
+
17
+ @triton.jit
18
+ def max_pool3d_forward_kernel(
19
+ input_ptr,
20
+ output_ptr,
21
+ indices_ptr,
22
+ in_stride_n, in_stride_c, in_stride_t, in_stride_h, in_stride_w,
23
+ in_c, in_t, in_h, in_w,
24
+ out_t, out_h, out_w,
25
+ kernel_t: tl.constexpr,
26
+ kernel_h: tl.constexpr,
27
+ kernel_w: tl.constexpr,
28
+ stride_t: tl.constexpr,
29
+ stride_h: tl.constexpr,
30
+ stride_w: tl.constexpr,
31
+ padding_t: tl.constexpr,
32
+ padding_h: tl.constexpr,
33
+ padding_w: tl.constexpr,
34
+ dilation_t: tl.constexpr,
35
+ dilation_h: tl.constexpr,
36
+ dilation_w: tl.constexpr,
37
+ BLOCK_H: tl.constexpr,
38
+ BLOCK_W: tl.constexpr,
39
+ ):
40
+ pid_nct = tl.program_id(0).to(tl.int64)
41
+ pid_hw = tl.program_id(1).to(tl.int64)
42
+ num_w_blocks = tl.cdiv(out_w, BLOCK_W)
43
+ h_block_idx = pid_hw // num_w_blocks
44
+ w_block_idx = pid_hw % num_w_blocks
45
+ t_out_idx = pid_nct % out_t
46
+ nc_idx = pid_nct // out_t
47
+ n_idx = nc_idx // in_c
48
+ c_idx = nc_idx % in_c
49
+
50
+ h_out_offsets = h_block_idx * BLOCK_H + tl.arange(0, BLOCK_H)
51
+ w_out_offsets = w_block_idx * BLOCK_W + tl.arange(0, BLOCK_W)
52
+
53
+ min_val = float('-inf')
54
+ max_val_acc = tl.full((BLOCK_H, BLOCK_W), min_val, dtype=input_ptr.type.element_ty)
55
+ max_idx_acc = tl.full((BLOCK_H, BLOCK_W), -1, dtype=tl.int64)
56
+
57
+ input_base_ptr = input_ptr + n_idx * in_stride_n + c_idx * in_stride_c
58
+
59
+ for kt in tl.static_range(0, kernel_t):
60
+ t_in = t_out_idx * stride_t - padding_t + kt * dilation_t
61
+ t_ok = (t_in >= 0) & (t_in < in_t)
62
+ for kh in tl.static_range(0, kernel_h):
63
+ for kw in tl.static_range(0, kernel_w):
64
+ h_in = h_out_offsets[:, None] * stride_h - padding_h + kh * dilation_h
65
+ w_in = w_out_offsets[None, :] * stride_w - padding_w + kw * dilation_w
66
+ in_mask = (t_ok
67
+ & (h_in >= 0) & (h_in < in_h)
68
+ & (w_in >= 0) & (w_in < in_w))
69
+ input_offset = (t_in * in_stride_t
70
+ + h_in * in_stride_h + w_in * in_stride_w)
71
+ current_val = tl.load(
72
+ input_base_ptr + input_offset, mask=in_mask, other=min_val
73
+ )
74
+ # PyTorch convention: flattened (t, h, w) offset per (n, c).
75
+ current_idx = ((t_in * in_h + h_in) * in_w + w_in).to(tl.int64)
76
+
77
+ is_new_max = current_val > max_val_acc
78
+ max_val_acc = tl.where(is_new_max, current_val, max_val_acc)
79
+ max_idx_acc = tl.where(is_new_max & in_mask, current_idx, max_idx_acc)
80
+
81
+ plane = out_h * out_w
82
+ out_base_ptr = output_ptr + pid_nct * plane
83
+ indices_base_ptr = indices_ptr + pid_nct * plane
84
+ output_block_ptr = (
85
+ out_base_ptr + h_out_offsets[:, None] * out_w + w_out_offsets[None, :]
86
+ )
87
+ indices_block_ptr = (
88
+ indices_base_ptr + h_out_offsets[:, None] * out_w + w_out_offsets[None, :]
89
+ )
90
+
91
+ out_mask = (h_out_offsets[:, None] < out_h) & (w_out_offsets[None, :] < out_w)
92
+ tl.store(output_block_ptr, max_val_acc, mask=out_mask)
93
+ tl.store(indices_block_ptr, max_idx_acc, mask=out_mask)
@@ -0,0 +1,91 @@
1
+ """Max reduction — pure @triton.jit kernels.
2
+
3
+ Global two-pass max and dim-specific max (returns value + index).
4
+ Extracted from FlagGems (Apache-2.0).
5
+
6
+ Note: FlagGems uses `get_dtype_min` from utils.limits. We inline the
7
+ sentinel via float('-inf') which Triton handles for all float dtypes.
8
+ For the dim kernel, bf16 accumulation is promoted to fp32.
9
+ """
10
+
11
+ import triton
12
+ import triton.language as tl
13
+
14
+
15
+ # ---------------------------------------------------------------------------
16
+ # Global reduction: two-pass max
17
+ # ---------------------------------------------------------------------------
18
+
19
+ @triton.jit
20
+ def max_kernel_mid(
21
+ inp,
22
+ mid,
23
+ M,
24
+ BLOCK_SIZE: tl.constexpr,
25
+ ):
26
+ """Pass 1: compute block-local max."""
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
+ inp_ptrs = inp + offset
30
+ mask = offset < M
31
+ inp_val = tl.load(inp_ptrs, mask=mask, other=float('-inf'))
32
+ max_val = tl.max(inp_val)
33
+ mid_ptr = mid + pid
34
+ tl.store(mid_ptr, max_val)
35
+
36
+
37
+ @triton.jit
38
+ def max_kernel_result(mid, out, mid_size, BLOCK_MID: tl.constexpr):
39
+ """Pass 2: reduce partial maxes into scalar."""
40
+ offset = tl.arange(0, BLOCK_MID)
41
+ mid_ptrs = mid + offset
42
+ mask = offset < mid_size
43
+ mid_val = tl.load(mid_ptrs, mask=mask, other=float('-inf'))
44
+ max_val = tl.max(mid_val)
45
+ tl.store(out, max_val)
46
+
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # Dim-specific: max along one axis (returns value + argmax index)
50
+ # ---------------------------------------------------------------------------
51
+
52
+ @triton.jit
53
+ def max_kernel(
54
+ inp,
55
+ out_value,
56
+ out_index,
57
+ M,
58
+ N,
59
+ BLOCK_M: tl.constexpr,
60
+ BLOCK_N: tl.constexpr,
61
+ ):
62
+ """Max reduction along compressed inner dim N.
63
+
64
+ inp: [M, N] (dim-compressed) → out_value: [M], out_index: [M] (int64)
65
+ Tracks both maximum value and its index (argmax).
66
+ bf16 inputs are accumulated in fp32 to avoid precision issues.
67
+ """
68
+ pid_m = tl.program_id(0).to(tl.int64)
69
+ m_offset = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
70
+
71
+ dtype = inp.type.element_ty
72
+ acc_type = tl.float32 if dtype is tl.bfloat16 else dtype
73
+ result_value = tl.full([BLOCK_M], value=float('-inf'), dtype=acc_type)
74
+ result_index = tl.zeros([BLOCK_M], dtype=tl.int64)
75
+ for i in range(0, N, BLOCK_N):
76
+ n_offset = i + tl.arange(0, BLOCK_N)
77
+ offset = m_offset[:, None] * N + n_offset[None, :]
78
+ mask = (m_offset[:, None] < M) & (n_offset[None, :] < N)
79
+ inp_ptrs = inp + offset
80
+ inp_vals = tl.load(inp_ptrs, mask=mask, other=float('-inf'))
81
+ max_value, max_index = tl.max(inp_vals, axis=1, return_indices=True)
82
+ update_mask = max_value > result_value
83
+ result_value = tl.where(update_mask, max_value, result_value)
84
+ result_index = tl.where(update_mask, i + max_index, result_index)
85
+
86
+ mask1 = m_offset < M
87
+ offset_index = m_offset
88
+ out_value_ptrs = out_value + offset_index
89
+ out_index_ptrs = out_index + offset_index
90
+ tl.store(out_value_ptrs, result_value, mask=mask1)
91
+ tl.store(out_index_ptrs, result_index, mask=mask1)
@@ -0,0 +1,18 @@
1
+ """Element-wise maximum — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def maximum_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, tl.maximum(x, y), mask=mask)
nbxtensor/ops/mean.py ADDED
@@ -0,0 +1,40 @@
1
+ """Mean reduction — pure @triton.jit kernel, the row walked in tiles of the certified width."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ from nbxtensor.ops._configs import nbx_autotune, row_reduce_configs, prune_row_reduce
7
+
8
+
9
+ @nbx_autotune(configs=row_reduce_configs(), key=['BATCH_BUCKET', 'FEAT_BUCKET'],
10
+ prune_configs_by={'early_config_prune': prune_row_reduce}, cache_results=True)
11
+ @triton.jit
12
+ def mean_forward_kernel(
13
+ input_ptr, output_ptr,
14
+ batch_dim, feat_dim, BATCH_BUCKET, FEAT_BUCKET,
15
+ input_batch_stride, input_feat_stride,
16
+ BLOCK_SIZE_BATCH: tl.constexpr,
17
+ BLOCK_SIZE_FEAT: tl.constexpr,
18
+ ):
19
+ """Mean reduction over the last dimension: input [batch_dim, feat_dim] -> output [batch_dim].
20
+
21
+ The first tile is reduced alone and every further tile combined into it, so a row that fits one
22
+ tile is reduced by exactly the instructions it was before the loop existed.
23
+ """
24
+ batch_pid = tl.program_id(0).to(tl.int64)
25
+ batch_offset = batch_pid * BLOCK_SIZE_BATCH + tl.arange(0, BLOCK_SIZE_BATCH)
26
+ feat_offset = tl.arange(0, BLOCK_SIZE_FEAT)
27
+ batch_mask = batch_offset < batch_dim
28
+ row_ptr = input_ptr + input_batch_stride * batch_offset[:, None]
29
+
30
+ feat_mask = feat_offset < feat_dim
31
+ inp = tl.load(row_ptr + input_feat_stride * feat_offset[None, :],
32
+ mask=batch_mask[:, None] & feat_mask[None, :], other=0.0).to(tl.float32)
33
+ result = tl.sum(inp, axis=1)
34
+ for start in range(BLOCK_SIZE_FEAT, feat_dim, BLOCK_SIZE_FEAT):
35
+ offs = start + feat_offset
36
+ feat_mask = offs < feat_dim
37
+ inp = tl.load(row_ptr + input_feat_stride * offs[None, :].to(tl.int64),
38
+ mask=batch_mask[:, None] & feat_mask[None, :], other=0.0).to(tl.float32)
39
+ result += tl.sum(inp, axis=1)
40
+ tl.store(output_ptr + batch_offset, result / feat_dim, mask=batch_mask)
@@ -0,0 +1,91 @@
1
+ """Min reduction — pure @triton.jit kernels.
2
+
3
+ Global two-pass min and dim-specific min (returns value + index).
4
+ Extracted from FlagGems (Apache-2.0).
5
+
6
+ Note: FlagGems uses `get_dtype_max` from utils.limits. We inline the
7
+ sentinel via float('inf') which Triton handles for all float dtypes.
8
+ For the dim kernel, bf16 accumulation is promoted to fp32.
9
+ """
10
+
11
+ import triton
12
+ import triton.language as tl
13
+
14
+
15
+ # ---------------------------------------------------------------------------
16
+ # Global reduction: two-pass min
17
+ # ---------------------------------------------------------------------------
18
+
19
+ @triton.jit
20
+ def min_kernel_mid(
21
+ inp,
22
+ mid,
23
+ M,
24
+ BLOCK_SIZE: tl.constexpr,
25
+ ):
26
+ """Pass 1: compute block-local min."""
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
+ inp_ptrs = inp + offset
30
+ mask = offset < M
31
+ inp_val = tl.load(inp_ptrs, mask=mask, other=float('inf'))
32
+ min_val = tl.min(inp_val)
33
+ mid_ptr = mid + pid
34
+ tl.store(mid_ptr, min_val)
35
+
36
+
37
+ @triton.jit
38
+ def min_kernel_result(mid, out, mid_size, BLOCK_MID: tl.constexpr):
39
+ """Pass 2: reduce partial mins into scalar."""
40
+ offset = tl.arange(0, BLOCK_MID)
41
+ mid_ptrs = mid + offset
42
+ mask = offset < mid_size
43
+ mid_val = tl.load(mid_ptrs, mask=mask, other=float('inf'))
44
+ min_val = tl.min(mid_val)
45
+ tl.store(out, min_val)
46
+
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # Dim-specific: min along one axis (returns value + argmin index)
50
+ # ---------------------------------------------------------------------------
51
+
52
+ @triton.jit
53
+ def min_kernel(
54
+ inp,
55
+ out_value,
56
+ out_index,
57
+ M,
58
+ N,
59
+ BLOCK_M: tl.constexpr,
60
+ BLOCK_N: tl.constexpr,
61
+ ):
62
+ """Min reduction along compressed inner dim N.
63
+
64
+ inp: [M, N] (dim-compressed) → out_value: [M], out_index: [M] (int64)
65
+ Tracks both minimum value and its index (argmin).
66
+ bf16 inputs are accumulated in fp32 to avoid precision issues.
67
+ """
68
+ pid_m = tl.program_id(0).to(tl.int64)
69
+ m_offset = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
70
+
71
+ dtype = inp.type.element_ty
72
+ acc_type = tl.float32 if dtype is tl.bfloat16 else dtype
73
+ min_values = tl.full([BLOCK_M], dtype=acc_type, value=float('inf'))
74
+ argmin_values = tl.full([BLOCK_M], dtype=tl.int64, value=0)
75
+ for start_n in range(0, N, BLOCK_N):
76
+ n_offset = start_n + tl.arange(0, BLOCK_N)
77
+ offset = m_offset[:, None] * N + n_offset[None, :]
78
+ mask = (m_offset[:, None] < M) & (n_offset[None, :] < N)
79
+ inp_ptrs = inp + offset
80
+ inp_vals = tl.load(inp_ptrs, mask=mask, other=float('inf'))
81
+ local_min, local_argmin = tl.min(inp_vals, 1, return_indices=True)
82
+ update = local_min < min_values
83
+ min_values = tl.where(update, local_min, min_values)
84
+ argmin_values = tl.where(update, start_n + local_argmin, argmin_values)
85
+
86
+ offset_index = m_offset
87
+ out_value_ptrs = out_value + offset_index
88
+ out_index_ptrs = out_index + offset_index
89
+ mask1 = m_offset < M
90
+ tl.store(out_value_ptrs, min_values, mask=mask1)
91
+ tl.store(out_index_ptrs, argmin_values, mask=mask1)
@@ -0,0 +1,18 @@
1
+ """Element-wise minimum — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def minimum_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, tl.minimum(x, y), mask=mask)
nbxtensor/ops/mish.py ADDED
@@ -0,0 +1,22 @@
1
+ """Mish — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ from ._common import tanh_fn
7
+
8
+ @triton.jit
9
+ def mish_forward_kernel(
10
+ input_ptr, output_ptr,
11
+ n_elements,
12
+ BLOCK_SIZE: tl.constexpr,
13
+ ):
14
+ pid = tl.program_id(0).to(tl.int64)
15
+ 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)
16
+ mask = offset < n_elements
17
+
18
+ x = tl.load(input_ptr + offset, mask=mask)
19
+ x_fp32 = x.to(tl.float32)
20
+ # mish = x * tanh(softplus(x)) = x * tanh(ln(1 + exp(x)))
21
+ out = x_fp32 * tanh_fn(tl.log(1.0 + tl.exp(x_fp32)))
22
+ tl.store(output_ptr + offset, out, mask=mask)
@@ -0,0 +1,152 @@
1
+ """The m8n8k4 matrix unit (sm_70 tensor cores, SASS HMMA.884) as a Gluon building block.
2
+
3
+ Triton >= 3.3 lowers `tl.dot` to scalar FMA below sm_80 (triton-lang/triton#5066), so an arch whose profile
4
+ declares `matrix_unit.shape: m8n8k4` gets its tensor cores from here: our own Gluon kernels issue
5
+ `mma.sync.aligned.m8n8k4.row.col.f32.f16.f16.f32` through `inline_asm_elementwise`, with the operands placed in
6
+ registers by linear layouts. Method and proofs: docs/reference/tensor-cores-through-linear-layouts.md.
7
+
8
+ The fragment (CUTLASS cute/atom/mma_traits_sm70.hpp, SM70_8x8x4_F32F16F16F32_TN): lane = a0 + 2 a1 + 4 q0 + 8 q1
9
+ + 16 b, thread t = a0 + 2 a1 + 4 b of quadpair q holds A row t and B column t (k = 0..3), and accumulator
10
+ register v = v0 + 2 v1 + 4 v2 holds D[m = a0 + 2 v1 + 4 b, n = v0 + 2 a1 + 4 v2]; the four quadpairs tile 16x16.
11
+
12
+ A [BM, BN] accumulator lives as the 7-D tensor [MB, 2, 8, NB, 2, 2, 4] = (mb, mi3, mi2..0, nb, ni3, ni2, ni1..0),
13
+ m = 16 mb + mi, n = 16 nb + ni (row-major order, so a reshape to [BM, BN] moves nothing). In these coordinates the
14
+ A fragment depends only on (mb, mi3, mi2..0, ni1..0) and the B fragment only on (mi2..0, nb, ni3, ni1..0): each is
15
+ a plain broadcast of [MB, 2, 8, 1, 1, 1, 4] / [1, 1, 8, NB, 2, 1, 4], which `inline_asm_elementwise` broadcasts
16
+ itself, so one register fragment feeds every sub-tile that shares it. Operands come from shared memory laid out
17
+ [k-step x rows, 4] (k innermost, 8 bytes per row) and are read in a linear layout derived from the accumulator's;
18
+ the reshape/permute to the broadcast shape is a relabelling, which `convert_layout(assert_trivial=True)` proves.
19
+ """
20
+
21
+ from triton.experimental import gluon
22
+ from triton.experimental.gluon import language as gl
23
+
24
+ #: What the instruction below takes, as a hardware profile's `matrix_unit` names it (checked by
25
+ #: `_configs.matrix_unit`: a profile cannot declare dtypes this instruction does not compute in). `k` is the
26
+ #: columns one instruction reduces: the split flash's `block_k` is a multiple of it (KSA/KSB count instructions).
27
+ UNIT = {"shape": "m8n8k4", "operand_dtype": "float16", "accumulator_dtype": "float32", "k": 4}
28
+
29
+ MMA_ASM: gl.constexpr = gl.constexpr(
30
+ "mma.sync.aligned.m8n8k4.row.col.f32.f16.f16.f32 {$0,$1,$2,$3,$4,$5,$6,$7}, {$8, $9}, {$12, $13},"
31
+ " {$16,$17,$18,$19,$20,$21,$22,$23};")
32
+ # pack=8: eight accumulator elements per call; f16 operands arrive two per 32-bit register, so A and B are four
33
+ # registers each of which the instruction reads the first two (k = 0..3; the other two repeat them).
34
+ MMA_CONSTRAINTS: gl.constexpr = gl.constexpr(",".join(["=f"] * 8 + ["r"] * 8 + ["f"] * 8))
35
+
36
+
37
+ def _bits(n: int):
38
+ return [1 << i for i in range(n.bit_length() - 1)]
39
+
40
+
41
+ def _e7(d: int, x: int):
42
+ v = [0] * 7
43
+ v[d] = x
44
+ return v
45
+
46
+
47
+ def acc_layout(MB: int, NB: int, WM: int, WN: int):
48
+ """The [MB, 2, 8, NB, 2, 2, 4] accumulator over WM x WN warps (WM | MB, WN | NB, all powers of two)."""
49
+ rm = [x * WM for x in _bits(MB // WM)]
50
+ rn = [x * WN for x in _bits(NB // WN)]
51
+ return gl.DistributedLinearLayout(
52
+ reg_bases=[_e7(6, 1), _e7(2, 2), _e7(5, 1)] + [_e7(3, x) for x in rn] + [_e7(0, x) for x in rm],
53
+ lane_bases=[_e7(2, 1), _e7(6, 2), _e7(1, 1), _e7(4, 1), _e7(2, 4)],
54
+ warp_bases=[_e7(0, x) for x in _bits(WM)] + [_e7(3, x) for x in _bits(WN)],
55
+ block_bases=[], shape=[MB, 2, 8, NB, 2, 2, 4])
56
+
57
+
58
+ def frag_a_layout(MB: int, NB: int, WM: int, WN: int):
59
+ """One k-step of the A operand, [16 MB, 4] = (row, k), in the registers acc_layout(MB, NB, WM, WN) needs."""
60
+ rm = [x * WM for x in _bits(MB // WM)]
61
+ rn = [x * WN for x in _bits(NB // WN)]
62
+ return gl.DistributedLinearLayout(
63
+ reg_bases=[[0, 1], [0, 2], [0, 0]] + [[0, 0]] * len(rn) + [[16 * x, 0] for x in rm],
64
+ lane_bases=[[1, 0], [2, 0], [8, 0], [0, 0], [4, 0]],
65
+ warp_bases=[[16 * x, 0] for x in _bits(WM)] + [[0, 0]] * len(_bits(WN)),
66
+ block_bases=[], shape=[16 * MB, 4])
67
+
68
+
69
+ def frag_b_layout(MB: int, NB: int, WM: int, WN: int):
70
+ """One k-step of the B operand, [16 NB, 4] = (column, k), in the registers acc_layout(MB, NB, WM, WN) needs."""
71
+ rm = [x * WM for x in _bits(MB // WM)]
72
+ rn = [x * WN for x in _bits(NB // WN)]
73
+ return gl.DistributedLinearLayout(
74
+ reg_bases=[[0, 1], [0, 2], [0, 0]] + [[16 * x, 0] for x in rn] + [[0, 0]] * len(rm),
75
+ lane_bases=[[1, 0], [2, 0], [0, 0], [8, 0], [4, 0]],
76
+ warp_bases=[[0, 0]] * len(_bits(WM)) + [[16 * x, 0] for x in _bits(WN)],
77
+ block_bases=[], shape=[16 * NB, 4])
78
+
79
+
80
+ @gluon.jit
81
+ def acc_rows_cols(L: gl.constexpr, MB: gl.constexpr, NB: gl.constexpr):
82
+ """Row and column index of every accumulator element, broadcastable over L ([.., 1, 1, 1, 1] / [1, 1, 1, ..])."""
83
+ o0 = gl.arange(0, MB, layout=gl.SliceLayout(1, gl.SliceLayout(2, gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(5, gl.SliceLayout(6, L)))))))
84
+ o1 = gl.arange(0, 2, layout=gl.SliceLayout(0, gl.SliceLayout(2, gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(5, gl.SliceLayout(6, L)))))))
85
+ o2 = gl.arange(0, 8, layout=gl.SliceLayout(0, gl.SliceLayout(1, gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(5, gl.SliceLayout(6, L)))))))
86
+ o3 = gl.arange(0, NB, layout=gl.SliceLayout(0, gl.SliceLayout(1, gl.SliceLayout(2, gl.SliceLayout(4, gl.SliceLayout(5, gl.SliceLayout(6, L)))))))
87
+ o4 = gl.arange(0, 2, layout=gl.SliceLayout(0, gl.SliceLayout(1, gl.SliceLayout(2, gl.SliceLayout(3, gl.SliceLayout(5, gl.SliceLayout(6, L)))))))
88
+ o5 = gl.arange(0, 2, layout=gl.SliceLayout(0, gl.SliceLayout(1, gl.SliceLayout(2, gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(6, L)))))))
89
+ o6 = gl.arange(0, 4, layout=gl.SliceLayout(0, gl.SliceLayout(1, gl.SliceLayout(2, gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(5, L)))))))
90
+ rows = o0[:, None, None, None, None, None, None] * 16 + o1[None, :, None, None, None, None, None] * 8 \
91
+ + o2[None, None, :, None, None, None, None]
92
+ cols = o3[None, None, None, :, None, None, None] * 16 + o4[None, None, None, None, :, None, None] * 8 \
93
+ + o5[None, None, None, None, None, :, None] * 4 + o6[None, None, None, None, None, None, :]
94
+ return rows, cols
95
+
96
+
97
+ @gluon.jit
98
+ def row_layout_rows(L: gl.constexpr, MB: gl.constexpr):
99
+ """Row index [MB, 2, 8] in the layout of a row statistic of L (L with its four column dims reduced)."""
100
+ RS: gl.constexpr = gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(5, gl.SliceLayout(6, L))))
101
+ r0 = gl.arange(0, MB, layout=gl.SliceLayout(1, gl.SliceLayout(2, RS)))
102
+ r1 = gl.arange(0, 2, layout=gl.SliceLayout(0, gl.SliceLayout(2, RS)))
103
+ r2 = gl.arange(0, 8, layout=gl.SliceLayout(0, gl.SliceLayout(1, RS)))
104
+ return r0[:, None, None] * 16 + r1[None, :, None] * 8 + r2[None, None, :]
105
+
106
+
107
+ @gluon.jit
108
+ def row_max(x):
109
+ return gl.max(gl.max(gl.max(gl.max(x, axis=6), axis=5), axis=4), axis=3)
110
+
111
+
112
+ @gluon.jit
113
+ def row_sum(x):
114
+ return gl.sum(gl.sum(gl.sum(gl.sum(x, axis=6), axis=5), axis=4), axis=3)
115
+
116
+
117
+ @gluon.jit
118
+ def bcast_rows(r, L: gl.constexpr):
119
+ """A [MB, 2, 8] row statistic -> broadcastable over accumulator L (any NB; the row bits are shared)."""
120
+ RL: gl.constexpr = gl.SliceLayout(3, gl.SliceLayout(4, gl.SliceLayout(5, gl.SliceLayout(6, L))))
121
+ r = gl.convert_layout(r, RL, assert_trivial=True)
122
+ return gl.expand_dims(gl.expand_dims(gl.expand_dims(gl.expand_dims(r, 3), 4), 5), 6)
123
+
124
+
125
+ @gluon.jit
126
+ def stage_k_inner(smem, tile, R: gl.constexpr, KK: gl.constexpr):
127
+ """tile [R, KK] whose k runs along its columns -> smem [(KK/4) R, 4] laid out [k-step, R, 4]."""
128
+ smem.store(gl.reshape(gl.permute(gl.reshape(tile, [R, KK // 4, 4]), [1, 0, 2]), [(KK // 4) * R, 4]))
129
+
130
+
131
+ @gluon.jit
132
+ def stage_k_outer(smem, tile, KK: gl.constexpr, C: gl.constexpr):
133
+ """tile [KK, C] whose k runs along its rows -> smem [(KK/4) C, 4] laid out [k-step, C, 4]. Conflict-free
134
+ stores want each thread to hold 4 consecutive k of a column (a [4, x] size_per_thread load layout)."""
135
+ smem.store(gl.reshape(gl.permute(gl.reshape(tile, [KK // 4, 4, C]), [0, 2, 1]), [(KK // 4) * C, 4]))
136
+
137
+
138
+ @gluon.jit
139
+ def mma_k4(sa, a_row0, sb, b_row0, acc, MB: gl.constexpr, NB: gl.constexpr,
140
+ LA: gl.constexpr, LB: gl.constexpr, L: gl.constexpr):
141
+ """acc += A[:, 4j:4j+4] @ B[4j:4j+4, :] for the k-step whose rows start at a_row0 / b_row0 of the staged
142
+ operands (16 MB rows of sa, 16 NB rows of sb)."""
143
+ fa = sa.slice(a_row0, 16 * MB).load(LA) # (mb, mi3, mi2, ni1, mi0 | mi1, ni0)
144
+ fa = gl.reshape(fa, [MB, 2, 2, 2, 2, 2, 2])
145
+ fa = gl.convert_layout(gl.reshape(gl.permute(fa, [0, 1, 2, 5, 4, 3, 6]), [MB, 2, 8, 1, 1, 1, 4]), L,
146
+ assert_trivial=True)
147
+ fb = sb.slice(b_row0, 16 * NB).load(LB) # (nb, ni3, mi2, ni1, mi0 | mi1, ni0)
148
+ fb = gl.reshape(fb, [NB, 2, 2, 2, 2, 2, 2])
149
+ fb = gl.convert_layout(gl.reshape(gl.permute(fb, [2, 5, 4, 0, 1, 3, 6]), [1, 1, 8, NB, 2, 1, 4]), L,
150
+ assert_trivial=True)
151
+ return gl.inline_asm_elementwise(MMA_ASM, MMA_CONSTRAINTS, [fa, fb, acc], dtype=gl.float32, is_pure=True,
152
+ pack=8)