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,163 @@
1
+ """Batch normalization — pure @triton.jit kernel. Extracted from FlagGems.
2
+
3
+ For inference: uses running_mean/running_var (is_train=False path).
4
+ For training: computes online mean/var with Welford's algorithm.
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+ from triton import next_power_of_2
10
+
11
+
12
+ def _batch_norm_block_heuristic(args):
13
+ """Heuristic for BLOCK_M: process multiple batch elements per CTA when
14
+ spatial_dim is small."""
15
+ return (min(max(1, next_power_of_2(args['batch_dim'] // 2**10)), 128)
16
+ if args['spatial_dim'] < 64 else 1)
17
+
18
+
19
+ def _batch_norm_block_n_heuristic(args):
20
+ return min(4096, next_power_of_2(args['spatial_dim']))
21
+
22
+
23
+ @triton.heuristics({
24
+ 'BLOCK_M': _batch_norm_block_heuristic,
25
+ 'BLOCK_N': _batch_norm_block_n_heuristic,
26
+ })
27
+ @triton.jit
28
+ def batch_norm_forward_kernel(
29
+ input_pointer,
30
+ weight_pointer,
31
+ bias_pointer,
32
+ mean_pointer,
33
+ inv_std_pointer,
34
+ output_pointer,
35
+ running_mean_pointer,
36
+ running_var_pointer,
37
+ batch_dim,
38
+ spatial_dim,
39
+ input_batch_stride,
40
+ input_feat_stride,
41
+ input_spatial_stride,
42
+ output_batch_stride,
43
+ output_feat_stride,
44
+ output_spatial_stride,
45
+ momentum,
46
+ eps,
47
+ is_train: tl.constexpr,
48
+ BLOCK_M: tl.constexpr,
49
+ BLOCK_N: tl.constexpr,
50
+ ):
51
+ feat_pid = tl.program_id(0).to(tl.int64)
52
+
53
+ # Training mode: compute mean/var online
54
+ if is_train:
55
+ mean = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
56
+ var = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
57
+ cnt = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.int32)
58
+
59
+ m_num_steps = tl.cdiv(batch_dim, BLOCK_M)
60
+ n_num_steps = tl.cdiv(spatial_dim, BLOCK_N)
61
+
62
+ for m_step in range(0, m_num_steps):
63
+ for n_step in range(0, n_num_steps):
64
+ spatial_offset = n_step * BLOCK_N + tl.arange(0, BLOCK_N)
65
+ spatial_mask = spatial_offset < spatial_dim
66
+
67
+ batch_offset = m_step * BLOCK_M + tl.arange(0, BLOCK_M)
68
+ batch_mask = batch_offset < batch_dim
69
+
70
+ curr_input_pointer = (
71
+ input_pointer
72
+ + input_feat_stride * feat_pid
73
+ + input_batch_stride * batch_offset[:, None]
74
+ + input_spatial_stride * spatial_offset[None, :]
75
+ )
76
+
77
+ mask = batch_mask[:, None] & spatial_mask[None, :]
78
+ curr_input = tl.load(curr_input_pointer, mask=mask).to(tl.float32)
79
+
80
+ step = m_step * n_num_steps + n_step + 1
81
+ new_mean = tl.where(mask, mean + (curr_input - mean) / step, mean)
82
+ new_var = tl.where(
83
+ mask, var + (curr_input - new_mean) * (curr_input - mean), var
84
+ )
85
+ cnt += mask.to(tl.int32)
86
+ mean = new_mean
87
+ var = new_var
88
+
89
+ final_mean = tl.sum(mean * cnt) / (batch_dim * spatial_dim)
90
+ var = tl.sum(var + cnt * (mean - final_mean) * (mean - final_mean)) / (
91
+ batch_dim * spatial_dim
92
+ )
93
+ inv_std = 1.0 / tl.sqrt(var + eps)
94
+ mean = final_mean
95
+
96
+ tl.store(feat_pid + mean_pointer, mean)
97
+ tl.store(feat_pid + inv_std_pointer, inv_std)
98
+
99
+ # Running-stats update only when running buffers are supplied. The
100
+ # instance_norm case (AdaIN: training=True, no running mean/var) passes
101
+ # null running pointers — skip the update so we neither dereference a
102
+ # null pointer nor write the momentum-blended stats back into the input
103
+ # tensor (the old x-placeholder corrupted the activations in place).
104
+ if running_mean_pointer:
105
+ running_mean_pointer += feat_pid
106
+ running_var_pointer += feat_pid
107
+
108
+ running_mean = tl.load(running_mean_pointer)
109
+ running_var = tl.load(running_var_pointer)
110
+
111
+ n = batch_dim * spatial_dim
112
+ tl.store(running_mean_pointer, (1 - momentum) * running_mean + momentum * mean)
113
+ tl.store(
114
+ running_var_pointer,
115
+ (1 - momentum) * running_var + momentum * var * n / (n - 1),
116
+ )
117
+
118
+ else:
119
+ # Inference mode: use running stats
120
+ mean = tl.load(feat_pid + running_mean_pointer)
121
+ inv_std = 1.0 / tl.sqrt(tl.load(feat_pid + running_var_pointer) + eps)
122
+
123
+ if weight_pointer:
124
+ weight = tl.load(feat_pid + weight_pointer).to(tl.float32)
125
+ else:
126
+ weight = 1.0
127
+ if bias_pointer:
128
+ bias = tl.load(feat_pid + bias_pointer).to(tl.float32)
129
+ else:
130
+ bias = 0.0
131
+
132
+ # Apply normalization: weight * (x - mean) * inv_std + bias
133
+ for m_step in range(0, tl.cdiv(batch_dim, BLOCK_M)):
134
+ for n_step in range(0, tl.cdiv(spatial_dim, BLOCK_N)):
135
+ batch_offset = m_step * BLOCK_M + tl.arange(0, BLOCK_M)
136
+ batch_mask = batch_offset < batch_dim
137
+
138
+ spatial_offset = n_step * BLOCK_N + tl.arange(0, BLOCK_N)
139
+ spatial_mask = spatial_offset < spatial_dim
140
+
141
+ curr_input_pointer = (
142
+ input_pointer
143
+ + input_feat_stride * feat_pid
144
+ + input_batch_stride * batch_offset[:, None]
145
+ + input_spatial_stride * spatial_offset[None, :]
146
+ )
147
+ curr_output_pointer = (
148
+ output_pointer
149
+ + output_feat_stride * feat_pid
150
+ + output_batch_stride * batch_offset[:, None]
151
+ + output_spatial_stride * spatial_offset[None, :]
152
+ )
153
+
154
+ curr_input = tl.load(
155
+ curr_input_pointer, mask=batch_mask[:, None] & spatial_mask[None, :]
156
+ ).to(tl.float32)
157
+ output = weight * (curr_input - mean) * inv_std + bias
158
+
159
+ tl.store(
160
+ curr_output_pointer,
161
+ output,
162
+ mask=batch_mask[:, None] & spatial_mask[None, :],
163
+ )
@@ -0,0 +1,196 @@
1
+ """Element-wise add, sub, mul and div over two operands read by their own strides —
2
+ pure @triton.jit, N-D scalable like `strided_copy`.
3
+
4
+ `_prepare_binary` used to broadcast a smaller operand by `expand(...).
5
+ contiguous()` — a full-size transient per call: a conv bias (32,) over a
6
+ 448 × 448 image was 6.4 M elements written and read back per layer
7
+ (351 strided copies per Real-ESRGAN upscale, the copy census of
8
+ 2026-09-07); an attention mask (S, S) broadcast over the heads the same.
9
+ These kernels read each operand through its strides (0 on a broadcast
10
+ dim), so the broadcast costs nothing and a transposed operand is read
11
+ in place. The arithmetic is the flat kernels' expression, verbatim
12
+ (`x + alpha * y`, `x * y`), so the bytes are those of the copying path.
13
+ """
14
+
15
+ import triton
16
+ import triton.language as tl
17
+
18
+
19
+ @triton.jit
20
+ def add_strided_nd_kernel(
21
+ x_ptr, y_ptr, output_ptr,
22
+ n_elements,
23
+ alpha,
24
+ shape_ptr, # GPU pointer → NDIM int64 extents of the output
25
+ x_stride_ptr, # GPU pointer → NDIM int64 strides of x (0 on a broadcast dim)
26
+ y_stride_ptr, # GPU pointer → NDIM int64 strides of y
27
+ BLOCK_SIZE: tl.constexpr,
28
+ NDIM: tl.constexpr,
29
+ ):
30
+ """out = x + alpha * y, x and y read by their strides, out contiguous."""
31
+ pid = tl.program_id(0).to(tl.int64)
32
+ offsets = 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)
33
+ mask = offsets < n_elements
34
+ remaining = offsets
35
+ x_off = tl.zeros_like(offsets)
36
+ y_off = tl.zeros_like(offsets)
37
+ for i in tl.static_range(NDIM):
38
+ dim = NDIM - 1 - i
39
+ d = tl.load(shape_ptr + dim)
40
+ xs = tl.load(x_stride_ptr + dim)
41
+ ys = tl.load(y_stride_ptr + dim)
42
+ idx = remaining % d
43
+ remaining = remaining // d
44
+ x_off = x_off + idx * xs
45
+ y_off = y_off + idx * ys
46
+ x = tl.load(x_ptr + x_off, mask=mask)
47
+ y = tl.load(y_ptr + y_off, mask=mask)
48
+ tl.store(output_ptr + offsets, x + alpha * y, mask=mask)
49
+
50
+
51
+ @triton.jit
52
+ def mul_strided_nd_kernel(
53
+ x_ptr, y_ptr, output_ptr,
54
+ n_elements,
55
+ shape_ptr,
56
+ x_stride_ptr,
57
+ y_stride_ptr,
58
+ BLOCK_SIZE: tl.constexpr,
59
+ NDIM: tl.constexpr,
60
+ ):
61
+ """out = x * y, x and y read by their strides, out contiguous."""
62
+ pid = tl.program_id(0).to(tl.int64)
63
+ offsets = 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)
64
+ mask = offsets < n_elements
65
+ remaining = offsets
66
+ x_off = tl.zeros_like(offsets)
67
+ y_off = tl.zeros_like(offsets)
68
+ for i in tl.static_range(NDIM):
69
+ dim = NDIM - 1 - i
70
+ d = tl.load(shape_ptr + dim)
71
+ xs = tl.load(x_stride_ptr + dim)
72
+ ys = tl.load(y_stride_ptr + dim)
73
+ idx = remaining % d
74
+ remaining = remaining // d
75
+ x_off = x_off + idx * xs
76
+ y_off = y_off + idx * ys
77
+ x = tl.load(x_ptr + x_off, mask=mask)
78
+ y = tl.load(y_ptr + y_off, mask=mask)
79
+ tl.store(output_ptr + offsets, x * y, mask=mask)
80
+
81
+
82
+ @triton.jit
83
+ def sub_strided_nd_kernel(
84
+ x_ptr, y_ptr, output_ptr,
85
+ n_elements,
86
+ alpha,
87
+ shape_ptr,
88
+ x_stride_ptr,
89
+ y_stride_ptr,
90
+ BLOCK_SIZE: tl.constexpr,
91
+ NDIM: tl.constexpr,
92
+ ):
93
+ """out = x - alpha * y, x and y read by their strides, out contiguous."""
94
+ pid = tl.program_id(0).to(tl.int64)
95
+ offsets = 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)
96
+ mask = offsets < n_elements
97
+ remaining = offsets
98
+ x_off = tl.zeros_like(offsets)
99
+ y_off = tl.zeros_like(offsets)
100
+ for i in tl.static_range(NDIM):
101
+ dim = NDIM - 1 - i
102
+ d = tl.load(shape_ptr + dim)
103
+ xs = tl.load(x_stride_ptr + dim)
104
+ ys = tl.load(y_stride_ptr + dim)
105
+ idx = remaining % d
106
+ remaining = remaining // d
107
+ x_off = x_off + idx * xs
108
+ y_off = y_off + idx * ys
109
+ x = tl.load(x_ptr + x_off, mask=mask)
110
+ y = tl.load(y_ptr + y_off, mask=mask)
111
+ tl.store(output_ptr + offsets, x - alpha * y, mask=mask)
112
+
113
+
114
+ @triton.jit
115
+ def div_strided_nd_kernel(
116
+ x_ptr, y_ptr, output_ptr,
117
+ n_elements,
118
+ shape_ptr,
119
+ x_stride_ptr,
120
+ y_stride_ptr,
121
+ BLOCK_SIZE: tl.constexpr,
122
+ NDIM: tl.constexpr,
123
+ ):
124
+ """out = x / y, x and y read by their strides, out contiguous."""
125
+ pid = tl.program_id(0).to(tl.int64)
126
+ offsets = 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)
127
+ mask = offsets < n_elements
128
+ remaining = offsets
129
+ x_off = tl.zeros_like(offsets)
130
+ y_off = tl.zeros_like(offsets)
131
+ for i in tl.static_range(NDIM):
132
+ dim = NDIM - 1 - i
133
+ d = tl.load(shape_ptr + dim)
134
+ xs = tl.load(x_stride_ptr + dim)
135
+ ys = tl.load(y_stride_ptr + dim)
136
+ idx = remaining % d
137
+ remaining = remaining // d
138
+ x_off = x_off + idx * xs
139
+ y_off = y_off + idx * ys
140
+ x = tl.load(x_ptr + x_off, mask=mask)
141
+ y = tl.load(y_ptr + y_off, mask=mask)
142
+ tl.store(output_ptr + offsets, x / y, mask=mask)
143
+
144
+
145
+ @triton.jit
146
+ def add_scalar_strided_nd_kernel(
147
+ x_ptr, output_ptr,
148
+ n_elements,
149
+ scalar,
150
+ shape_ptr,
151
+ x_stride_ptr,
152
+ BLOCK_SIZE: tl.constexpr,
153
+ NDIM: tl.constexpr,
154
+ ):
155
+ """out = x + scalar, x read by its strides, out contiguous (add_scalar_kernel's expression)."""
156
+ pid = tl.program_id(0).to(tl.int64)
157
+ offsets = 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)
158
+ mask = offsets < n_elements
159
+ remaining = offsets
160
+ x_off = tl.zeros_like(offsets)
161
+ for i in tl.static_range(NDIM):
162
+ dim = NDIM - 1 - i
163
+ d = tl.load(shape_ptr + dim)
164
+ xs = tl.load(x_stride_ptr + dim)
165
+ idx = remaining % d
166
+ remaining = remaining // d
167
+ x_off = x_off + idx * xs
168
+ x = tl.load(x_ptr + x_off, mask=mask)
169
+ tl.store(output_ptr + offsets, x + scalar, mask=mask)
170
+
171
+
172
+ @triton.jit
173
+ def mul_scalar_strided_nd_kernel(
174
+ x_ptr, output_ptr,
175
+ n_elements,
176
+ scalar,
177
+ shape_ptr,
178
+ x_stride_ptr,
179
+ BLOCK_SIZE: tl.constexpr,
180
+ NDIM: tl.constexpr,
181
+ ):
182
+ """out = x * scalar, x read by its strides, out contiguous (mul_scalar_kernel's expression)."""
183
+ pid = tl.program_id(0).to(tl.int64)
184
+ offsets = 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)
185
+ mask = offsets < n_elements
186
+ remaining = offsets
187
+ x_off = tl.zeros_like(offsets)
188
+ for i in tl.static_range(NDIM):
189
+ dim = NDIM - 1 - i
190
+ d = tl.load(shape_ptr + dim)
191
+ xs = tl.load(x_stride_ptr + dim)
192
+ idx = remaining % d
193
+ remaining = remaining // d
194
+ x_off = x_off + idx * xs
195
+ x = tl.load(x_ptr + x_off, mask=mask)
196
+ tl.store(output_ptr + offsets, x * scalar, mask=mask)
@@ -0,0 +1,26 @@
1
+ """Bitwise AND kernel — extracted from FlagGems.
2
+
3
+ Pure Triton. ZERO PyTorch imports.
4
+ Logic: result = x & y
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+
10
+ @triton.jit
11
+ def bitwise_and_forward_kernel(
12
+ x_ptr,
13
+ y_ptr,
14
+ output_ptr,
15
+ n_elements,
16
+ BLOCK_SIZE: tl.constexpr,
17
+ ):
18
+ pid = tl.program_id(0).to(tl.int64)
19
+ 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)
20
+ mask = offset < n_elements
21
+
22
+ x = tl.load(x_ptr + offset, mask=mask)
23
+ y = tl.load(y_ptr + offset, mask=mask)
24
+
25
+ result = x & y
26
+ tl.store(output_ptr + offset, result, mask=mask)
@@ -0,0 +1,47 @@
1
+ """Bitwise left shift — pure @triton.jit kernel.
2
+
3
+ Computes: output = x << y (element-wise).
4
+
5
+ Both inputs must be integer tensors.
6
+
7
+ Extracted from FlagGems reference (bitwise_left_shift.py).
8
+ """
9
+
10
+ import triton
11
+ import triton.language as tl
12
+
13
+ @triton.jit
14
+ def bitwise_left_shift_kernel(
15
+ x_ptr,
16
+ y_ptr,
17
+ output_ptr,
18
+ n_elements,
19
+ BLOCK_SIZE: tl.constexpr,
20
+ ):
21
+ """Bitwise left shift: out = x << y."""
22
+ pid = tl.program_id(0).to(tl.int64)
23
+ 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)
24
+ mask = offset < n_elements
25
+
26
+ x = tl.load(x_ptr + offset, mask=mask)
27
+ y = tl.load(y_ptr + offset, mask=mask)
28
+
29
+ result = x << y
30
+ tl.store(output_ptr + offset, result, mask=mask)
31
+
32
+ @triton.jit
33
+ def bitwise_left_shift_scalar_kernel(
34
+ x_ptr,
35
+ output_ptr,
36
+ n_elements,
37
+ shift_amount,
38
+ BLOCK_SIZE: tl.constexpr,
39
+ ):
40
+ """Bitwise left shift by scalar: out = x << shift_amount."""
41
+ pid = tl.program_id(0).to(tl.int64)
42
+ 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)
43
+ mask = offset < n_elements
44
+
45
+ x = tl.load(x_ptr + offset, mask=mask)
46
+ result = x << shift_amount
47
+ tl.store(output_ptr + offset, result, mask=mask)
@@ -0,0 +1,24 @@
1
+ """Bitwise NOT kernel — extracted from FlagGems.
2
+
3
+ Pure Triton. ZERO PyTorch imports.
4
+ Logic: result = ~x
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+
10
+ @triton.jit
11
+ def bitwise_not_forward_kernel(
12
+ x_ptr,
13
+ output_ptr,
14
+ n_elements,
15
+ BLOCK_SIZE: tl.constexpr,
16
+ ):
17
+ pid = tl.program_id(0).to(tl.int64)
18
+ 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)
19
+ mask = offset < n_elements
20
+
21
+ x = tl.load(x_ptr + offset, mask=mask)
22
+
23
+ result = ~x
24
+ tl.store(output_ptr + offset, result, mask=mask)
@@ -0,0 +1,26 @@
1
+ """Bitwise OR kernel — extracted from FlagGems.
2
+
3
+ Pure Triton. ZERO PyTorch imports.
4
+ Logic: result = x | y
5
+ """
6
+
7
+ import triton
8
+ import triton.language as tl
9
+
10
+ @triton.jit
11
+ def bitwise_or_forward_kernel(
12
+ x_ptr,
13
+ y_ptr,
14
+ output_ptr,
15
+ n_elements,
16
+ BLOCK_SIZE: tl.constexpr,
17
+ ):
18
+ pid = tl.program_id(0).to(tl.int64)
19
+ 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)
20
+ mask = offset < n_elements
21
+
22
+ x = tl.load(x_ptr + offset, mask=mask)
23
+ y = tl.load(y_ptr + offset, mask=mask)
24
+
25
+ result = x | y
26
+ tl.store(output_ptr + offset, result, mask=mask)
@@ -0,0 +1,47 @@
1
+ """Bitwise right shift — pure @triton.jit kernel.
2
+
3
+ Computes: output = x >> y (element-wise, arithmetic shift).
4
+
5
+ Both inputs must be integer tensors.
6
+
7
+ Extracted from FlagGems reference (bitwise_right_shift.py).
8
+ """
9
+
10
+ import triton
11
+ import triton.language as tl
12
+
13
+ @triton.jit
14
+ def bitwise_right_shift_kernel(
15
+ x_ptr,
16
+ y_ptr,
17
+ output_ptr,
18
+ n_elements,
19
+ BLOCK_SIZE: tl.constexpr,
20
+ ):
21
+ """Bitwise right shift: out = x >> y."""
22
+ pid = tl.program_id(0).to(tl.int64)
23
+ 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)
24
+ mask = offset < n_elements
25
+
26
+ x = tl.load(x_ptr + offset, mask=mask)
27
+ y = tl.load(y_ptr + offset, mask=mask)
28
+
29
+ result = x >> y
30
+ tl.store(output_ptr + offset, result, mask=mask)
31
+
32
+ @triton.jit
33
+ def bitwise_right_shift_scalar_kernel(
34
+ x_ptr,
35
+ output_ptr,
36
+ n_elements,
37
+ shift_amount,
38
+ BLOCK_SIZE: tl.constexpr,
39
+ ):
40
+ """Bitwise right shift by scalar: out = x >> shift_amount."""
41
+ pid = tl.program_id(0).to(tl.int64)
42
+ 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)
43
+ mask = offset < n_elements
44
+
45
+ x = tl.load(x_ptr + offset, mask=mask)
46
+ result = x >> shift_amount
47
+ tl.store(output_ptr + offset, result, mask=mask)
@@ -0,0 +1,37 @@
1
+ """Bucketize (searchsorted over a small boundary vector) — pure
2
+ @triton.jit kernel.
3
+
4
+ aten::bucketize semantics: for each element v, the returned index i
5
+ counts the boundaries that sort strictly before v (right=False,
6
+ ``boundaries[i-1] < v <= boundaries[i]``) or before-or-equal
7
+ (right=True, ``boundaries[i-1] <= v < boundaries[i]``).
8
+
9
+ Boundary vectors on this path are decode-control scale (block-diagonal
10
+ attention masks: one boundary per temporal frame / packed segment —
11
+ tens of entries), so a linear scan per element beats a binary search
12
+ and stays branch-free and bit-reproducible.
13
+ """
14
+
15
+ import triton
16
+ import triton.language as tl
17
+
18
+
19
+ @triton.jit
20
+ def bucketize_kernel(
21
+ x_ptr, boundaries_ptr, out_ptr,
22
+ n_elements, n_boundaries,
23
+ RIGHT: tl.constexpr,
24
+ BLOCK_SIZE: tl.constexpr,
25
+ ):
26
+ pid = tl.program_id(0).to(tl.int64)
27
+ offs = 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)
28
+ in_range = offs < n_elements
29
+ x = tl.load(x_ptr + offs, mask=in_range, other=0)
30
+ acc = tl.zeros((BLOCK_SIZE,), dtype=tl.int64)
31
+ for i in range(0, n_boundaries):
32
+ b = tl.load(boundaries_ptr + i)
33
+ if RIGHT:
34
+ acc += (b <= x).to(tl.int64)
35
+ else:
36
+ acc += (b < x).to(tl.int64)
37
+ tl.store(out_ptr + offs, acc, mask=in_range)
@@ -0,0 +1,87 @@
1
+ """Concatenation — pure @triton.jit kernel.
2
+
3
+ Ported from FlagGems cat_copy_func_kernel_4 (Apache-2.0 license).
4
+ Copies up to 4 input tensors per launch into the correct position
5
+ in the output tensor along the cat dimension.
6
+ """
7
+
8
+ import triton
9
+ import triton.language as tl
10
+
11
+
12
+ @triton.jit
13
+ def cat_copy_kernel_4(
14
+ out_ptr,
15
+ in_ptr_a,
16
+ in_ptr_b,
17
+ in_ptr_c,
18
+ in_ptr_d,
19
+ dim_size_in_a,
20
+ dim_size_in_b,
21
+ dim_size_in_c,
22
+ dim_size_in_d,
23
+ dim_size_out,
24
+ dim_prod_post,
25
+ dim_offset_a,
26
+ dim_offset_b,
27
+ dim_offset_c,
28
+ dim_offset_d,
29
+ total_elements_a,
30
+ total_elements_b,
31
+ total_elements_c,
32
+ total_elements_d,
33
+ BLOCK_X: tl.constexpr,
34
+ ):
35
+ """Copy up to 4 input tensors into their correct positions in the output.
36
+
37
+ pid_x indexes blocks within a single input tensor.
38
+ pid_y selects which of the 4 input tensors this program handles.
39
+
40
+ The index remapping converts flat input indices to flat output indices
41
+ by splitting into (pre_dim, cat_dim, post_dim) components and applying
42
+ the cat dimension offset.
43
+ """
44
+ pid_x = tl.program_id(0).to(tl.int64)
45
+ pid_y = tl.program_id(1).to(tl.int64)
46
+
47
+ # Select the correct input tensor and its metadata
48
+ if pid_y == 0:
49
+ in_ptr = in_ptr_a
50
+ elif pid_y == 1:
51
+ in_ptr = in_ptr_b
52
+ elif pid_y == 2:
53
+ in_ptr = in_ptr_c
54
+ else:
55
+ in_ptr = in_ptr_d
56
+
57
+ # The per-input scalars are selected OUTSIDE the pointer branches, by tl.where,
58
+ # which unifies their types: Triton specialises a Python int as int32 when it
59
+ # fits, int64 when it does not, and as a constexpr when it equals 1 — so one
60
+ # input past 2^31 elements beside a small one made the if/elif branches
61
+ # disagree (`Mismatched type for total_elements`, Open-Sora-v2 VAE decode,
62
+ # 2026-09-25), and a `.to(tl.int64)` inside the branches broke on the
63
+ # constexpr form ('int' object has no attribute 'to', Flex.1-alpha).
64
+ dim_size_in = tl.where(pid_y == 0, dim_size_in_a, tl.where(pid_y == 1, dim_size_in_b, tl.where(pid_y == 2, dim_size_in_c, dim_size_in_d)))
65
+ dim_offset = tl.where(pid_y == 0, dim_offset_a, tl.where(pid_y == 1, dim_offset_b, tl.where(pid_y == 2, dim_offset_c, dim_offset_d)))
66
+ total_elements = tl.where(pid_y == 0, total_elements_a, tl.where(pid_y == 1, total_elements_b, tl.where(pid_y == 2, total_elements_c, total_elements_d)))
67
+
68
+ block_start = pid_x * BLOCK_X
69
+ offsets = tl.arange(0, BLOCK_X)
70
+ mask = block_start + offsets < total_elements
71
+
72
+ idx = block_start + offsets
73
+
74
+ # Decompose flat index into (pre, dim, post) coordinates
75
+ pre_idx = idx // (dim_size_in * dim_prod_post)
76
+ dim_idx = (idx // dim_prod_post) % dim_size_in
77
+ post_idx = idx % dim_prod_post
78
+
79
+ # Compute output index with the cat dimension offset applied
80
+ out_idx = (
81
+ pre_idx * dim_size_out * dim_prod_post
82
+ + (dim_idx + dim_offset) * dim_prod_post
83
+ + post_idx
84
+ )
85
+
86
+ data = tl.load(in_ptr + idx, mask=mask)
87
+ tl.store(out_ptr + out_idx, data, mask=mask)
nbxtensor/ops/celu.py ADDED
@@ -0,0 +1,20 @@
1
+ """CELU activation — pure @triton.jit kernel. Logic from FlagGems."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def celu_forward_kernel(
8
+ input_ptr, output_ptr,
9
+ n_elements,
10
+ alpha,
11
+ BLOCK_SIZE: tl.constexpr,
12
+ ):
13
+ pid = tl.program_id(0).to(tl.int64)
14
+ offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
15
+ mask = offset < n_elements
16
+
17
+ x = tl.load(input_ptr + offset, mask=mask)
18
+ x_fp32 = x.to(tl.float32)
19
+ out = tl.where(x_fp32 > 0, x_fp32, alpha * (tl.exp(x_fp32 / alpha) - 1.0))
20
+ tl.store(output_ptr + offset, out, mask=mask)