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,479 @@
1
+ """The fp64 oracle the autotune screen consults, computed from the LIVE args.
2
+
3
+ The screen's consensus asks the candidates whether they agree with each other.
4
+ That question has one blind spot, and it is not academic: when the defect is in
5
+ the BACKEND'S EMISSION rather than in the choice of tile, every candidate is
6
+ wrong in the same way, the vote is unanimous, and the screen seats a wrong
7
+ configuration in silence.
8
+
9
+ Measured 2026-09-11 on four `addmm` shapes the catalogue demands: the emitted
10
+ MSL declared the float scalars `alpha`/`beta` as `int`, so the bit pattern of
11
+ `1.0f` multiplied the accumulator — wrong by a factor of 1065353216. Eight
12
+ runs, four shapes, two arms: the bare vote SEATED a configuration every time;
13
+ the same screen with this oracle REFUSED every time.
14
+
15
+ ## Where the cost is paid, and why it is affordable
16
+
17
+ A CERTIFIED entry is served without a sweep, without a screen and without an
18
+ oracle — zero cost. Only an UNCERTIFIED key sweeps, and only then is the screen
19
+ run and the oracle computed, once for the key and not once per candidate.
20
+
21
+ **The cost is therefore paid exactly where the risk lives, and never
22
+ elsewhere** — and the certified directory gains a second reason to exist that
23
+ was not visible before: it does not only remove the sweep, it removes the
24
+ oracle's cost with it.
25
+
26
+ ## What this covers, and what it says when it does not
27
+
28
+ An oracle exists for the kernels whose mathematics can be recomputed in float64
29
+ on the host from the live operands. For anything else this returns None, and
30
+ the screen falls back to the consensus — LOUDLY, once per process, naming the
31
+ key, because a screen running without an oracle is exactly the situation the
32
+ `addmm` measurement showed to be dangerous.
33
+ """
34
+ from __future__ import annotations
35
+
36
+ from typing import Any, Dict, List, Optional
37
+
38
+ import numpy as np
39
+
40
+ #: Keys already announced as running without an oracle. Once per process: a
41
+ #: warning repeated per launch is a warning nobody reads.
42
+ _ANNOUNCED: set = set()
43
+
44
+ _NP = {"fp16": np.float16, "float16": np.float16,
45
+ "fp32": np.float32, "float32": np.float32,
46
+ "fp64": np.float64, "float64": np.float64}
47
+
48
+
49
+ def _to_f64(t) -> Optional[np.ndarray]:
50
+ """A live operand as float64, or None when it cannot be read here."""
51
+ try:
52
+ from nbxtensor.dtype.nbx_dtype import NBXDtype
53
+ # ONE path to host memory, for every dtype. The bf16 case used to read
54
+ # the device pointer directly with `ctypes.string_at`, which crosses NO
55
+ # BARRIER -- so a buffer a kernel had just written was read before the
56
+ # write landed. Measured 2026-09-12 on a kernel-written buffer: 4093 of
57
+ # 4096 elements differed from the copy path, and agreed after an
58
+ # explicit synchronisation.
59
+ #
60
+ # That produced the symptom it is easiest to misread: every candidate
61
+ # compared against the same stale bytes, so the fp64 oracle contradicted
62
+ # all ten and the screen refused the whole space. A reference read at
63
+ # the wrong moment contradicts every correct answer exactly as loudly
64
+ # as a wrong one. Eighteen recorded refusals rested on it.
65
+ #
66
+ # The defect had the shape of a PATH, not of a dtype: bf16 was merely
67
+ # the only traffic on it. So the raw path is gone rather than repaired,
68
+ # and a dtype routed here later cannot inherit it. Removing it also
69
+ # removes the second failure mode `string_at` carries -- it hands its
70
+ # size to `PyBytes_FromStringAndSize` as a C int, so any buffer of
71
+ # 2 GiB or more returns "Negative size", confirmed live on this machine.
72
+ host = t.to_cpu() if getattr(t, "_device", "cpu") != "cpu" else t
73
+ if getattr(t, "_dtype", None) == NBXDtype.bfloat16:
74
+ # numpy has no bf16; the bits are the top half of an fp32 and
75
+ # travel in a uint16 container.
76
+ bits = np.asarray(host.numpy()).view(np.uint16).astype(np.uint32)
77
+ return ((bits << np.uint32(16)).view(np.float32)
78
+ .reshape(tuple(t.shape)).astype(np.float64))
79
+ return np.asarray(host.numpy(), dtype=np.float64)
80
+ except Exception: # noqa: BLE001
81
+ return None
82
+
83
+
84
+ def _mm(named: Dict[str, Any], rows: Optional[tuple] = None) -> Optional[np.ndarray]:
85
+ """The fp64 reference for `mm`/`addmm`, optionally on a ROW WINDOW only.
86
+
87
+ `rows=(r0, r1)` computes `a[r0:r1] @ b` instead of the whole product. That is the rack's
88
+ row-windowed oracle technique (autotune_certify.RowWindowedOracle), brought to the screen
89
+ so a shape over the screening budget is verified on named windows instead of not at all.
90
+ A whole fp64 reference for a 4 194 304 x 540 output is 18 GB; three row windows of it are
91
+ a few megabytes, and the per-element comparison is identical on them."""
92
+ a_live = named.get("a_ptr")
93
+ if rows is not None:
94
+ # The rows are cut WHERE THE OPERAND LIVES, before it crosses. Cut after the read,
95
+ # the whole operand came to the host and was cast whole to float64 once per window
96
+ # (measured 2026-09-28: 4 096 MiB on the host for 64 rows of a 1 048 576 x 256 fp32
97
+ # operand; the certifier's footprint spiked by 3.7 GB per matmul key), so the window
98
+ # saved nothing where it was meant to. A device slice is a view whose strides no flat
99
+ # reader follows; it is made contiguous on the device first (`_materialise`'s rule).
100
+ r0, r1 = rows
101
+ if getattr(a_live, "_device", "cpu") != "cpu" and hasattr(a_live, "__getitem__"):
102
+ piece = a_live[r0:r1]
103
+ contiguous = getattr(piece, "contiguous", None)
104
+ a_live = contiguous() if callable(contiguous) else piece
105
+ a, b = _to_f64(a_live), _to_f64(named.get("b_ptr"))
106
+ if a is None or b is None:
107
+ return None
108
+ if rows is not None and a.shape[0] != (r1 - r0):
109
+ a = a[r0:r1] # a host operand: cut after the read
110
+ out = a @ b
111
+ bias = named.get("bias_ptr")
112
+ if bias is not None:
113
+ bv = _to_f64(bias)
114
+ if bv is None:
115
+ return None
116
+ alpha = float(named.get("alpha", 1.0) or 1.0)
117
+ beta = float(named.get("beta", 1.0) or 1.0)
118
+ if bv.ndim == 2 and rows is not None and bv.shape[0] != out.shape[0]:
119
+ bv = bv[r0:r1] # a per-row bias follows the window
120
+ out = alpha * out + beta * (bv[None, :] if bv.ndim == 1 else bv)
121
+ return out
122
+
123
+
124
+ def _baddbmm(named: Dict[str, Any]) -> Optional[np.ndarray]:
125
+ a, b = _to_f64(named.get("A_ptr")), _to_f64(named.get("B_ptr"))
126
+ if a is None or b is None:
127
+ return None
128
+ out = a @ b
129
+ alpha = float(named.get("alpha", 1.0) or 1.0)
130
+ beta = float(named.get("beta", 1.0) or 1.0)
131
+ out = alpha * out
132
+ if named.get("HAS_BIAS") and named.get("bias_ptr") is not None:
133
+ bv = _to_f64(named["bias_ptr"])
134
+ if bv is None:
135
+ return None
136
+ out = out + beta * bv
137
+ return out
138
+
139
+
140
+ #: kernel short name -> (reference for its OUTPUT from live args, output arg).
141
+ #: A kernel absent from here has no oracle and the screen says so out loud.
142
+ #:
143
+ #: The OUTPUT ARGUMENT NAME is not decoration. The first version of this
144
+ #: provider matched the output buffer by BYTE LENGTH, and for a matmul at
145
+ #: (19, 2048, 2048) the operand `a` and the output `c` are both 19x2048 fp32 —
146
+ #: the same 155648 bytes. The oracle was therefore placed on `a`, an INPUT, so
147
+ #: every candidate "disagreed" with it and the screen refused all ten
148
+ #: candidates of a shape whose certified deviation is 1.7e-06.
149
+ #:
150
+ #: An oracle that refuses correct configurations is worse than no oracle: it
151
+ #: turns a silent wrong into a loud stop on healthy work, and it would have
152
+ #: been believed because a refusal reads as vigilance. Matched by ADDRESS now.
153
+ ORACLES = {
154
+ "matmul_kernel": (_mm, "c_ptr"),
155
+ "addmm_kernel": (_mm, "c_ptr"),
156
+ "baddbmm_kernel": (_baddbmm, "out_ptr"),}
157
+
158
+ # The convolution family — the 11.5 % the table above did not cover (owed-proofs
159
+ # item 3: 822 of 7 158 keys on this rack). Its reference lives in its own module
160
+ # with its own tests against torch at 1e-12; until 2026-09-13 that module's
161
+ # table was never joined to THIS one, so the live screen kept announcing "no
162
+ # oracle for this kernel" on every conv key while the docstring next door said
163
+ # the family was covered. Register entry 46.
164
+ from nbxtensor.ops.oracles import conv2d_fp64 as _conv # noqa: E402
165
+
166
+ ORACLES.update({
167
+ name: ((lambda named, _fn=fn: _fn(named, _to_f64)), out_name)
168
+ for name, (fn, out_name) in _conv.ORACLES.items()
169
+ })
170
+
171
+
172
+ #: Kernels whose oracle can be computed on a ROW WINDOW of the output — the output read as
173
+ #: `[prod(leading dims), last dim]`, which for the matrix kernels is the matrix and for the
174
+ #: convolution family is `[N*Cout*Ho, Wo]`. The convolution rows map to input rows through the
175
+ #: receptive field (`conv2d_fp64.receptive_slab`, the certifier's arithmetic since 2026-09-07);
176
+ #: until 2026-09-26 the family was absent here and an over-budget conv key fell to windowed
177
+ #: CONSENSUS or to no screen at all, while an under-budget one read its WHOLE input in float64
178
+ #: (a 128-channel 2048x1024 input: 2.1 GB, the Mac's 27.5 GB footprint). A kernel absent from
179
+ #: this set falls back to windowed consensus, announced, rather than to nothing.
180
+ ROW_WINDOWABLE = {"matmul_kernel", "addmm_kernel"} | set(_conv.ROW_ORACLES)
181
+
182
+
183
+ def _slab_reader(tensor, shape):
184
+ """Read `[n0:n1, :, u0:u1, v0:v1]` of a contiguous NCHW device tensor to the host in float64
185
+ — ONLY that slab crosses, cut where the tensor lives. `shape` is the `[N, C, H, W]` the
186
+ kernel's named extents declare; the live argument may be flat."""
187
+ def slab(n0, n1, u0, u1, v0, v1):
188
+ view = tensor.view(*shape) if tuple(tensor.shape) != tuple(shape) else tensor
189
+ piece = view[n0:n1, :, u0:u1, v0:v1].contiguous()
190
+ return _to_f64(piece)
191
+ return slab
192
+
193
+
194
+ def oracle_row_bytes(tuner, meta) -> Optional[int]:
195
+ """What one flat output row costs THIS kernel's float64 reference on the host, or None for
196
+ a kernel the row table does not window (the default: the row's own elements in float64).
197
+ Raises `ValueError` for a kernel the table windows whose cost cannot be formed — the
198
+ launcher then seats the key unscreened and says why, rather than sizing the window to the
199
+ output row."""
200
+ name = getattr(getattr(tuner, "base_fn", None), "__name__", "") or ""
201
+ named = {**dict(getattr(tuner, "nargs", None) or {}), **dict(meta or {})}
202
+ return _conv.oracle_row_bytes(name, named)
203
+
204
+
205
+ def fp64_footprint(buffers) -> int:
206
+ """The host bytes a FULL reference would hold for these device buffers: every element in
207
+ float64, whatever it is on the device. The screening budget is a rule about cost, and the
208
+ oracle's cost is this number, not the buffers' device bytes — a 537 MB bf16 input is 2.1 GB
209
+ of float64 before the first tap is computed. The element size comes from `NBXDtype`, the
210
+ one authority (`_writable_buffers` records `dtype.name`, the enum's own name); a name the
211
+ enum does not know is a refusal, never a guess."""
212
+ from nbxtensor.dtype.nbx_dtype import NBXDtype, dtype_size, parse_dtype
213
+ total = 0
214
+ for _addr, nbytes, dtype in buffers:
215
+ # `_writable_buffers` records `value.dtype.name`, and `NBXTensor.dtype` is the TRITON
216
+ # dtype (`fp16`, `bf16`, `fp32`, ...) — the engine's own parser knows those spellings
217
+ # beside the enum's; anything neither knows is refused, never guessed.
218
+ name = str(dtype)
219
+ try:
220
+ nbx = NBXDtype[name] if name in NBXDtype.__members__ else parse_dtype(name)
221
+ except (KeyError, ValueError):
222
+ raise ValueError(f"the screen cannot size a buffer of dtype {dtype!r}: not an NBXDtype") from None
223
+ total += int(nbytes) * 8 // dtype_size(nbx)
224
+ return total
225
+
226
+
227
+ def windowed_reference(tuner, meta, rows) -> Optional[np.ndarray]:
228
+ """The fp64 reference for flat `rows` of the output, or None if this kernel cannot be windowed.
229
+
230
+ Returns the ARRAY, not bytes: the launcher slices the candidates' own bytes to the same
231
+ rows and compares, so both sides are the same rows of the same tensor. A refusal by a
232
+ row oracle is recorded through `set_last_refusal`, so the launcher's seat line can say
233
+ "the oracle refused, and why" instead of "no oracle covers this kernel"."""
234
+ name = getattr(getattr(tuner, "base_fn", None), "__name__", "") or ""
235
+ if name not in ROW_WINDOWABLE:
236
+ return None
237
+ named = {**dict(getattr(tuner, "nargs", None) or {}), **dict(meta or {})}
238
+ if not named:
239
+ return None
240
+ entry = _conv.ROW_ORACLES.get(name)
241
+ if entry is None:
242
+ try:
243
+ return _mm(named, rows=rows)
244
+ except Exception: # noqa: BLE001
245
+ return None
246
+ try:
247
+ x, w = named.get(entry.input_name), named.get(entry.weight_name)
248
+ if x is None or w is None:
249
+ raise ValueError(f"its arguments {entry.input_name!r}/{entry.weight_name!r} are not among the live arguments")
250
+ weight = _to_f64(w)
251
+ if weight is None:
252
+ raise ValueError("its weight could not be read here")
253
+ return entry.rows(named, _slab_reader(x, entry.input_shape(named)), weight, rows)
254
+ except (KeyError, TypeError, ValueError) as exc:
255
+ set_last_refusal(f"{name}: the row-windowed oracle refused — {exc}")
256
+ return None
257
+
258
+
259
+ def _span_bytes(logical, tensor, nbytes: int) -> Optional[bytes]:
260
+ """`logical` (the tensor's elements in row-major order) laid out as the `nbytes` span the screen snapshots from
261
+ the tensor's `data_ptr()`, or None when they cannot be the same buffer.
262
+
263
+ The screen compares a candidate's effect on the PHYSICAL span of every buffer (`_writable_buffers` keeps a dense
264
+ permutation, a conv input read NHWC as NCHW, and a stride-0 broadcast). A reference in logical order is that span
265
+ only for a contiguous tensor: for a permuted fp32 conv input it is the same elements in another order, every
266
+ candidate "changed" the input, and the screen refused the whole space of a correct kernel (2026-10-29)."""
267
+ stride = getattr(tensor, "stride", None)
268
+ item = logical.dtype.itemsize
269
+ if (not callable(stride) or getattr(tensor, "is_contiguous", lambda: True)()
270
+ or logical.ndim == 0):
271
+ return logical.tobytes() if logical.nbytes == nbytes else None
272
+ if nbytes % item:
273
+ return None
274
+ steps = tuple(int(s) for s in stride())
275
+ if any(s < 0 for s in steps):
276
+ return None
277
+ reach = sum((int(n) - 1) * s for n, s in zip(logical.shape, steps)) + 1 if logical.size else 0
278
+ if reach * item != nbytes:
279
+ return None
280
+ span = np.zeros(reach, dtype=logical.dtype)
281
+ np.lib.stride_tricks.as_strided(span, shape=logical.shape, strides=tuple(s * item for s in steps))[...] = logical
282
+ return span.tobytes()
283
+
284
+
285
+ def provider(tuner, key, buffers, meta=None) -> Optional[List[bytes]]:
286
+ """The correct contents of every screened buffer, or None.
287
+
288
+ The screen snapshots EVERY writable buffer, not just the output — four of
289
+ them for `addmm` (`a`, `b`, `bias`, `c`). The correct content of an INPUT
290
+ after the kernel is its content unchanged; only the output has an oracle.
291
+ Returning the oracle for all of them compares an input to an output.
292
+ """
293
+
294
+ name = getattr(getattr(tuner, "base_fn", None), "__name__", "") or ""
295
+ entry = ORACLES.get(name)
296
+ if entry is None:
297
+ announce_no_oracle(name or str(tuner), key)
298
+ return None
299
+ fn, out_name = entry
300
+ # Positional arguments from the autotuner, constexpr arguments from the
301
+ # launch kwargs: an oracle that needs `kernel_height` finds it only here.
302
+ named = {**dict(getattr(tuner, "nargs", None) or {}), **dict(meta or {})}
303
+ if not named:
304
+ return None
305
+ out_tensor = named.get(out_name)
306
+ out_addr = int(out_tensor.data_ptr()) if out_tensor is not None else None
307
+ if out_addr is None:
308
+ announce_no_oracle(name, key,
309
+ why=f"its output argument {out_name!r} is not among "
310
+ f"the live arguments")
311
+ return None
312
+ try:
313
+ import time as _time
314
+ _t0 = _time.perf_counter()
315
+ reference = fn(named)
316
+ # The oracle's own CPU wall time is the one number measured for this
317
+ # key BEFORE any candidate runs, so it is the bootstrap base for the
318
+ # first candidate's time budget: a GPU configuration slower than the
319
+ # single-threaded float64 CPU computation of the same mathematics is
320
+ # not a configuration, whatever else it is.
321
+ record_oracle_ms(key, (_time.perf_counter() - _t0) * 1e3)
322
+ except Exception: # noqa: BLE001
323
+ reference = None
324
+ if reference is None:
325
+ announce_no_oracle(name, key, why="its operands could not be read here")
326
+ return None
327
+
328
+ # A reference built from non-finite operands vouches for nothing. NaN
329
+ # compares unequal to everything including itself, so every candidate
330
+ # "disagrees" and the screen either refuses the whole space or — worse, when
331
+ # the deviation is computed on bf16 bits — lets a wrong configuration
332
+ # through wearing a `screened: true` stamp. Measured on swin2SR (M4 Pro,
333
+ # 2026-09-17): a conv whose input carried 63181 NaN and 356 Inf produced
334
+ # "the fp64 oracle contradicts EVERY candidate (18 of 18)".
335
+ #
336
+ # Refusing here routes the key through `_seat_unscreened`, which records it
337
+ # `screened: false` with this reason and keeps it out of the certified
338
+ # directory. The engine still runs; it just stops claiming the run was
339
+ # validated.
340
+ bad = int(np.count_nonzero(~np.isfinite(reference)))
341
+ if bad:
342
+ set_last_refusal(
343
+ f"the fp64 reference is not finite ({bad} of {reference.size} "
344
+ f"elements NaN or Inf), so it cannot adjudicate any candidate — "
345
+ f"the operands read for this key were themselves not finite")
346
+ announce_no_oracle(name, key, why=last_refusal())
347
+ return None
348
+
349
+ # Every live tensor by its address, so an INPUT is read through the copy
350
+ # path like everything else. The line this replaces read the device
351
+ # pointer with `ctypes.string_at` and justified it as "an input,
352
+ # unchanged" -- an assumption this repository's own measurement destroyed
353
+ # the same day: the bf16 operand of eighteen refusals was the BIAS, an
354
+ # input produced by a conversion kernel earlier in the graph. An input can
355
+ # be exactly as stale as an output, and "unchanged" says nothing about
356
+ # WHEN it was written.
357
+ #
358
+ # The size failure mode does not even need that argument: `string_at`
359
+ # hands its length to `PyBytes_FromStringAndSize` as a C int, so any
360
+ # buffer of 2 GiB or more returns "Negative size" whoever wrote it --
361
+ # confirmed live here at 2 GiB + 1 -- and a matmul input passes 2 GiB
362
+ # without difficulty on the shapes that matter.
363
+ by_addr = {}
364
+ for _v in named.values():
365
+ try:
366
+ by_addr[int(_v.data_ptr())] = _v
367
+ except Exception: # noqa: BLE001
368
+ continue
369
+
370
+ out: List[bytes] = []
371
+ for addr, nbytes, dtype_name in buffers:
372
+ if int(addr) == out_addr: # the output, BY ADDRESS
373
+ if dtype_name in ("bf16", "bfloat16"):
374
+ # bfloat16 is not a numpy dtype, so `_NP.get` fell through to
375
+ # fp32 -- and the reference then measured 4 bytes/element while
376
+ # the bf16 output buffer is 2, so `want.nbytes` was exactly
377
+ # double and the oracle was DISCARDED on every bf16 output.
378
+ # Measured 2026-09-14: conv2d at (1,180,448,448) bf16 --
379
+ # reference 144506880 vs buffer 72253440 -- so the whole conv
380
+ # family (and any bf16-output kernel) sat on the bare vote while
381
+ # the fp64 oracle was wired and computing. The output holds the
382
+ # top 16 bits of fp32; round the reference to bf16 the same way
383
+ # (`f32_to_bf16_bits`, round-to-nearest-even) so it compares in
384
+ # the buffer's own width. `_deviation` decodes bf16 bytes, so
385
+ # the tolerance comparison is unchanged. A dtype fix, not a
386
+ # backend one.
387
+ from nbxtensor.dtype.convert import f32_to_bf16_bits
388
+ want = np.ascontiguousarray(
389
+ f32_to_bf16_bits(np.ascontiguousarray(reference, dtype=np.float32)))
390
+ else:
391
+ want = np.ascontiguousarray(
392
+ reference.astype(_NP.get(dtype_name, np.float32)))
393
+ if want.size == int(np.prod(getattr(out_tensor, "shape", (want.size,)))):
394
+ want = want.reshape(tuple(out_tensor.shape))
395
+ raw = _span_bytes(want, out_tensor, int(nbytes))
396
+ if raw is None:
397
+ announce_no_oracle(
398
+ name, key,
399
+ why=f"the reference is {want.nbytes} bytes and the output "
400
+ f"buffer is {nbytes}")
401
+ return None
402
+ out.append(raw)
403
+ else:
404
+ # An input, unchanged -- read through the tensor's own copy to the
405
+ # host, which crosses the barrier a raw pointer read does not.
406
+ src = by_addr.get(int(addr))
407
+ if src is None:
408
+ announce_no_oracle(
409
+ name, key,
410
+ why=f"an input buffer at {addr:#x} is not among the live "
411
+ f"arguments, so it can only be read by raw pointer, "
412
+ f"which crosses no barrier and caps at 2 GiB")
413
+ return None
414
+ host = src.to_cpu() if getattr(src, "_device", "cpu") != "cpu" else src
415
+ logical = np.ascontiguousarray(host.numpy())
416
+ raw = _span_bytes(logical, src, int(nbytes))
417
+ if raw is None:
418
+ announce_no_oracle(
419
+ name, key,
420
+ why=f"the input at {addr:#x} copies to {logical.nbytes} bytes "
421
+ f"and the buffer is {nbytes}")
422
+ return None
423
+ out.append(raw)
424
+ return out
425
+
426
+
427
+ #: Oracle CPU wall time by key text, for the sweep's time budget. In-process,
428
+ #: like `_SCREEN_CACHE`: the budget protects a sweep that runs in this very
429
+ #: process, so persisting these would only let a stale machine state speak.
430
+ _ORACLE_MS: dict = {}
431
+
432
+
433
+ #: Why the oracle last declined, so the record can say it instead of "no
434
+ #: reference". Set immediately before returning None; read by the launcher when
435
+ #: it stamps the key unscreened.
436
+ _LAST_REFUSAL: Optional[str] = None
437
+
438
+
439
+ def set_last_refusal(why: str) -> None:
440
+ global _LAST_REFUSAL
441
+ _LAST_REFUSAL = why
442
+
443
+
444
+ def last_refusal() -> Optional[str]:
445
+ return _LAST_REFUSAL
446
+
447
+
448
+ def record_oracle_ms(key, ms: float) -> None:
449
+ _ORACLE_MS[str(key)] = float(ms)
450
+
451
+
452
+ def oracle_ms_of(key):
453
+ """The oracle's measured CPU time for this key, or None if it never ran."""
454
+ return _ORACLE_MS.get(str(key))
455
+
456
+
457
+ def announce_no_oracle(kernel_name: str, key, why: str = "no oracle is registered "
458
+ "for this kernel") -> None:
459
+ """Say, once per process, that a screen ran on a consensus alone.
460
+
461
+ A mechanism that is complete and switched off is the most expensive form of
462
+ a vacuous guard: it costs the price of writing it and returns nothing. The
463
+ only thing worse is one that is silent about being off.
464
+ """
465
+ token = (kernel_name, str(key))
466
+ if token in _ANNOUNCED:
467
+ return
468
+ _ANNOUNCED.add(token)
469
+ print(f"[AUTOTUNE_ORACLE] {kernel_name}: screening at key {key} on the "
470
+ f"CONSENSUS ALONE — {why}. A consensus cannot see a defect that is "
471
+ f"in the backend's emission, because every candidate then shares it "
472
+ f"and the vote is unanimous (measured: addmm wrong by 1e9 with a "
473
+ f"unanimous vote, 2026-09-11).", flush=True)
474
+
475
+
476
+ def install() -> None:
477
+ """Make the screen consult this oracle."""
478
+ from nbxtensor.backend import launcher as L
479
+ L.set_screen_oracle(provider)
nbxtensor/ops/selu.py ADDED
@@ -0,0 +1,22 @@
1
+ """SELU — pure @triton.jit kernel."""
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+ @triton.jit
7
+ def selu_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
+ scale = 1.0507009873554804934193349852946
17
+ alpha = 1.6732632423543772848170429916717
18
+
19
+ x = tl.load(input_ptr + offset, mask=mask)
20
+ x_fp32 = x.to(tl.float32)
21
+ out = scale * (tl.maximum(0, x_fp32) + tl.minimum(0, alpha * (tl.exp(x_fp32) - 1.0)))
22
+ tl.store(output_ptr + offset, out, mask=mask)