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/rope.py ADDED
@@ -0,0 +1,142 @@
1
+ """RoPE (Rotary Position Embedding) — pure @triton.jit kernels.
2
+
3
+ Fused forward kernel: applies rotary embedding in-place to Q and K.
4
+ HuggingFace Llama/Mistral style: split-half rotation (not interleaved).
5
+ Extracted from Liger-Kernel (BSD-2-Clause; THIRD_PARTY_NOTICES.md).
6
+
7
+ Layout:
8
+ q: (bsz, seq_len, n_q_heads, head_dim) — physical (transposed from [B,H,S,D])
9
+ k: (bsz, seq_len, n_kv_heads, head_dim)
10
+ cos: (1|bsz, seq_len, head_dim)
11
+ sin: (1|bsz, seq_len, head_dim)
12
+
13
+ Grid: (bsz * seq_len,)
14
+ Each program handles one (batch, position) across ALL heads.
15
+ """
16
+
17
+ import triton
18
+ import triton.language as tl
19
+
20
+
21
+ @triton.jit
22
+ def rope_forward_kernel(
23
+ q_ptr,
24
+ q_row_stride,
25
+ k_ptr,
26
+ k_row_stride,
27
+ cos,
28
+ cos_row_stride,
29
+ sin,
30
+ sin_row_stride,
31
+ sl,
32
+ bs: tl.constexpr,
33
+ cos_bs: tl.constexpr,
34
+ n_qh: tl.constexpr,
35
+ n_kh: tl.constexpr,
36
+ hd: tl.constexpr,
37
+ pad_n_qh: tl.constexpr,
38
+ pad_n_kh: tl.constexpr,
39
+ pad_hd: tl.constexpr,
40
+ BLOCK_SIZE: tl.constexpr,
41
+ BACKWARD_PASS: tl.constexpr = False,
42
+ ):
43
+ """Fused RoPE kernel — applies rotary embedding in-place to Q and K.
44
+
45
+ Each program instance processes one (batch, seq_position) pair across
46
+ all Q heads and K heads simultaneously. The rotation formula is:
47
+
48
+ y_left = x_left * cos - x_right * sin
49
+ y_right = x_right * cos + x_left * sin
50
+
51
+ For backward pass, sin is negated (equivalent to inverse rotation).
52
+ """
53
+ pid = tl.program_id(0).to(tl.int64)
54
+
55
+ # Advance pointers to current (batch, position) row
56
+ q_ptr = q_ptr + pid * q_row_stride
57
+ k_ptr = k_ptr + pid * k_row_stride
58
+
59
+ # Locate cos/sin row for this token position
60
+ # pid indexes [bsz, seq_len] flattened; seq_len is fastest-changing
61
+ batch_idx = pid // sl
62
+ cos_row_idx = pid % sl
63
+ cos = cos + tl.where(
64
+ cos_bs == 1,
65
+ cos_row_idx * cos_row_stride,
66
+ batch_idx * (sl * cos_row_stride) + cos_row_idx * cos_row_stride,
67
+ )
68
+ sin = sin + tl.where(
69
+ cos_bs == 1,
70
+ cos_row_idx * sin_row_stride,
71
+ batch_idx * (sl * sin_row_stride) + cos_row_idx * sin_row_stride,
72
+ )
73
+
74
+ # Load cos/sin (only need left half — right half is identical)
75
+ cos_offsets = tl.arange(0, pad_hd // 2)
76
+ cos_mask = cos_offsets < hd // 2
77
+ # A table WIDER than Q is rounded to Q's dtype on load (round-to-nearest,
78
+ # the conversion a stored cast makes): the wrapper no longer materialises
79
+ # a cast copy of the step's fp32 cos/sin per layer for an fp16 Q. A table
80
+ # narrower than Q is widened by the wrapper beforehand (a copy, said in
81
+ # its line): widened on load, the fp32 rotation's fused multiply-add
82
+ # moved with the convert before it (Sana's Gemma-2 encoder, 2026-09-07).
83
+ cos_row = tl.load(cos + cos_offsets, mask=cos_mask, other=0).to(q_ptr.dtype.element_ty)
84
+ sin_row = tl.load(sin + cos_offsets, mask=cos_mask, other=0).to(q_ptr.dtype.element_ty)
85
+
86
+ # --- Q heads: load left half and right half ---
87
+ first_half_q_offsets = (
88
+ tl.arange(0, pad_n_qh)[:, None] * hd
89
+ + tl.arange(0, pad_hd // 2)[None, :]
90
+ )
91
+ first_q_mask = (tl.arange(0, pad_n_qh)[:, None] < n_qh) & (
92
+ tl.arange(0, pad_hd // 2)[None, :] < hd // 2
93
+ )
94
+ q_tile_1 = tl.load(
95
+ q_ptr + first_half_q_offsets, mask=first_q_mask, other=0
96
+ ).to(sin_row.dtype)
97
+
98
+ second_half_q_offsets = first_half_q_offsets + (hd // 2)
99
+ q_tile_2 = tl.load(
100
+ q_ptr + second_half_q_offsets, mask=first_q_mask, other=0
101
+ ).to(sin_row.dtype)
102
+
103
+ # --- K heads: load left half and right half ---
104
+ first_half_k_offsets = (
105
+ tl.arange(0, pad_n_kh)[:, None] * hd
106
+ + tl.arange(0, pad_hd // 2)[None, :]
107
+ )
108
+ first_k_mask = (tl.arange(0, pad_n_kh)[:, None] < n_kh) & (
109
+ tl.arange(0, pad_hd // 2)[None, :] < hd // 2
110
+ )
111
+ k_tile_1 = tl.load(
112
+ k_ptr + first_half_k_offsets, mask=first_k_mask, other=0
113
+ ).to(sin_row.dtype)
114
+
115
+ second_half_k_offsets = first_half_k_offsets + (hd // 2)
116
+ k_tile_2 = tl.load(
117
+ k_ptr + second_half_k_offsets, mask=first_k_mask, other=0
118
+ ).to(sin_row.dtype)
119
+
120
+ # --- Apply rotation ---
121
+ if not BACKWARD_PASS:
122
+ # Forward: y = [x1, x2] * [cos, cos] + [-x2, x1] * [sin, sin]
123
+ # The plain expression, as the backend contracts it per dtype: written
124
+ # with an explicit fma it matched the fp32 path but not the fp16 one
125
+ # (VibeVoice, 2026-09-07) — the contraction is not the same in both,
126
+ # and the bytes of every certified row depend on it staying as it is.
127
+ new_q_1 = q_tile_1 * cos_row - q_tile_2 * sin_row
128
+ new_q_2 = q_tile_2 * cos_row + q_tile_1 * sin_row
129
+ new_k_1 = k_tile_1 * cos_row - k_tile_2 * sin_row
130
+ new_k_2 = k_tile_2 * cos_row + k_tile_1 * sin_row
131
+ else:
132
+ # Backward (inverse rotation): negate sin
133
+ new_q_1 = q_tile_1 * cos_row + q_tile_2 * sin_row
134
+ new_q_2 = q_tile_2 * cos_row - q_tile_1 * sin_row
135
+ new_k_1 = k_tile_1 * cos_row + k_tile_2 * sin_row
136
+ new_k_2 = k_tile_2 * cos_row - k_tile_1 * sin_row
137
+
138
+ # Store results in-place
139
+ tl.store(q_ptr + first_half_q_offsets, new_q_1, mask=first_q_mask)
140
+ tl.store(q_ptr + second_half_q_offsets, new_q_2, mask=first_q_mask)
141
+ tl.store(k_ptr + first_half_k_offsets, new_k_1, mask=first_k_mask)
142
+ tl.store(k_ptr + second_half_k_offsets, new_k_2, mask=first_k_mask)
nbxtensor/ops/rsqrt.py ADDED
@@ -0,0 +1,17 @@
1
+ """Reciprocal square root — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def rsqrt_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.rsqrt(x.to(tl.float32)), mask=mask)
@@ -0,0 +1,96 @@
1
+ """Scaled softmax — pure @triton.jit kernel.
2
+
3
+ Computes softmax(input * scale_factor) for attention score tensors.
4
+ Input shape: [B, H, Q, K] (batch, heads, query_seq, key_seq).
5
+
6
+ Uses online softmax (two-pass): first pass computes max and exp-sum,
7
+ second pass normalizes. Numerically stable.
8
+
9
+ Extracted from FlagGems reference (scaled_softmax.py).
10
+ """
11
+
12
+ import triton
13
+ import triton.language as tl
14
+
15
+
16
+ @triton.jit
17
+ def scaled_softmax_kernel(
18
+ output_ptr,
19
+ input_ptr,
20
+ scale_factor,
21
+ query_seq_len,
22
+ key_seq_len,
23
+ stride_b,
24
+ stride_h,
25
+ stride_q,
26
+ BLOCK_Q: tl.constexpr,
27
+ BLOCK_K: tl.constexpr,
28
+ ):
29
+ """Scaled softmax: out = softmax(input * scale_factor) along last dim.
30
+
31
+ Grid: (cdiv(query_seq_len, BLOCK_Q), num_heads, batch_size)
32
+ """
33
+ query_tile_idx = tl.program_id(0).to(tl.int64)
34
+ head_idx = tl.program_id(1).to(tl.int64)
35
+ batch_idx = tl.program_id(2).to(tl.int64)
36
+
37
+ start_q = query_tile_idx * BLOCK_Q
38
+ q_offsets = start_q + tl.arange(0, BLOCK_Q)
39
+ q_mask = q_offsets < query_seq_len
40
+
41
+ row_start = (
42
+ input_ptr
43
+ + batch_idx * stride_b
44
+ + head_idx * stride_h
45
+ + q_offsets * stride_q
46
+ )
47
+
48
+ # Pass 1: find row max and exp-sum (online softmax)
49
+ m = tl.full([BLOCK_Q], -float('inf'), dtype=tl.float32)
50
+ exp_sum = tl.zeros([BLOCK_Q], dtype=tl.float32)
51
+
52
+ for k_idx in range(0, tl.cdiv(key_seq_len, BLOCK_K)):
53
+ k_offsets = k_idx * BLOCK_K + tl.arange(0, BLOCK_K)
54
+ block_ptr = row_start[:, None] + k_offsets[None, :]
55
+
56
+ row_mask = q_mask[:, None]
57
+ col_mask = k_offsets[None, :] < key_seq_len
58
+ valid = row_mask & col_mask
59
+
60
+ s = tl.load(block_ptr, mask=valid, other=-float('inf'))
61
+ s = s * scale_factor
62
+
63
+ m_new = tl.max(s, axis=1)
64
+ m_old = m
65
+ m = tl.maximum(m_old, m_new)
66
+
67
+ # Rescale previous sum
68
+ exp_sum = exp_sum * tl.exp(m_old - m)
69
+ # Add current block
70
+ s_exp = tl.exp(s - m[:, None])
71
+ exp_sum = exp_sum + tl.sum(tl.where(valid, s_exp, 0.0), axis=1)
72
+
73
+ exp_sum_inv = 1.0 / exp_sum
74
+
75
+ # Pass 2: compute and store normalized values
76
+ out_row_start = (
77
+ output_ptr
78
+ + batch_idx * stride_b
79
+ + head_idx * stride_h
80
+ + q_offsets * stride_q
81
+ )
82
+
83
+ for k_idx in range(0, tl.cdiv(key_seq_len, BLOCK_K)):
84
+ k_offsets = k_idx * BLOCK_K + tl.arange(0, BLOCK_K)
85
+ in_ptr = row_start[:, None] + k_offsets[None, :]
86
+ out_ptr = out_row_start[:, None] + k_offsets[None, :]
87
+
88
+ row_mask = q_mask[:, None]
89
+ col_mask = k_offsets[None, :] < key_seq_len
90
+ valid = row_mask & col_mask
91
+
92
+ s = tl.load(in_ptr, mask=valid, other=-float('inf'))
93
+ s = s * scale_factor
94
+ p = tl.exp(s - m[:, None]) * exp_sum_inv[:, None]
95
+
96
+ tl.store(out_ptr, p, mask=valid)
@@ -0,0 +1,139 @@
1
+ """Scatter along dim — pure @triton.jit kernel.
2
+
3
+ Approach from FlagGems: work on flattened index space. For each element,
4
+ decompose into (outer, dim, inner), load the scatter index, then store
5
+ (or atomic_add) into the destination at the indexed position.
6
+
7
+ scatter: dst[outer][index[outer][dim][inner]][inner] = src[outer][dim][inner]
8
+ scatter_add: dst[...] += src[...]
9
+ """
10
+
11
+ import triton
12
+ import triton.language as tl
13
+
14
+ @triton.jit
15
+ def scatter_kernel(
16
+ src, index, out,
17
+ N,
18
+ out_dim_stride,
19
+ src_stride_outer, src_stride_dim, src_stride_inner,
20
+ idx_stride_outer, idx_stride_dim, idx_stride_inner,
21
+ out_stride_outer, out_stride_inner,
22
+ outer_size, dim_size, inner_size,
23
+ BLOCK_SIZE: tl.constexpr,
24
+ ):
25
+ """Scatter: out[outer][index_val][inner] = src[outer][dim][inner]."""
26
+ pid = tl.program_id(0).to(tl.int64)
27
+ 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)
28
+ mask = offset < N
29
+
30
+ inner_idx = offset % inner_size
31
+ temp = offset // inner_size
32
+ dim_idx = temp % dim_size
33
+ outer_idx = temp // dim_size
34
+
35
+ # Load scatter index
36
+ idx_offset = outer_idx * idx_stride_outer + dim_idx * idx_stride_dim + inner_idx * idx_stride_inner
37
+ cur_index = tl.load(index + idx_offset, mask=mask, other=0)
38
+
39
+ # Load source value
40
+ src_offset = outer_idx * src_stride_outer + dim_idx * src_stride_dim + inner_idx * src_stride_inner
41
+ val = tl.load(src + src_offset, mask=mask, other=0.0)
42
+
43
+ # Store to output at scattered position
44
+ out_offset = outer_idx * out_stride_outer + cur_index * out_dim_stride + inner_idx * out_stride_inner
45
+ tl.store(out + out_offset, val, mask=mask)
46
+
47
+ @triton.jit
48
+ def scatter_add_kernel(
49
+ src, index, out,
50
+ N,
51
+ out_dim_stride,
52
+ src_stride_outer, src_stride_dim, src_stride_inner,
53
+ idx_stride_outer, idx_stride_dim, idx_stride_inner,
54
+ out_stride_outer, out_stride_inner,
55
+ outer_size, dim_size, inner_size,
56
+ BLOCK_SIZE: tl.constexpr,
57
+ ):
58
+ """Scatter add: out[outer][index_val][inner] += src[outer][dim][inner]."""
59
+ pid = tl.program_id(0).to(tl.int64)
60
+ 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)
61
+ mask = offset < N
62
+
63
+ inner_idx = offset % inner_size
64
+ temp = offset // inner_size
65
+ dim_idx = temp % dim_size
66
+ outer_idx = temp // dim_size
67
+
68
+ idx_offset = outer_idx * idx_stride_outer + dim_idx * idx_stride_dim + inner_idx * idx_stride_inner
69
+ cur_index = tl.load(index + idx_offset, mask=mask, other=0)
70
+
71
+ src_offset = outer_idx * src_stride_outer + dim_idx * src_stride_dim + inner_idx * src_stride_inner
72
+ val = tl.load(src + src_offset, mask=mask, other=0.0)
73
+
74
+ out_offset = outer_idx * out_stride_outer + cur_index * out_dim_stride + inner_idx * out_stride_inner
75
+ tl.atomic_add(out + out_offset, val, mask=mask)
76
+
77
+ # ═══════════════════════════════════════════════════════════════════════════════
78
+ # scatter_reduce kernels — amax, amin using Triton native atomics
79
+ # ═══════════════════════════════════════════════════════════════════════════════
80
+
81
+ @triton.jit
82
+ def scatter_reduce_amax_kernel(
83
+ src, index, out,
84
+ N,
85
+ out_dim_stride,
86
+ src_stride_outer, src_stride_dim, src_stride_inner,
87
+ idx_stride_outer, idx_stride_dim, idx_stride_inner,
88
+ out_stride_outer, out_stride_inner,
89
+ outer_size, dim_size, inner_size,
90
+ BLOCK_SIZE: tl.constexpr,
91
+ ):
92
+ """scatter_reduce with reduce='amax': atomic max."""
93
+ pid = tl.program_id(0).to(tl.int64)
94
+ 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)
95
+ mask = offset < N
96
+
97
+ inner_idx = offset % inner_size
98
+ temp = offset // inner_size
99
+ dim_idx = temp % dim_size
100
+ outer_idx = temp // dim_size
101
+
102
+ idx_offset = outer_idx * idx_stride_outer + dim_idx * idx_stride_dim + inner_idx * idx_stride_inner
103
+ cur_index = tl.load(index + idx_offset, mask=mask, other=0)
104
+
105
+ src_offset = outer_idx * src_stride_outer + dim_idx * src_stride_dim + inner_idx * src_stride_inner
106
+ val = tl.load(src + src_offset, mask=mask, other=0.0)
107
+
108
+ out_offset = outer_idx * out_stride_outer + cur_index * out_dim_stride + inner_idx * out_stride_inner
109
+ tl.atomic_max(out + out_offset, val, mask=mask)
110
+
111
+ @triton.jit
112
+ def scatter_reduce_amin_kernel(
113
+ src, index, out,
114
+ N,
115
+ out_dim_stride,
116
+ src_stride_outer, src_stride_dim, src_stride_inner,
117
+ idx_stride_outer, idx_stride_dim, idx_stride_inner,
118
+ out_stride_outer, out_stride_inner,
119
+ outer_size, dim_size, inner_size,
120
+ BLOCK_SIZE: tl.constexpr,
121
+ ):
122
+ """scatter_reduce with reduce='amin': atomic min."""
123
+ pid = tl.program_id(0).to(tl.int64)
124
+ 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)
125
+ mask = offset < N
126
+
127
+ inner_idx = offset % inner_size
128
+ temp = offset // inner_size
129
+ dim_idx = temp % dim_size
130
+ outer_idx = temp // dim_size
131
+
132
+ idx_offset = outer_idx * idx_stride_outer + dim_idx * idx_stride_dim + inner_idx * idx_stride_inner
133
+ cur_index = tl.load(index + idx_offset, mask=mask, other=0)
134
+
135
+ src_offset = outer_idx * src_stride_outer + dim_idx * src_stride_dim + inner_idx * src_stride_inner
136
+ val = tl.load(src + src_offset, mask=mask, other=0.0)
137
+
138
+ out_offset = outer_idx * out_stride_outer + cur_index * out_dim_stride + inner_idx * out_stride_inner
139
+ tl.atomic_min(out + out_offset, val, mask=mask)