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,64 @@
1
+ """Trace — pure @triton.jit kernel.
2
+
3
+ Sum of diagonal elements of a 2D matrix.
4
+ Single program iterates over the diagonal in blocks, accumulating in
5
+ float32 (or int64 for integer types) for numerical stability.
6
+
7
+ Extracted from FlagGems (Apache 2.0).
8
+
9
+ Grid: (1,)
10
+ """
11
+
12
+ import triton
13
+ import triton.language as tl
14
+
15
+
16
+ @triton.jit
17
+ def trace_kernel(
18
+ inp_ptr,
19
+ out_ptr,
20
+ num_diag,
21
+ stride0,
22
+ stride1,
23
+ BLOCK_SIZE: tl.constexpr,
24
+ ):
25
+ """Sum diagonal elements of a 2D matrix.
26
+
27
+ Iterates over the diagonal in blocks of BLOCK_SIZE, accumulating
28
+ partial sums. The diagonal stride is stride0 + stride1 (step to
29
+ move from (i,i) to (i+1,i+1)).
30
+
31
+ Args:
32
+ inp_ptr: input 2D matrix pointer
33
+ out_ptr: scalar output pointer
34
+ num_diag: min(M, N) — number of diagonal elements
35
+ stride0: row stride of input
36
+ stride1: column stride of input
37
+ """
38
+ # Select accumulation dtype based on input type
39
+ inp_dtype = inp_ptr.type.element_ty
40
+ if inp_dtype.is_int():
41
+ acc_dtype = tl.int64
42
+ other_val = 0
43
+ elif inp_dtype == tl.float64:
44
+ acc_dtype = tl.float64
45
+ other_val = 0.0
46
+ else:
47
+ acc_dtype = tl.float32
48
+ other_val = 0.0
49
+
50
+ acc = tl.zeros((BLOCK_SIZE,), dtype=acc_dtype)
51
+
52
+ diag_stride = stride0 + stride1
53
+
54
+ for i in range(0, tl.cdiv(num_diag, BLOCK_SIZE)):
55
+ block_start = i * BLOCK_SIZE
56
+ current_indices = block_start + tl.arange(0, BLOCK_SIZE)
57
+ mask = current_indices < num_diag
58
+
59
+ ptr_offsets = current_indices * diag_stride
60
+ vals = tl.load(inp_ptr + ptr_offsets, mask=mask, other=other_val)
61
+ acc += vals.to(acc_dtype)
62
+
63
+ final_sum = tl.sum(acc, axis=0)
64
+ tl.store(out_ptr, final_sum.to(out_ptr.type.element_ty))
nbxtensor/ops/tril.py ADDED
@@ -0,0 +1,64 @@
1
+ """Lower triangular — pure @triton.jit kernels. Adapted from FlagGems triu.
2
+
3
+ tril_kernel: 2D version, iterates over N blocks per row.
4
+ tril_batch_kernel: batched version, handles N-D tensors flattened to (batch, M*N).
5
+
6
+ The only difference from triu: condition is >= (keep below diagonal) vs <= (keep above).
7
+ """
8
+
9
+ import triton
10
+ import triton.language as tl
11
+
12
+
13
+ @triton.jit(do_not_specialize=["diagonal"])
14
+ def tril_kernel(
15
+ X,
16
+ Y,
17
+ M,
18
+ N,
19
+ diagonal,
20
+ M_BLOCK_SIZE: tl.constexpr,
21
+ N_BLOCK_SIZE: tl.constexpr,
22
+ ):
23
+ pid = tl.program_id(0).to(tl.int64)
24
+ row = pid * M_BLOCK_SIZE + tl.arange(0, M_BLOCK_SIZE)[:, None]
25
+ m_mask = row < M
26
+ X += row * N
27
+ Y += row * N
28
+
29
+ for n_offset in range(0, N, N_BLOCK_SIZE):
30
+ cols = n_offset + tl.arange(0, N_BLOCK_SIZE)[None, :]
31
+ n_mask = cols < N
32
+ mask = m_mask & n_mask
33
+
34
+ x = tl.load(X + cols, mask, other=0.0)
35
+ y = tl.where(row + diagonal >= cols, x, 0.0)
36
+ tl.store(Y + cols, y, mask=mask)
37
+
38
+
39
+ @triton.jit(do_not_specialize=["diagonal"])
40
+ def tril_batch_kernel(
41
+ X,
42
+ Y,
43
+ batch,
44
+ MN,
45
+ N,
46
+ diagonal,
47
+ BATCH_BLOCK_SIZE: tl.constexpr,
48
+ MN_BLOCK_SIZE: tl.constexpr,
49
+ ):
50
+ batch_id = tl.program_id(0).to(tl.int64)
51
+ mn_id = tl.program_id(1).to(tl.int64)
52
+ row = batch_id * BATCH_BLOCK_SIZE + tl.arange(0, BATCH_BLOCK_SIZE)[:, None]
53
+ batch_mask = row < batch
54
+ X += row * MN
55
+ Y += row * MN
56
+
57
+ cols = mn_id * MN_BLOCK_SIZE + tl.arange(0, MN_BLOCK_SIZE)[None, :]
58
+ mn_mask = cols < MN
59
+ mask = batch_mask & mn_mask
60
+ x = tl.load(X + cols, mask, other=0.0)
61
+ m = cols // N
62
+ n = cols % N
63
+ y = tl.where(m + diagonal >= n, x, 0.0)
64
+ tl.store(Y + cols, y, mask=mask)
nbxtensor/ops/triu.py ADDED
@@ -0,0 +1,62 @@
1
+ """Upper triangular — pure @triton.jit kernels. Extracted from FlagGems.
2
+
3
+ triu_kernel: 2D version, iterates over N blocks per row.
4
+ triu_batch_kernel: batched version, handles N-D tensors flattened to (batch, M*N).
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+
10
+
11
+ @triton.jit(do_not_specialize=["diagonal"])
12
+ def triu_kernel(
13
+ X,
14
+ Y,
15
+ M,
16
+ N,
17
+ diagonal,
18
+ M_BLOCK_SIZE: tl.constexpr,
19
+ N_BLOCK_SIZE: tl.constexpr,
20
+ ):
21
+ pid = tl.program_id(0).to(tl.int64)
22
+ row = pid * M_BLOCK_SIZE + tl.arange(0, M_BLOCK_SIZE)[:, None]
23
+ m_mask = row < M
24
+ X += row * N
25
+ Y += row * N
26
+
27
+ for n_offset in range(0, N, N_BLOCK_SIZE):
28
+ cols = n_offset + tl.arange(0, N_BLOCK_SIZE)[None, :]
29
+ n_mask = cols < N
30
+ mask = m_mask & n_mask
31
+
32
+ x = tl.load(X + cols, mask, other=0.0)
33
+ y = tl.where(row + diagonal <= cols, x, 0.0)
34
+ tl.store(Y + cols, y, mask=mask)
35
+
36
+
37
+ @triton.jit(do_not_specialize=["diagonal"])
38
+ def triu_batch_kernel(
39
+ X,
40
+ Y,
41
+ batch,
42
+ MN,
43
+ N,
44
+ diagonal,
45
+ BATCH_BLOCK_SIZE: tl.constexpr,
46
+ MN_BLOCK_SIZE: tl.constexpr,
47
+ ):
48
+ batch_id = tl.program_id(0).to(tl.int64)
49
+ mn_id = tl.program_id(1).to(tl.int64)
50
+ row = batch_id * BATCH_BLOCK_SIZE + tl.arange(0, BATCH_BLOCK_SIZE)[:, None]
51
+ batch_mask = row < batch
52
+ X += row * MN
53
+ Y += row * MN
54
+
55
+ cols = mn_id * MN_BLOCK_SIZE + tl.arange(0, MN_BLOCK_SIZE)[None, :]
56
+ mn_mask = cols < MN
57
+ mask = batch_mask & mn_mask
58
+ x = tl.load(X + cols, mask, other=0.0)
59
+ m = cols // N
60
+ n = cols % N
61
+ y = tl.where(m + diagonal <= n, x, 0.0)
62
+ tl.store(Y + cols, y, mask=mask)
@@ -0,0 +1,37 @@
1
+ """unfold_backward (overlap-add) — pure @triton.jit kernel.
2
+
3
+ aten::unfold_backward is the gradient of `Tensor.unfold`: it scatter-adds the
4
+ unfolded frames back into the original signal, so overlapping positions are
5
+ summed. This is exactly the iSTFT overlap-add (frames [.., N_frames, size] with
6
+ hop `step` → signal [.., L]).
7
+
8
+ For output position i: out[i] = Σ_{f} grad[f, j] where j = i - f*step and
9
+ 0 <= j < size. The covering frames are f = i//step - fo for a small fo range
10
+ (~size/step frames overlap a given position).
11
+ """
12
+
13
+ import triton
14
+ import triton.language as tl
15
+
16
+
17
+ @triton.jit
18
+ def unfold_backward_1d_kernel(
19
+ grad_ptr, # (B, N_frames, size) contiguous
20
+ out_ptr, # (B, L) contiguous
21
+ N_frames, size, step, L,
22
+ MAX_OVERLAP: tl.constexpr,
23
+ BLOCK_SIZE: tl.constexpr,
24
+ ):
25
+ pid_b = tl.program_id(0).to(tl.int64)
26
+ pid_l = tl.program_id(1).to(tl.int64)
27
+ offs = pid_l.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id (register 58)
28
+ mask = offs < L
29
+ acc = tl.zeros((BLOCK_SIZE,), dtype=tl.float32)
30
+ base = pid_b * (N_frames * size)
31
+ for fo in range(MAX_OVERLAP):
32
+ f = (offs // step) - fo
33
+ j = offs - f * step
34
+ valid = (f >= 0) & (f < N_frames) & (j >= 0) & (j < size) & mask
35
+ val = tl.load(grad_ptr + base + f * size + j, mask=valid, other=0.0)
36
+ acc += tl.where(valid, val, 0.0)
37
+ tl.store(out_ptr + pid_b * L + offs, acc, mask=mask)
@@ -0,0 +1,97 @@
1
+ """Unique — pure @triton.jit kernels.
2
+
3
+ NOTE: The full unique implementation (FlagGems) requires a multi-phase
4
+ pipeline (sort -> local-ne -> cumsum -> scatter -> fan-out) orchestrated
5
+ by Python wrapper code that allocates intermediate buffers and chains
6
+ multiple kernel launches. The core algorithmic kernels are extracted below.
7
+
8
+ These kernels assume the input is PRE-SORTED. The Python wrapper must:
9
+ 1. Sort the input: sorted_data, sorted_indices = sort(input.ravel())
10
+ 2. Launch simple_unique_flat_kernel (for small inputs) or the
11
+ local_ne -> global_cumsum pipeline (for large inputs)
12
+ 3. Slice the output to [:unique_size]
13
+
14
+ Extracted from FlagGems (Apache 2.0).
15
+ """
16
+
17
+ import triton
18
+ import triton.language as tl
19
+
20
+
21
+ @triton.jit
22
+ def simple_unique_flat_kernel(
23
+ sorted_data_ptr,
24
+ sorted_indices_ptr,
25
+ data_out_ptr,
26
+ inverse_indices_ptr,
27
+ idx_ptr,
28
+ unique_size_ptr,
29
+ return_inverse: tl.constexpr,
30
+ return_counts: tl.constexpr,
31
+ num_tasks,
32
+ tile_size: tl.constexpr,
33
+ ):
34
+ """Single-block unique on pre-sorted data (for small inputs <= 8192).
35
+
36
+ Compares each element with its predecessor to detect boundaries,
37
+ uses cumsum for compacted output indices, then scatters unique values.
38
+
39
+ Grid: (1,)
40
+ """
41
+ i0 = tl.arange(0, tile_size)
42
+ mask = i0 < num_tasks
43
+
44
+ # Load current and previous elements
45
+ a = tl.load(sorted_data_ptr + i0, mask=mask)
46
+ i0_prev = tl.where(i0 > 0, i0 - 1, 0)
47
+ b = tl.load(sorted_data_ptr + i0_prev, mask=mask)
48
+
49
+ # Detect unique boundaries: ne(a, prev(a)), first element always unique
50
+ ne_result = tl.where(i0 > 0, a != b, 0)
51
+ cumsum = tl.cumsum(ne_result)
52
+
53
+ # Write unique_size (last element's cumsum = num_unique - 1)
54
+ unique_size_mask = i0 == tile_size - 1
55
+ tl.store(unique_size_ptr + tl.zeros_like(i0), cumsum, mask=unique_size_mask)
56
+
57
+ # Scatter unique values to compacted output
58
+ tl.store(data_out_ptr + cumsum, a, mask=mask)
59
+
60
+ # Scatter inverse indices: original position -> compacted index
61
+ if return_inverse:
62
+ sorted_indices = tl.load(sorted_indices_ptr + i0, mask=mask)
63
+ tl.store(inverse_indices_ptr + sorted_indices, cumsum, mask=mask)
64
+
65
+ # Record boundary positions for count computation
66
+ if return_counts:
67
+ idx_mask = ((i0 == 0) | ne_result.to(tl.int1)) & mask
68
+ tl.store(idx_ptr + cumsum, i0, mask=idx_mask)
69
+
70
+
71
+ @triton.jit
72
+ def output_counts_kernel(
73
+ idx_ptr,
74
+ origin_num_tasks,
75
+ counts_ptr,
76
+ num_tasks,
77
+ tile_size: tl.constexpr,
78
+ ):
79
+ """Compute counts from boundary indices.
80
+
81
+ counts[i] = idx[i+1] - idx[i], with the last count going to the end.
82
+
83
+ Grid: (ceil(num_unique / tile_size),)
84
+ """
85
+ pid = tl.program_id(0).to(tl.int64)
86
+ r = tl.arange(0, tile_size)
87
+ i0 = pid * tile_size + r
88
+ mask = i0 < num_tasks
89
+
90
+ idx = tl.load(idx_ptr + i0, mask=mask)
91
+
92
+ i0_next = i0 + 1
93
+ next_mask = i0_next < num_tasks
94
+ idx_next = tl.load(idx_ptr + i0_next, mask=next_mask)
95
+
96
+ counts = tl.where(i0_next < num_tasks, idx_next - idx, origin_num_tasks - idx)
97
+ tl.store(counts_ptr + i0, counts, mask=mask)
@@ -0,0 +1,106 @@
1
+ """Bilinear 2D upsampling — pure @triton.jit kernel.
2
+
3
+ For each output pixel (n, c, oh, ow), compute source coordinates in
4
+ input space, find the 4 nearest input pixels, and bilinearly interpolate.
5
+
6
+ Supports align_corners=True (maps corner-to-corner) and align_corners=False
7
+ (maps center-to-center with half-pixel offset).
8
+ """
9
+
10
+ import triton
11
+ import triton.language as tl
12
+
13
+
14
+ @triton.jit
15
+ def upsample_bilinear2d_kernel(
16
+ input_ptr,
17
+ output_ptr,
18
+ N, C,
19
+ IH, IW,
20
+ OH, OW,
21
+ # Precomputed scale factors: how input coords map to output coords
22
+ # For align_corners=False: scale_h = IH / OH, scale_w = IW / OW
23
+ # For align_corners=True: scale_h = (IH-1)/(OH-1), scale_w = (IW-1)/(OW-1)
24
+ scale_h,
25
+ scale_w,
26
+ # 0.0 for align_corners=True, 0.5 for align_corners=False
27
+ offset,
28
+ BLOCK_X: tl.constexpr,
29
+ BLOCK_Y: tl.constexpr,
30
+ ):
31
+ """Bilinear interpolation upsampling.
32
+
33
+ Grid: (cdiv(OW, BLOCK_X), cdiv(OH, BLOCK_Y), N*C)
34
+ Each program handles a BLOCK_Y x BLOCK_X tile of output pixels for one (n, c).
35
+ """
36
+ pid_x = tl.program_id(0).to(tl.int64)
37
+ pid_y = tl.program_id(1).to(tl.int64)
38
+ pid_nc = tl.program_id(2).to(tl.int64)
39
+
40
+ ow = pid_x * BLOCK_X + tl.arange(0, BLOCK_X) # [BLOCK_X]
41
+ oh = pid_y * BLOCK_Y + tl.arange(0, BLOCK_Y) # [BLOCK_Y]
42
+
43
+ # Map output coords to input coords (floating point)
44
+ # align_corners=False: src = (dst + 0.5) * scale - 0.5
45
+ # align_corners=True: src = dst * scale
46
+ src_h = (oh.to(tl.float32) + offset) * scale_h - offset # [BLOCK_Y]
47
+ src_w = (ow.to(tl.float32) + offset) * scale_w - offset # [BLOCK_X]
48
+
49
+ # Clamp to valid range
50
+ src_h = tl.maximum(src_h, 0.0)
51
+ src_w = tl.maximum(src_w, 0.0)
52
+ # IH/IW may arrive as a Python int (Triton-specialized) or a tl scalar
53
+ # depending on the call's shape — `.to()` fails on the former, float() on the
54
+ # latter. `* 1.0` promotes to float robustly for both.
55
+ src_h = tl.minimum(src_h, (IH - 1) * 1.0)
56
+ src_w = tl.minimum(src_w, (IW - 1) * 1.0)
57
+
58
+ # Floor and ceil indices
59
+ h0 = src_h.to(tl.int32) # [BLOCK_Y]
60
+ w0 = src_w.to(tl.int32) # [BLOCK_X]
61
+ h1 = tl.minimum(h0 + 1, IH - 1) # [BLOCK_Y]
62
+ w1 = tl.minimum(w0 + 1, IW - 1) # [BLOCK_X]
63
+
64
+ # Fractional parts (bilinear weights)
65
+ fh = src_h - h0.to(tl.float32) # [BLOCK_Y]
66
+ fw = src_w - w0.to(tl.float32) # [BLOCK_X]
67
+
68
+ # Bilinear weights for 4 corners
69
+ w_h0 = 1.0 - fh # [BLOCK_Y]
70
+ w_h1 = fh # [BLOCK_Y]
71
+ w_w0 = 1.0 - fw # [BLOCK_X]
72
+ w_w1 = fw # [BLOCK_X]
73
+
74
+ # Base offset for this (n, c) plane
75
+ base = pid_nc * IH * IW
76
+
77
+ # Masks
78
+ mask_h = oh < OH # [BLOCK_Y]
79
+ mask_w = ow < OW # [BLOCK_X]
80
+ mask_2d = mask_h[:, None] & mask_w[None, :] # [BLOCK_Y, BLOCK_X]
81
+
82
+ # Load 4 corner values
83
+ # top-left: input[n, c, h0, w0]
84
+ # top-right: input[n, c, h0, w1]
85
+ # bottom-left: input[n, c, h1, w0]
86
+ # bottom-right: input[n, c, h1, w1]
87
+ off_tl = base + h0[:, None] * IW + w0[None, :]
88
+ off_tr = base + h0[:, None] * IW + w1[None, :]
89
+ off_bl = base + h1[:, None] * IW + w0[None, :]
90
+ off_br = base + h1[:, None] * IW + w1[None, :]
91
+
92
+ v_tl = tl.load(input_ptr + off_tl, mask=mask_2d, other=0.0).to(tl.float32)
93
+ v_tr = tl.load(input_ptr + off_tr, mask=mask_2d, other=0.0).to(tl.float32)
94
+ v_bl = tl.load(input_ptr + off_bl, mask=mask_2d, other=0.0).to(tl.float32)
95
+ v_br = tl.load(input_ptr + off_br, mask=mask_2d, other=0.0).to(tl.float32)
96
+
97
+ # Bilinear interpolation
98
+ # result = w_h0 * (w_w0 * v_tl + w_w1 * v_tr) + w_h1 * (w_w0 * v_bl + w_w1 * v_br)
99
+ top = w_w0[None, :] * v_tl + w_w1[None, :] * v_tr
100
+ bot = w_w0[None, :] * v_bl + w_w1[None, :] * v_br
101
+ result = w_h0[:, None] * top + w_h1[:, None] * bot
102
+
103
+ # Store output
104
+ out_base = pid_nc * OH * OW
105
+ out_off = out_base + oh[:, None] * OW + ow[None, :]
106
+ tl.store(output_ptr + out_off, result, mask=mask_2d)
@@ -0,0 +1,52 @@
1
+ """Upsample nearest 2D — pure @triton.jit kernel.
2
+
3
+ Extracted from FlagGems (FlagOpen/FlagGems) upsample_nearest2d.py.
4
+ Stripped FlagGems-specific decorators (@libentry, runtime heuristics).
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+
10
+
11
+ @triton.jit
12
+ def upsample_nearest2d_kernel(
13
+ ptr_o,
14
+ ptr_i,
15
+ N,
16
+ C,
17
+ OH,
18
+ OW,
19
+ IH,
20
+ IW,
21
+ s_n,
22
+ s_c,
23
+ s_h,
24
+ s_w,
25
+ reciprocal_scale_h,
26
+ reciprocal_scale_w,
27
+ BLOCK_SIZE: tl.constexpr,
28
+ ):
29
+ NC = N * C
30
+ nc_stride = tl.num_programs(axis=1)
31
+ nc_iter = (tl.program_id(axis=1).to(tl.int64)).to(tl.int32) # loop bounds are 32-bit counts: the Metal lowering refuses a 64-bit scf.for bound (addressing stays 64-bit through the program ids)
32
+ pid = tl.program_id(axis=0).to(tl.int64)
33
+ idx = 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)
34
+ ow = idx % OW
35
+ oh = idx // OW % OH
36
+
37
+ ih = tl.minimum((oh * reciprocal_scale_h).to(tl.int32), IH - 1)
38
+ iw = tl.minimum((ow * reciprocal_scale_w).to(tl.int32), IW - 1)
39
+
40
+ # The input is read through its strides: a first-frame branch feeds this op `x[:, :, 0]` of a
41
+ # 5-D activation, a view whose channel stride spans every frame — flat indexing read another
42
+ # channel's frames there (CogVideoX / Open-Sora frame 0). The output is fresh and contiguous.
43
+ offset_o = (nc_iter * OH + oh) * OW + ow
44
+ in_hw = ih.to(tl.int64) * s_h + iw.to(tl.int64) * s_w
45
+ dst_index_stride = nc_stride * OH * OW
46
+ while nc_iter < NC:
47
+ n = nc_iter // C
48
+ c = nc_iter % C
49
+ data = tl.load(ptr_i + n.to(tl.int64) * s_n + c.to(tl.int64) * s_c + in_hw)
50
+ tl.store(ptr_o + offset_o, data)
51
+ ptr_o += dst_index_stride
52
+ nc_iter += nc_stride
@@ -0,0 +1,61 @@
1
+ """Upsample nearest 3D — pure @triton.jit kernel.
2
+
3
+ 3D nearest neighbor upsampling: [N,C,D,H,W] -> [N,C,D*s_d,H*s_h,W*s_w].
4
+ Adapted from our upsample_nearest2d.py by adding the depth dimension.
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+
10
+
11
+ @triton.jit
12
+ def upsample_nearest3d_kernel(
13
+ ptr_o,
14
+ ptr_i,
15
+ N,
16
+ C,
17
+ OD,
18
+ OH,
19
+ OW,
20
+ ID,
21
+ IH,
22
+ IW,
23
+ reciprocal_scale_d,
24
+ reciprocal_scale_h,
25
+ reciprocal_scale_w,
26
+ BLOCK_SIZE: tl.constexpr,
27
+ ):
28
+ """Nearest-neighbor 3D upsample.
29
+
30
+ Grid: (cdiv(OD*OH*OW, BLOCK_SIZE), cdiv(N*C, 4))
31
+ Each program handles BLOCK_SIZE output pixels across one (n,c) slice,
32
+ iterating over (n,c) in strides of nc_stride.
33
+ """
34
+ NC = N * C
35
+ nc_stride = tl.num_programs(axis=1)
36
+ nc_iter = (tl.program_id(axis=1).to(tl.int64)).to(tl.int32) # loop bounds are 32-bit counts: the Metal lowering refuses a 64-bit scf.for bound (addressing stays 64-bit through the program ids)
37
+ pid = tl.program_id(axis=0).to(tl.int64)
38
+ idx = 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)
39
+
40
+ # Decompose flat index -> (od, oh, ow)
41
+ ow = idx % OW
42
+ oh = (idx // OW) % OH
43
+ od = (idx // (OW * OH)) % OD
44
+
45
+ # Map output coords to input coords (nearest neighbor)
46
+ id_ = tl.minimum((od * reciprocal_scale_d).to(tl.int32), ID - 1)
47
+ ih = tl.minimum((oh * reciprocal_scale_h).to(tl.int32), IH - 1)
48
+ iw = tl.minimum((ow * reciprocal_scale_w).to(tl.int32), IW - 1)
49
+
50
+ # Compute offsets for contiguous [N, C, D, H, W] layout
51
+ offset_o = ((nc_iter * OD + od) * OH + oh) * OW + ow
52
+ offset_i = ((nc_iter * ID + id_) * IH + ih) * IW + iw
53
+ src_index_stride = nc_stride * ID * IH * IW
54
+ dst_index_stride = nc_stride * OD * OH * OW
55
+
56
+ while nc_iter < NC:
57
+ data = tl.load(ptr_i + offset_i)
58
+ tl.store(ptr_o + offset_o, data)
59
+ ptr_i += src_index_stride
60
+ ptr_o += dst_index_stride
61
+ nc_iter += nc_stride
nbxtensor/ops/var.py ADDED
@@ -0,0 +1,136 @@
1
+ """Variance — pure @triton.jit kernels.
2
+
3
+ Welford online algorithm for numerically-stable variance.
4
+ Global reduction via two-pass and dim-specific Welford kernel.
5
+ Extracted from FlagGems var_mean (Apache-2.0).
6
+ """
7
+
8
+ import triton
9
+ import triton.language as tl
10
+
11
+
12
+ # ---------------------------------------------------------------------------
13
+ # Welford combine function (used by tl.reduce)
14
+ # ---------------------------------------------------------------------------
15
+
16
+ @triton.jit
17
+ def welford_func(mean_x, count_x, M_x, mean_y, count_y, M_y):
18
+ """Combine two Welford partial aggregates."""
19
+ count = count_x + count_y
20
+ _count = tl.maximum(count, 1)
21
+ mc_x = mean_x * count_x
22
+ mc_y = mean_y * count_y
23
+ mean = (mc_x + mc_y) / _count
24
+ M = M_x + mc_x * mean_x + M_y + mc_y * mean_y - count * mean * mean
25
+ return mean, count, M
26
+
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Global reduction: two-pass (partial stats → combine)
30
+ # ---------------------------------------------------------------------------
31
+
32
+ @triton.jit
33
+ def var_kernel_1(
34
+ X,
35
+ Acc,
36
+ Average,
37
+ Count,
38
+ N,
39
+ BLOCK_N: tl.constexpr,
40
+ ):
41
+ """Pass 1: compute partial sum, sum-of-squares, and count per block."""
42
+ pid = tl.program_id(0).to(tl.int64)
43
+ offset = pid * BLOCK_N + tl.arange(0, BLOCK_N)
44
+
45
+ X = X + offset
46
+ Acc = Acc + pid
47
+ Average = Average + pid
48
+ Count = Count + pid
49
+ mask = offset < N
50
+
51
+ x = tl.load(X, mask, other=0.0).to(tl.float32)
52
+
53
+ count = tl.sum(mask.to(tl.float32))
54
+ average = tl.sum(x) / count
55
+ acc = tl.sum(x * x) - count * average * average
56
+
57
+ tl.store(Average, average)
58
+ tl.store(Acc, acc)
59
+ tl.store(Count, count)
60
+
61
+
62
+ @triton.jit(do_not_specialize=["correction"])
63
+ def var_kernel_2(
64
+ Acc,
65
+ Average,
66
+ Count,
67
+ Var,
68
+ N,
69
+ correction,
70
+ BLOCK_NUM,
71
+ BLOCK_N: tl.constexpr,
72
+ ):
73
+ """Pass 2: Welford-combine all blocks and output variance."""
74
+ offset = tl.arange(0, BLOCK_N)
75
+ mask = offset < BLOCK_NUM
76
+ Acc = Acc + offset
77
+ Average = Average + offset
78
+ Count = Count + offset
79
+ acc = tl.load(Acc, mask, other=0.0).to(tl.float32)
80
+ average = tl.load(Average, mask, other=0.0).to(tl.float32)
81
+ count = tl.load(Count, mask, other=0.0).to(tl.float32)
82
+
83
+ _mean, _, nvar = tl.reduce(
84
+ (average, count, acc), axis=0, combine_fn=welford_func
85
+ )
86
+
87
+ var = nvar / (N - correction)
88
+ tl.store(Var, var)
89
+
90
+
91
+ # ---------------------------------------------------------------------------
92
+ # Dim-specific: Welford online variance along one axis
93
+ # ---------------------------------------------------------------------------
94
+
95
+ @triton.jit(do_not_specialize=["correction"])
96
+ def var_welford_kernel(
97
+ X,
98
+ Var,
99
+ M,
100
+ N,
101
+ correction,
102
+ BLOCK_M: tl.constexpr,
103
+ BLOCK_N: tl.constexpr,
104
+ ):
105
+ """Welford variance along compressed inner dim N.
106
+
107
+ X: [M, N] (dim-compressed) → Var: [M]
108
+ """
109
+ pid = tl.program_id(0).to(tl.int64) * BLOCK_M + tl.arange(0, BLOCK_M)[:, None]
110
+ X = X + pid * N
111
+ Var = Var + pid
112
+ row_mask = pid < M
113
+
114
+ _mean = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
115
+ _acc = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
116
+ _count = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
117
+ for off in range(0, N, BLOCK_N):
118
+ cols = off + tl.arange(0, BLOCK_N)[None, :]
119
+ col_mask = cols < N
120
+ mask = row_mask & col_mask
121
+
122
+ x = tl.load(X + cols, mask, other=0.0).to(tl.float32)
123
+
124
+ count = _count + mask
125
+ cnt = tl.maximum(count, 1)
126
+ cur_mean = (_mean * _count + x) / cnt
127
+ _acc += (x - cur_mean) * (x - _mean) * mask
128
+ _mean = cur_mean
129
+ _count = count
130
+
131
+ _mean_r, _, acc_r = tl.reduce(
132
+ (_mean, _count, _acc), axis=1, combine_fn=welford_func
133
+ )
134
+ var = acc_r / (N - correction)
135
+ var = var[:, None]
136
+ tl.store(Var, var, row_mask)