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
nbxtensor/ops/copy.py ADDED
@@ -0,0 +1,18 @@
1
+ """Copy / dtype cast — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def copy_forward_kernel(
8
+ input_ptr, output_ptr,
9
+ n_elements,
10
+ BLOCK_SIZE: tl.constexpr,
11
+ ):
12
+ """Copy tensor (with implicit dtype conversion via pointer types)."""
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
+ tl.store(output_ptr + offset, x, mask=mask)
@@ -0,0 +1,39 @@
1
+ """Copy — pure @triton.jit kernel.
2
+
3
+ Ported from FlagGems copy (Apache-2.0 license).
4
+ Copies elements from src to dst, with optional dtype conversion
5
+ handled by Triton's automatic casting on store.
6
+ """
7
+
8
+ import triton
9
+ import triton.language as tl
10
+
11
+ @triton.jit
12
+ def copy_kernel(
13
+ src_ptr, dst_ptr,
14
+ n_elements,
15
+ BLOCK_SIZE: tl.constexpr,
16
+ SATURATE_F16: tl.constexpr = False,
17
+ ):
18
+ """Copy src to dst. Dtype conversion happens automatically via Triton's
19
+ store when src and dst pointer types differ.
20
+
21
+ SATURATE_F16: protected float16 downcast — finite values beyond the
22
+ fp16 range clamp to ±65504 instead of overflowing to ±inf. This
23
+ mirrors the compiled DtypeEngine's hardware-protected conversion
24
+ contract (bf16/fp32 sentinel fills like finfo.min must survive a
25
+ V100 fp16 remap as finite extremes; an additive attention mask that
26
+ overflows to -inf poisons softmax rows — the DeepSeek-V2 wrong-token
27
+ incident). NaN and true ±inf inputs pass through unchanged.
28
+ """
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
+ data = tl.load(src_ptr + offset, mask=mask)
34
+ if SATURATE_F16:
35
+ f = data.to(tl.float32)
36
+ is_finite = (f == f) & (f != float("inf")) & (f != float("-inf"))
37
+ clamped = tl.minimum(tl.maximum(f, -65504.0), 65504.0)
38
+ data = tl.where(is_finite, clamped, f)
39
+ tl.store(dst_ptr + offset, data, mask=mask)
nbxtensor/ops/cos.py ADDED
@@ -0,0 +1,17 @@
1
+ """Cosine — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def cos_forward_kernel(
8
+ input_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(input_ptr + offset, mask=mask)
17
+ tl.store(output_ptr + offset, tl.cos(x.to(tl.float32)), mask=mask)
@@ -0,0 +1,64 @@
1
+ """Count Nonzero — pure @triton.jit kernel.
2
+
3
+ Counts non-zero elements in a flattened tensor using atomic addition.
4
+ Each block counts its local non-zeros, then atomically adds to the output.
5
+ Extracted from FlagGems (Apache 2.0).
6
+
7
+ Grid: (ceil(numel / BLOCK_SIZE),)
8
+ """
9
+
10
+ import triton
11
+ import triton.language as tl
12
+
13
+ @triton.jit
14
+ def count_nonzero_kernel(
15
+ x_ptr,
16
+ out_ptr,
17
+ numel,
18
+ BLOCK_SIZE: tl.constexpr,
19
+ ):
20
+ """Count non-zero elements via block-local sum + atomic global add.
21
+
22
+ Each program loads a block of elements, compares != 0, sums the
23
+ boolean result, then atomically adds the count to the output scalar.
24
+ """
25
+ pid = tl.program_id(0).to(tl.int64)
26
+ block_start = pid * BLOCK_SIZE
27
+ offsets = block_start + tl.arange(0, BLOCK_SIZE)
28
+ mask = offsets < numel
29
+
30
+ x = tl.load(x_ptr + offsets, mask=mask, other=0)
31
+ is_nonzero = (x != 0).to(tl.int64)
32
+ nonzero_count = tl.sum(is_nonzero, axis=0)
33
+
34
+ tl.atomic_add(out_ptr, nonzero_count)
35
+
36
+ @triton.jit
37
+ def count_nonzero_dim_kernel(
38
+ x_ptr,
39
+ out_ptr,
40
+ N,
41
+ numel,
42
+ BLOCK_SIZE: tl.constexpr,
43
+ ):
44
+ """Count non-zero elements along a dimension (after dim_compress).
45
+
46
+ Each program handles one row of the compressed tensor and iterates
47
+ over columns in blocks, accumulating the non-zero count.
48
+
49
+ x_ptr: flattened compressed input (M * N elements, reduction dim = N)
50
+ out_ptr: output of shape (M,)
51
+ """
52
+ pid_x = tl.program_id(0).to(tl.int64)
53
+
54
+ nonzero_count = tl.zeros((), dtype=tl.int64)
55
+ for start_n in range(0, N, BLOCK_SIZE):
56
+ cols_offsets = start_n + tl.arange(0, BLOCK_SIZE)
57
+ offset = pid_x * N + cols_offsets
58
+ col_mask = (offset < numel) & (cols_offsets < N)
59
+
60
+ x = tl.load(x_ptr + offset, mask=col_mask, other=0)
61
+ is_nonzero = (x != 0).to(tl.int64)
62
+ nonzero_count += tl.sum(is_nonzero)
63
+
64
+ tl.store(out_ptr + pid_x, nonzero_count)
@@ -0,0 +1,67 @@
1
+ """Cross entropy loss — pure @triton.jit kernel.
2
+
3
+ Extracted from attorch (BobMcDear/attorch) cross_entropy_loss_kernels.py.
4
+ Chosen over Liger (523 lines) for inference: simpler, pure, no training extras.
5
+ Forward only. Numerically stable log-sum-exp implementation.
6
+ """
7
+
8
+ import triton
9
+ import triton.language as tl
10
+ from triton import next_power_of_2
11
+
12
+ @triton.heuristics({
13
+ 'BLOCK_SIZE_FEAT': lambda args: next_power_of_2(args['feat_dim']),
14
+ })
15
+ @triton.jit
16
+ def cross_entropy_loss_forward_kernel(
17
+ input_pointer, target_pointer, weight_pointer,
18
+ sum_weights_pointer, output_pointer,
19
+ batch_dim, feat_dim,
20
+ input_batch_stride, input_feat_stride,
21
+ weighted: tl.constexpr,
22
+ BLOCK_SIZE_BATCH: tl.constexpr,
23
+ BLOCK_SIZE_FEAT: tl.constexpr,
24
+ ):
25
+ """Cross entropy loss: -log(softmax(input)[target]).
26
+
27
+ Numerically stable via log-sum-exp trick.
28
+
29
+ Args:
30
+ input_pointer: [batch_dim, feat_dim] logits
31
+ target_pointer: [batch_dim] integer class indices
32
+ weight_pointer: optional [feat_dim] class weights
33
+ output_pointer: [batch_dim/BLOCK_SIZE_BATCH] partial losses
34
+ """
35
+ batch_pid = tl.program_id(axis=0).to(tl.int64)
36
+
37
+ batch_offset = batch_pid * BLOCK_SIZE_BATCH + tl.arange(0, BLOCK_SIZE_BATCH)
38
+ feat_offset = tl.arange(0, BLOCK_SIZE_FEAT)
39
+
40
+ batch_mask = batch_offset < batch_dim
41
+ feat_mask = feat_offset < feat_dim
42
+
43
+ target = tl.load(target_pointer + batch_offset, mask=batch_mask)
44
+
45
+ pred_pointer = (input_pointer +
46
+ input_feat_stride * target +
47
+ input_batch_stride * batch_offset)
48
+ input_pointer += (input_batch_stride * batch_offset[:, None] +
49
+ input_feat_stride * feat_offset[None, :])
50
+
51
+ input = tl.load(input_pointer, mask=batch_mask[:, None] & feat_mask[None, :],
52
+ other=-float('inf')).to(tl.float32)
53
+ pred = tl.load(pred_pointer, mask=batch_mask).to(tl.float32)
54
+
55
+ # Log-sum-exp: loss = log(sum(exp(x - max))) + max - pred
56
+ mx = tl.max(input, axis=1)
57
+ input -= mx[:, None]
58
+ loss = tl.log(tl.sum(tl.exp(input), axis=1)) - pred + mx
59
+
60
+ if weighted:
61
+ weight = tl.load(weight_pointer + target, mask=batch_mask).to(tl.float32)
62
+ loss *= weight
63
+ tl.store(sum_weights_pointer + batch_pid, tl.sum(weight))
64
+ else:
65
+ loss /= batch_dim
66
+
67
+ tl.store(output_pointer + batch_pid, tl.sum(loss))
@@ -0,0 +1,109 @@
1
+ """Cumulative Maximum — pure @triton.jit kernels.
2
+
3
+ Computes running maximum along a dimension, returning both values and indices.
4
+ Uses scan-then-fan algorithm: each block computes a local cummax via
5
+ tl.associative_scan, then partial results are combined across blocks.
6
+
7
+ Extracted from FlagGems (Apache 2.0).
8
+
9
+ Three kernels for the scan-then-fan pipeline:
10
+ 1. scan_part_max_kernel — local cummax within each block + partial max
11
+ 2. add_base_max_kernel — fan-out: combine partial maxima with local results
12
+ 3. cummax_loop_kernel — single-program loop variant for wide reductions
13
+ """
14
+
15
+ import triton
16
+ import triton.language as tl
17
+
18
+
19
+ @triton.jit
20
+ def _cummax_combine(val_a, idx_a, val_b, idx_b):
21
+ """Associative combiner: keep (value, index) of the maximum."""
22
+ pick_b = val_b > val_a
23
+ # Tie-break right: if equal, keep the later (right) index
24
+ pick_b = pick_b | ((val_a == val_b) & (idx_b >= idx_a))
25
+ val_out = tl.where(pick_b, val_b, val_a)
26
+ idx_out = tl.where(pick_b, idx_b, idx_a)
27
+ return val_out, idx_out
28
+
29
+
30
+ @triton.jit
31
+ def scan_part_max_kernel(
32
+ inp,
33
+ out,
34
+ out_indices,
35
+ partial_max,
36
+ partial_max_indices,
37
+ n_elements,
38
+ BLOCK_SIZE: tl.constexpr,
39
+ NEED_PARTIAL: tl.constexpr,
40
+ ):
41
+ """Block-local cumulative maximum with optional partial output.
42
+
43
+ Each block loads BLOCK_SIZE elements, computes cummax via associative
44
+ scan, stores results, and optionally writes the block-maximum for
45
+ the fan-out phase.
46
+ """
47
+ pid = tl.program_id(0).to(tl.int64)
48
+ 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)
49
+ mask = offset < n_elements
50
+
51
+ # Load input, use -inf for masked positions
52
+ inp_vals = tl.load(inp + offset, mask=mask, other=float('-inf'))
53
+ inp_vals = inp_vals.to(tl.float32)
54
+ indices = offset
55
+
56
+ # Associative scan for cummax
57
+ result, cummax_idx = tl.associative_scan(
58
+ (inp_vals, indices), 0, _cummax_combine
59
+ )
60
+
61
+ tl.store(out + offset, result, mask=mask)
62
+ tl.store(out_indices + offset, cummax_idx, mask=mask)
63
+
64
+ if tl.constexpr(NEED_PARTIAL):
65
+ # Reduce to find block maximum (tie-break right)
66
+ block_max = tl.max(inp_vals, axis=0)
67
+ # Find rightmost index with block_max value
68
+ is_max = inp_vals == block_max
69
+ max_idx = tl.max(tl.where(is_max, indices, -1), axis=0)
70
+ # Only one thread writes the partial
71
+ if tl.arange(0, BLOCK_SIZE)[0] == 0:
72
+ tl.store(partial_max + pid, block_max)
73
+ tl.store(partial_max_indices + pid, max_idx)
74
+
75
+
76
+ @triton.jit
77
+ def add_base_max_kernel(
78
+ out,
79
+ out_indices,
80
+ partial_max,
81
+ partial_max_indices,
82
+ n_elements,
83
+ BLOCK_SIZE: tl.constexpr,
84
+ ):
85
+ """Fan-out phase: combine partial maxima from prior blocks.
86
+
87
+ For each block (except the first), loads the cumulative partial max
88
+ from the previous block and merges with local results.
89
+ """
90
+ pid = tl.program_id(0).to(tl.int64)
91
+ 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)
92
+ mask = offset < n_elements
93
+
94
+ out_vals = tl.load(out + offset, mask=mask)
95
+ out_idx = tl.load(out_indices + offset, mask=mask)
96
+
97
+ if pid > 0:
98
+ prev_max = tl.load(partial_max + pid - 1)
99
+ prev_idx = tl.load(partial_max_indices + pid - 1)
100
+
101
+ # Merge: if previous partial max >= local, use previous
102
+ use_prev = (prev_max > out_vals) | (
103
+ (prev_max == out_vals) & (prev_idx >= out_idx)
104
+ )
105
+ final_vals = tl.where(use_prev, prev_max, out_vals)
106
+ final_idx = tl.where(use_prev, prev_idx, out_idx)
107
+
108
+ tl.store(out + offset, final_vals, mask=mask)
109
+ tl.store(out_indices + offset, final_idx, mask=mask)
@@ -0,0 +1,105 @@
1
+ """Cumulative Minimum — pure @triton.jit kernels.
2
+
3
+ Computes running minimum along a dimension, returning both values and indices.
4
+ Uses scan-then-fan algorithm (mirror of cummax with minimum).
5
+
6
+ Extracted from FlagGems (Apache 2.0).
7
+
8
+ Three kernels:
9
+ 1. scan_part_min_kernel — local cummin within each block + partial min
10
+ 2. add_base_min_kernel — fan-out: combine partial minima with local results
11
+ """
12
+
13
+ import triton
14
+ import triton.language as tl
15
+
16
+
17
+ @triton.jit
18
+ def _cummin_combine(val_a, idx_a, val_b, idx_b):
19
+ """Associative combiner: keep (value, index) of the minimum."""
20
+ pick_b = val_b < val_a
21
+ # Tie-break right: if equal, keep the later (right) index
22
+ pick_b = pick_b | ((val_a == val_b) & (idx_b >= idx_a))
23
+ val_out = tl.where(pick_b, val_b, val_a)
24
+ idx_out = tl.where(pick_b, idx_b, idx_a)
25
+ return val_out, idx_out
26
+
27
+
28
+ @triton.jit
29
+ def scan_part_min_kernel(
30
+ inp,
31
+ out,
32
+ out_indices,
33
+ partial_min,
34
+ partial_min_indices,
35
+ n_elements,
36
+ BLOCK_SIZE: tl.constexpr,
37
+ NEED_PARTIAL: tl.constexpr,
38
+ ):
39
+ """Block-local cumulative minimum with optional partial output.
40
+
41
+ Each block loads BLOCK_SIZE elements, computes cummin via associative
42
+ scan, stores results, and optionally writes the block-minimum for
43
+ the fan-out phase.
44
+ """
45
+ pid = tl.program_id(0).to(tl.int64)
46
+ 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)
47
+ mask = offset < n_elements
48
+
49
+ # Load input, use +inf for masked positions
50
+ inp_vals = tl.load(inp + offset, mask=mask, other=float('inf'))
51
+ inp_vals = inp_vals.to(tl.float32)
52
+ indices = offset
53
+
54
+ # Associative scan for cummin
55
+ result, cummin_idx = tl.associative_scan(
56
+ (inp_vals, indices), 0, _cummin_combine
57
+ )
58
+
59
+ tl.store(out + offset, result, mask=mask)
60
+ tl.store(out_indices + offset, cummin_idx, mask=mask)
61
+
62
+ if tl.constexpr(NEED_PARTIAL):
63
+ # Reduce to find block minimum (tie-break right)
64
+ block_min = tl.min(inp_vals, axis=0)
65
+ is_min = inp_vals == block_min
66
+ min_idx = tl.max(tl.where(is_min, indices, -1), axis=0)
67
+ if tl.arange(0, BLOCK_SIZE)[0] == 0:
68
+ tl.store(partial_min + pid, block_min)
69
+ tl.store(partial_min_indices + pid, min_idx)
70
+
71
+
72
+ @triton.jit
73
+ def add_base_min_kernel(
74
+ out,
75
+ out_indices,
76
+ partial_min,
77
+ partial_min_indices,
78
+ n_elements,
79
+ BLOCK_SIZE: tl.constexpr,
80
+ ):
81
+ """Fan-out phase: combine partial minima from prior blocks.
82
+
83
+ For each block (except the first), loads the cumulative partial min
84
+ from the previous block and merges with local results.
85
+ """
86
+ pid = tl.program_id(0).to(tl.int64)
87
+ 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)
88
+ mask = offset < n_elements
89
+
90
+ out_vals = tl.load(out + offset, mask=mask)
91
+ out_idx = tl.load(out_indices + offset, mask=mask)
92
+
93
+ if pid > 0:
94
+ prev_min = tl.load(partial_min + pid - 1)
95
+ prev_idx = tl.load(partial_min_indices + pid - 1)
96
+
97
+ # Merge: if previous partial min <= local, use previous
98
+ use_prev = (prev_min < out_vals) | (
99
+ (prev_min == out_vals) & (prev_idx >= out_idx)
100
+ )
101
+ final_vals = tl.where(use_prev, prev_min, out_vals)
102
+ final_idx = tl.where(use_prev, prev_idx, out_idx)
103
+
104
+ tl.store(out + offset, final_vals, mask=mask)
105
+ tl.store(out_indices + offset, final_idx, mask=mask)
@@ -0,0 +1,244 @@
1
+ """Cumulative sum — pure @triton.jit kernels. Extracted from FlagGems.
2
+
3
+ Two-pass scan-then-fan approach for large 1D cumsum:
4
+ scan_part_sum_kernel: per-block prefix sum + partial sums
5
+ add_base_sum_kernel: propagate partial sums across blocks
6
+
7
+ Multi-dimensional (A,B,C) variants:
8
+ scan_part_sum_abc_kernel: per-block scan along B dim
9
+ add_base_sum_abc_kernel: propagate partial sums along B dim
10
+
11
+ Row-wise persistent kernels:
12
+ reduce_then_scan_block_sum_kernel_row: block sums for row scan
13
+ reduce_then_scan_root_scan_kernel_row: persistent root scan
14
+ reduce_then_scan_block_scan_kernel_row: final block scan with prefix
15
+ """
16
+
17
+ import triton
18
+ import triton.language as tl
19
+
20
+
21
+ @tl.constexpr
22
+ def get_scan_accum_type(inp_dtype: tl.dtype) -> tl.dtype:
23
+ if inp_dtype.is_bf16() or inp_dtype.is_fp16():
24
+ return tl.float32
25
+ if inp_dtype.is_int():
26
+ return tl.int64
27
+ else:
28
+ return inp_dtype
29
+
30
+
31
+ # --- 1D scan-then-fan kernels ---
32
+
33
+
34
+ @triton.jit(do_not_specialize=["n_elements", "part_num"])
35
+ def scan_part_sum_kernel(
36
+ inp,
37
+ out,
38
+ partial_sum,
39
+ n_elements,
40
+ part_num,
41
+ BLOCK_SIZE: tl.constexpr,
42
+ ):
43
+ pid = tl.program_id(0).to(tl.int64)
44
+ 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)
45
+ mask = offset < n_elements
46
+
47
+ inp_ptrs = inp + offset
48
+ inp_vals = tl.load(inp_ptrs, mask=mask)
49
+ if (
50
+ tl.constexpr(inp_vals.dtype.is_int64())
51
+ or tl.constexpr(inp_vals.dtype.is_uint64())
52
+ ) or tl.constexpr(inp_vals.dtype.is_fp64()):
53
+ inp_vals = inp_vals
54
+ elif tl.constexpr(inp_vals.dtype.is_int()):
55
+ inp_vals = inp_vals.to(tl.int32)
56
+ else:
57
+ inp_vals = inp_vals.to(tl.float32)
58
+ result = tl.cumsum(inp_vals, axis=0)
59
+
60
+ part_sum_via_sum = tl.sum(inp_vals)
61
+
62
+ out_ptrs = out + offset
63
+ tl.store(out_ptrs, result, mask=mask)
64
+
65
+ partial_sum_ptrs = partial_sum + pid
66
+ tl.store(partial_sum_ptrs, part_sum_via_sum)
67
+
68
+
69
+ @triton.jit(do_not_specialize=["n_elements", "part_num"])
70
+ def add_base_sum_kernel(
71
+ out,
72
+ partial_sum,
73
+ n_elements,
74
+ part_num,
75
+ BLOCK_SIZE: tl.constexpr,
76
+ ):
77
+ pid = tl.program_id(0).to(tl.int64)
78
+ 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)
79
+ mask = offset < n_elements
80
+
81
+ out_ptrs = out + offset
82
+ out_vals = tl.load(out_ptrs, mask=mask)
83
+
84
+ if pid > 0:
85
+ partial_sum_ptrs = partial_sum + pid - 1
86
+ last_part_sum_via_sum = tl.load(partial_sum_ptrs)
87
+
88
+ final_vals = out_vals + last_part_sum_via_sum
89
+ tl.store(out_ptrs, final_vals.to(out_vals.dtype), mask=mask)
90
+
91
+
92
+ # --- Multi-dim (A,B,C) kernels ---
93
+
94
+
95
+ @triton.jit(do_not_specialize=["part_num"])
96
+ def scan_part_sum_abc_kernel(
97
+ inp,
98
+ out,
99
+ partial_sum,
100
+ B,
101
+ C,
102
+ part_num,
103
+ BLOCK_SIZE: tl.constexpr,
104
+ ):
105
+ pid_a = tl.program_id(0).to(tl.int64)
106
+ pid_b = tl.program_id(1).to(tl.int64)
107
+ pid_c = tl.program_id(2).to(tl.int64)
108
+
109
+ a_idx = pid_a
110
+ b_idx = pid_b.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id (register 58)
111
+ c_idx = pid_c
112
+
113
+ offset = a_idx * B * C + b_idx * C + c_idx
114
+ base_part_offset = a_idx * part_num * C + c_idx
115
+ part_offset = base_part_offset + pid_b * C
116
+
117
+ mask = b_idx < B
118
+ inp_ptrs = inp + offset
119
+ inp_vals = tl.load(inp_ptrs, mask=mask)
120
+ if (
121
+ tl.constexpr(inp_vals.dtype.is_int64())
122
+ or tl.constexpr(inp_vals.dtype.is_uint64())
123
+ ) or tl.constexpr(inp_vals.dtype.is_fp64()):
124
+ inp_vals = inp_vals
125
+ elif tl.constexpr(inp_vals.dtype.is_int()):
126
+ inp_vals = inp_vals.to(tl.int32)
127
+ else:
128
+ inp_vals = inp_vals.to(tl.float32)
129
+ result = tl.cumsum(inp_vals, axis=0)
130
+
131
+ part_sum_via_sum = tl.sum(inp_vals)
132
+
133
+ out_ptrs = out + offset
134
+ tl.store(out_ptrs, result, mask=mask)
135
+
136
+ partial_sum_ptrs = partial_sum + part_offset
137
+ tl.store(partial_sum_ptrs, part_sum_via_sum)
138
+
139
+
140
+ @triton.jit(do_not_specialize=["part_num"])
141
+ def add_base_sum_abc_kernel(
142
+ out,
143
+ partial_sum,
144
+ B,
145
+ C,
146
+ part_num,
147
+ BLOCK_SIZE: tl.constexpr,
148
+ ):
149
+ pid_a = tl.program_id(0).to(tl.int64)
150
+ pid_b = tl.program_id(1).to(tl.int64)
151
+ pid_c = tl.program_id(2).to(tl.int64)
152
+
153
+ a_idx = pid_a
154
+ b_idx = pid_b.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id (register 58)
155
+ c_idx = pid_c
156
+
157
+ base_offset = a_idx * B * C + c_idx
158
+ offset = base_offset + b_idx * C
159
+ base_part_offset = a_idx * part_num * C + c_idx
160
+ last_part_offset = base_part_offset + (pid_b - 1) * C
161
+
162
+ mask = b_idx < B
163
+ out_ptrs = out + offset
164
+ out_vals = tl.load(out_ptrs, mask=mask)
165
+
166
+ if pid_b > 0:
167
+ partial_sum_ptrs = partial_sum + last_part_offset
168
+ last_part_sum_via_sum = tl.load(partial_sum_ptrs)
169
+
170
+ final_vals = out_vals + last_part_sum_via_sum
171
+ tl.store(out_ptrs, final_vals.to(out_vals.dtype), mask=mask)
172
+
173
+
174
+ # --- Row-wise persistent scan kernels ---
175
+
176
+
177
+ @triton.jit
178
+ def reduce_then_scan_block_sum_kernel_row(
179
+ in_ptr,
180
+ block_sum_ptr,
181
+ N,
182
+ tiles_per_cta,
183
+ TILE_SIZE: tl.constexpr,
184
+ ):
185
+ """Block sum: each CTA reduces its assigned tiles into a single sum."""
186
+ pid_n = tl.program_id(1).to(tl.int64)
187
+ pid_m = tl.program_id(0).to(tl.int64)
188
+ num_programs_n = tl.num_programs(1)
189
+ block_offset = (pid_n * (tiles_per_cta * TILE_SIZE)).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)
190
+ block_end = min(block_offset + tiles_per_cta * TILE_SIZE, N).to(tl.int32)
191
+
192
+ acc_dtype: tl.constexpr = get_scan_accum_type(in_ptr.type.element_ty)
193
+ acc = tl.zeros((TILE_SIZE,), dtype=acc_dtype)
194
+ for start in range(block_offset, block_end, TILE_SIZE):
195
+ offsets = start + tl.arange(0, TILE_SIZE)
196
+ x = tl.load(in_ptr + pid_m * N + offsets, mask=offsets < N).to(acc_dtype)
197
+ acc += x
198
+ block_sum = tl.sum(acc, 0)
199
+ tl.store(
200
+ block_sum_ptr + pid_m * num_programs_n + pid_n, block_sum, cache_modifier=".cg"
201
+ )
202
+
203
+
204
+ @triton.jit
205
+ def reduce_then_scan_root_scan_kernel_row(in_ptr, out_ptr, N, TILE_SIZE: tl.constexpr):
206
+ """Persistent scan of block sums (or small row)."""
207
+ pid = tl.program_id(0).to(tl.int64)
208
+ offsets = tl.arange(0, TILE_SIZE)
209
+ mask = offsets < N
210
+ acc_dtype: tl.constexpr = get_scan_accum_type(in_ptr.type.element_ty)
211
+ x = tl.load(in_ptr + pid * N + offsets, mask=mask, other=0).to(acc_dtype)
212
+ out = tl.cumsum(x, 0)
213
+ tl.store(out_ptr + pid * N + offsets, out, mask=mask)
214
+
215
+
216
+ @triton.jit
217
+ def reduce_then_scan_block_scan_kernel_row(
218
+ in_ptr,
219
+ previous_sum_ptr,
220
+ out_ptr,
221
+ N,
222
+ num_tiles_n,
223
+ tiles_per_cta,
224
+ TILE_SIZE: tl.constexpr,
225
+ ):
226
+ """Final block scan: apply prefix from previous blocks, then local cumsum."""
227
+ pid_m = tl.program_id(0).to(tl.int64)
228
+ pid_n = tl.program_id(1).to(tl.int64)
229
+ block_offset = (pid_n * (tiles_per_cta * TILE_SIZE)).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)
230
+ block_end = min(block_offset + tiles_per_cta * TILE_SIZE, N).to(tl.int32)
231
+ acc_dtype: tl.constexpr = get_scan_accum_type(in_ptr.type.element_ty)
232
+
233
+ prefix = tl.load(
234
+ previous_sum_ptr + pid_m * num_tiles_n + pid_n - 1, mask=pid_n > 0, other=0
235
+ ).to(acc_dtype)
236
+ for start in range(block_offset, block_end, TILE_SIZE):
237
+ offsets = start + tl.arange(0, TILE_SIZE)
238
+ mask = offsets < N
239
+ x = tl.load(in_ptr + pid_m * N + offsets, mask=mask).to(acc_dtype)
240
+ tile_scan = prefix + tl.cumsum(x, 0)
241
+ prefix += tl.sum(x, 0)
242
+ tl.store(
243
+ out_ptr + pid_m * N + offsets, tile_scan, mask=mask, cache_modifier=".cg"
244
+ )