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,228 @@
1
+ # The library's half of amd/cdna.yml: the keys nbxtensor reads (docs/nbxtensor/device_keys.txt),
2
+ # moved with their sources by tools/split_vendor_files.py. NeuroBrix's half stays in
3
+ # src/neurobrix/config/vendors/amd/cdna.yml; the engine reads the two merged.
4
+
5
+ architecture: cdna
6
+ compute_capability: "gfx908" # MI100
7
+
8
+ block_sizes:
9
+ # Default block size for simple kernels
10
+ default: 1024
11
+
12
+ # Batched Matrix Multiply configuration
13
+ bmm:
14
+ block_m: 64
15
+ block_n: 64
16
+ block_k: 16
17
+ num_warps: 4
18
+
19
+ # Convolution configuration
20
+ conv2d:
21
+ block_h: 16
22
+ block_w: 16
23
+ num_warps: 4
24
+
25
+ # Generic reduction block size
26
+ reduction: 1024
27
+ # M=1 dequant-GEMV occupancy rule — see nvidia/volta.yml for the
28
+ # full rationale (pinned parity BLOCK_N under-fills small-N grids;
29
+ # the wrapper halves BLOCK_N until the grid reaches min_programs).
30
+ # 240 = 2 waves x 120 CUs (MI100); validation_status: analytical.
31
+ # Key absent or 0 -> no adaptation.
32
+ dequant_gemv:
33
+ min_programs: 240
34
+
35
+ # Scaled Dot-Product Attention block size thresholds.
36
+ # Schema documented in volta.yml. Decode entries first.
37
+ # CDNA1/2 values conservative for the 64 KB SMEM budget. CDNA3
38
+ # (MI300) has 160 KB and could use larger tiles — when needed,
39
+ # split into cdna3.yml or extend with conditional blocks.
40
+ sdpa_thresholds:
41
+ # Decode path (seqlen_q ≤ 16)
42
+ - seqlen_q_le: 16
43
+ head_dim_ge: 256
44
+ block_m: 16
45
+ block_n: 16
46
+ num_warps: 4
47
+ - seqlen_q_le: 16
48
+ block_m: 16
49
+ block_n: 32
50
+ num_warps: 4
51
+ # Prefill path (seqlen_q > 16)
52
+ - head_dim_ge: 256
53
+ block_m: 16
54
+ block_n: 16
55
+ num_warps: 4
56
+ - head_dim_ge: 128
57
+ block_m: 32
58
+ block_n: 32
59
+ num_warps: 4
60
+ - head_dim_lt: 128
61
+ block_m: 64
62
+ block_n: 64
63
+ num_warps: 4
64
+
65
+ memory:
66
+ max_shared_memory_per_block: 65536 # 64 KB (CDNA1/2)
67
+ max_registers_per_block: 65536
68
+ # AMD schedules in 64-wide WAVEFRONTS where NVIDIA uses 32-wide warps.
69
+ # Named `warp_size` for schema uniformity, the same convention
70
+ # apple_silicon.yml follows for its SIMD groups: one hardware concept has
71
+ # ONE key across every profile, so a consumer never branches on vendor to
72
+ # find it. Declaring it as `wavefront_size` meant a reader asking for
73
+ # `memory.warp_size` got nothing on AMD and would fall back to 32 — wrong
74
+ # by 2x, silently, on every CDNA card.
75
+ warp_size: 64
76
+ # The registers ONE lane may address for ordinary (non-matrix) code: the 256 architectural VGPRs V0-V255; the
77
+ # 256 AccVGPRs beside them in the same file serve the matrix (MFMA) instructions and spills, not a tile's elements
78
+ # (AMD Instinct MI300 / CDNA3 ISA reference guide, "VGPRs": up to 512 per wave, 256 of each type; CDNA2 the same,
79
+ # ORNL CDNA2 memory-hierarchy slides). Read by ops/_configs.fits_thread_registers (elements a thread holds).
80
+ max_registers_per_thread: 256
81
+ # SDPA deterministic-routing budget (R10 schema parity with
82
+ # volta.yml). 0 = NOT APPLICABLE: the flash-attention
83
+ # non-determinism diagnosed in P-TRITON-MOE-DETERMINISM-RESIDUAL
84
+ # is an NVIDIA Volta-SIMT MMA issue. ROCm/HIP uses a different
85
+ # Triton backend and matrix-core path; the Volta race does not
86
+ # transfer. Left 0 (no routing) until/unless empirically shown
87
+ # otherwise on CDNA hardware. hand_curated_from_docs.
88
+ sdpa_math_max_scores_bytes: 0
89
+ # Row block (alignment and floor) of the chunked deterministic
90
+ # math prefill; the chunk-halving retry on a refused allocation
91
+ # never goes below it.
92
+ sdpa_math_min_chunk_rows: 128
93
+ # Allocator pool: bytes the free-list may keep PARKED per device as a
94
+ # fraction of that device's memory (2026-09-02, pool default-on gate).
95
+ # Beyond it the largest parked blocks go back to the driver, bounding
96
+ # the pool's contribution to the driver watermark (measured +3.4 GB on
97
+ # the xlong int4 row unbounded). 0 = unbounded.
98
+ alloc_pool_parked_cap_fraction: 0.50
99
+ precision:
100
+ # Attention operands that disagree in dtype (an fp16 GEMM stored fp32 feeding V) all take the
101
+ # narrowest of the three, the compiled engine's alignment: the half attention stays on the matrix
102
+ # unit (V100, 2026-10-08: 1.16 s/op aligned narrowest vs 22.0 s/op on the scalar flash aligned widest).
103
+ attention_operands: narrowest
104
+ # Whether each engine branch's OWN kernels compute float64 / complex128 elements, read with
105
+ # supports_fp64 (both must hold) -- a CAPABILITY: `compiled` is ATen's, which carries both wherever
106
+ # the device does; `triton` is the NeuroBrix Triton kernels' (cuda/hip lower double; Metal's
107
+ # lowering narrows it in silence, measured 2026-09-28 on the Sana 4K positional embedding). Read
108
+ # by the DtypeEngine (`config.device_supports_fp64`) and by the Triton wrappers' binding
109
+ # (`triton.dtype.triton_has_fp64` -> `nbx_tensor.set_backend_has_fp64`).
110
+ kernels_carry_fp64:
111
+ compiled: true
112
+ triton: true
113
+ # Software-pipelining budget — see nvidia/volta.yml for the schema.
114
+ #
115
+ # validation_status: conservative_pending_first_light. cp.async is a
116
+ # PTX instruction and does not exist on CDNA; Triton's AMD backend
117
+ # pipelines through LDS by a different mechanism, so Volta's measured
118
+ # fault does not transfer and neither does Ampere's clearance. Until an
119
+ # MI-series card measures it, the cap is 2: clamping can only cost
120
+ # throughput, while allowing unvalidated pipelining could cost
121
+ # correctness. Raising this is a first-light task
122
+ # (docs/internal/amd_first_light.md), not a guess to make from here.
123
+ pipelining:
124
+ max_num_stages: 2
125
+
126
+ # Autotune correctness screen. The engine runs every candidate config once and
127
+ # compares its result against a reference config's before timing any of them,
128
+ # because an autotuner that ranks on speed alone selects whichever WRONG
129
+ # kernel is fastest — a kernel that writes half its output does half the
130
+ # stores and wins. Measured on Apple 2026-09-07: fp16 mm [64,32]@[32,64] chose
131
+ # a config that left half the columns zero.
132
+ #
133
+ # These are the tolerances that separate "a different but valid summation
134
+ # order" from "a different answer". Two configs with different block sizes
135
+ # reduce in a different order, so their results differ in the last bits; a
136
+ # config that drops output differs by the scale of the output itself. The
137
+ # gap between those two is several orders of magnitude, and these sit in it.
138
+ #
139
+ # Relative to the reference's own magnitude: max|a - b| / max|b|. Integer
140
+ # and boolean results are compared BIT-IDENTICALLY and ignore this table —
141
+ # there is no valid reordering that changes an integer.
142
+ autotune_screen_rtol:
143
+ float16: 2.0e-2
144
+ bfloat16: 4.0e-2
145
+ float32: 1.0e-4
146
+ float64: 1.0e-8
147
+ int64: 0.0 # an integer result (the MoE alignment's routing tables) is met exactly
148
+
149
+ # Above this many bytes of buffer, the autotune correctness screen does not
150
+ # run. Screening copies every argument out and back once per candidate, so a
151
+ # very large tensor turns a tuning step into hundreds of megabytes of traffic
152
+ # — and on unified memory that pressure is the machine's, not a card's.
153
+ # MEASURED 2026-09-07: unbounded screening of a 151936-wide softmax perturbed
154
+ # six unrelated tests in the same process. A skipped screen is announced, not
155
+ # silent.
156
+ autotune_screen_max_bytes: 33554432
157
+
158
+ autotune:
159
+ buckets:
160
+ # elements — an element-wise launch's element count (`kernels/ops/elementwise_launch.py`), NEVER the `default`
161
+ # dimension ladder (`autotune_bucket.ladder_for` refuses it). NOT measured on this architecture (no such device on
162
+ # either machine): the four classes measured on V100-SXM2 2026-10-23 (nvidia/volta.yml, launch-bound under 65 536
163
+ # elements, bandwidth classes above) and confirmed on apple_m4_pro 2026-10-24 — the measurement on this
164
+ # architecture is owed (docs/reference/owed-proofs.md, "element-wise ladder per architecture").
165
+ elements:
166
+ - {up_to: 65536, step: 65536}
167
+ - {up_to: 1048576, step: 1048576}
168
+ - {up_to: 16777216, step: 16777216}
169
+ - {up_to: null, step: 68719476736}
170
+ default:
171
+ - {up_to: 64, step: 1}
172
+ - {up_to: 256, step: 16}
173
+ - {up_to: 1024, step: 32}
174
+ - {up_to: 8192, step: 128}
175
+ # Above 8 192 a QUARTER-OCTAVE, not a 512-step. The 512 tail was decided by a sweep
176
+ # that ran to about 4 096 and never met a request-scale dimension: a vocoder's batched
177
+ # GEMM keys on the WAVEFORM and reaches 1 963 520, which a 512-step cuts into some four
178
+ # thousand buckets — 1 400 of one model's 1 522 distinct M values sat above 8 192.
179
+ # Measured 2026-09-22 on both classes, two shapes (the vocoder's B=1,N=1,K=9 and a
180
+ # GEMM at N=K=512), each octave bucket carrying three or four measured values with its
181
+ # TOP as representative: 0.0 % median loss, 0.2 % max at ONE octave bucket. The rows
182
+ # below are finer than the octave that was measured, so they cost no more than it did.
183
+ # The first three octaves above the knee keep a NARROW step. Measured directly on the
184
+ # rows as shipped (the upscalers' N=360, K=180; three sizes inside each bucket with
185
+ # its TOP among them, 2026-09-22): a quarter-octave there cost 0.0 % median but
186
+ # **5.2 %** at the 10 240 bucket and 1.2 % at 16 384 — the loss lives just above the
187
+ # knee, where a quarter of an OCTAVE is still a quarter of the VALUE. Beyond 65 536
188
+ # the same sweep measured 0.0 % median and at most 0.6 %, so the quarter-octave stands.
189
+ # The convolution-width ladder below keeps its quarter-octave: its own sweep measured
190
+ # 0.0 % median AND max there, on both classes and two channel counts.
191
+ - {up_to: 16384, step: 512}
192
+ - {up_to: 32768, step: 1024}
193
+ - {up_to: 65536, step: 2048}
194
+ - {up_to: 131072, step: 16384}
195
+ - {up_to: 262144, step: 32768}
196
+ - {up_to: 524288, step: 65536}
197
+ - {up_to: 1048576, step: 131072}
198
+ - {up_to: 2097152, step: 262144}
199
+ - {up_to: null, step: 524288}
200
+ # The width of a ONE-ROW convolution (a 1-D convolution over a sequence: a vocoder's
201
+ # samples, a mel spectrogram's frames) is the request's length, unbounded by any
202
+ # resolution — chatterbox's vocoder reaches 444 721 samples for 18 s of speech. Above the
203
+ # GEMM ladder it steps by a quarter-octave (≤ 25 % of the value), so a census meets every
204
+ # class of a speech length in ~100 runs instead of ~1 000; the loss of that step is owed a
205
+ # measurement on both classes (bucket_loss.py) before the ladder is called final.
206
+ W:
207
+ - {up_to: 64, step: 1}
208
+ - {up_to: 256, step: 16}
209
+ - {up_to: 1024, step: 32}
210
+ - {up_to: 8192, step: 128}
211
+ - {up_to: 16384, step: 2048}
212
+ - {up_to: 32768, step: 4096}
213
+ - {up_to: 65536, step: 8192}
214
+ - {up_to: 131072, step: 16384}
215
+ - {up_to: 262144, step: 32768}
216
+ - {up_to: 524288, step: 65536}
217
+ - {up_to: null, step: 131072}
218
+
219
+ # The flash kernel at a power-of-two head dim >= 128 is NOT measured on this architecture: the zero-pad
220
+ # detour stays (launch_keys.flash_headdim_detour). Declared, never left absent: true only where the
221
+ # correctness oracle was run with the detour off on this arch and stack (Volta, Triton 3.8, 2026-10-03).
222
+ flash:
223
+ pow2_head_dim_correct: false
224
+
225
+ # Convolution weight storage order (launch_keys.conv_weight_layout): KCRS, the container's own,
226
+ # until this arch measures KRSC (the M4 Pro measured +46-63 % on its 3x3 keys, 2026-10-07).
227
+ conv:
228
+ weight_layout: KCRS
@@ -0,0 +1,228 @@
1
+ # The library's half of amd/cdna2.yml: the keys nbxtensor reads (docs/nbxtensor/device_keys.txt),
2
+ # moved with their sources by tools/split_vendor_files.py. NeuroBrix's half stays in
3
+ # src/neurobrix/config/vendors/amd/cdna2.yml; the engine reads the two merged.
4
+
5
+ architecture: cdna2
6
+ compute_capability: "gfx90a" # MI210 / MI250 / MI250X
7
+
8
+ block_sizes:
9
+ # Default block size for simple kernels
10
+ default: 1024
11
+
12
+ # Batched Matrix Multiply configuration
13
+ bmm:
14
+ block_m: 64
15
+ block_n: 64
16
+ block_k: 16
17
+ num_warps: 4
18
+
19
+ # Convolution configuration
20
+ conv2d:
21
+ block_h: 16
22
+ block_w: 16
23
+ num_warps: 4
24
+
25
+ # Generic reduction block size
26
+ reduction: 1024
27
+ # M=1 dequant-GEMV occupancy rule — see nvidia/volta.yml for the
28
+ # full rationale (pinned parity BLOCK_N under-fills small-N grids;
29
+ # the wrapper halves BLOCK_N until the grid reaches min_programs).
30
+ # 220 = 2 waves x 110 CUs (one MI250X GCD); validation_status: analytical.
31
+ # Key absent or 0 -> no adaptation.
32
+ dequant_gemv:
33
+ min_programs: 220
34
+
35
+ # Scaled Dot-Product Attention block size thresholds.
36
+ # Schema documented in volta.yml. Decode entries first.
37
+ # CDNA1/2 values conservative for the 64 KB SMEM budget. CDNA3
38
+ # (MI300) has 160 KB and could use larger tiles — when needed,
39
+ # split into cdna3.yml or extend with conditional blocks.
40
+ sdpa_thresholds:
41
+ # Decode path (seqlen_q ≤ 16)
42
+ - seqlen_q_le: 16
43
+ head_dim_ge: 256
44
+ block_m: 16
45
+ block_n: 16
46
+ num_warps: 4
47
+ - seqlen_q_le: 16
48
+ block_m: 16
49
+ block_n: 32
50
+ num_warps: 4
51
+ # Prefill path (seqlen_q > 16)
52
+ - head_dim_ge: 256
53
+ block_m: 16
54
+ block_n: 16
55
+ num_warps: 4
56
+ - head_dim_ge: 128
57
+ block_m: 32
58
+ block_n: 32
59
+ num_warps: 4
60
+ - head_dim_lt: 128
61
+ block_m: 64
62
+ block_n: 64
63
+ num_warps: 4
64
+
65
+ memory:
66
+ max_shared_memory_per_block: 65536 # 64 KB (CDNA1/2)
67
+ max_registers_per_block: 65536
68
+ # AMD schedules in 64-wide WAVEFRONTS where NVIDIA uses 32-wide warps.
69
+ # Named `warp_size` for schema uniformity, the same convention
70
+ # apple_silicon.yml follows for its SIMD groups: one hardware concept has
71
+ # ONE key across every profile, so a consumer never branches on vendor to
72
+ # find it. Declaring it as `wavefront_size` meant a reader asking for
73
+ # `memory.warp_size` got nothing on AMD and would fall back to 32 — wrong
74
+ # by 2x, silently, on every CDNA card.
75
+ warp_size: 64
76
+ # The registers ONE lane may address for ordinary (non-matrix) code: the 256 architectural VGPRs V0-V255; the
77
+ # 256 AccVGPRs beside them in the same file serve the matrix (MFMA) instructions and spills, not a tile's elements
78
+ # (AMD Instinct MI300 / CDNA3 ISA reference guide, "VGPRs": up to 512 per wave, 256 of each type; CDNA2 the same,
79
+ # ORNL CDNA2 memory-hierarchy slides). Read by ops/_configs.fits_thread_registers (elements a thread holds).
80
+ max_registers_per_thread: 256
81
+ # SDPA deterministic-routing budget (R10 schema parity with
82
+ # volta.yml). 0 = NOT APPLICABLE: the flash-attention
83
+ # non-determinism diagnosed in P-TRITON-MOE-DETERMINISM-RESIDUAL
84
+ # is an NVIDIA Volta-SIMT MMA issue. ROCm/HIP uses a different
85
+ # Triton backend and matrix-core path; the Volta race does not
86
+ # transfer. Left 0 (no routing) until/unless empirically shown
87
+ # otherwise on CDNA hardware. hand_curated_from_docs.
88
+ sdpa_math_max_scores_bytes: 0
89
+ # Row block (alignment and floor) of the chunked deterministic
90
+ # math prefill; the chunk-halving retry on a refused allocation
91
+ # never goes below it.
92
+ sdpa_math_min_chunk_rows: 128
93
+ # Allocator pool: bytes the free-list may keep PARKED per device as a
94
+ # fraction of that device's memory (2026-09-02, pool default-on gate).
95
+ # Beyond it the largest parked blocks go back to the driver, bounding
96
+ # the pool's contribution to the driver watermark (measured +3.4 GB on
97
+ # the xlong int4 row unbounded). 0 = unbounded.
98
+ alloc_pool_parked_cap_fraction: 0.50
99
+ precision:
100
+ # Attention operands that disagree in dtype (an fp16 GEMM stored fp32 feeding V) all take the
101
+ # narrowest of the three, the compiled engine's alignment: the half attention stays on the matrix
102
+ # unit (V100, 2026-10-08: 1.16 s/op aligned narrowest vs 22.0 s/op on the scalar flash aligned widest).
103
+ attention_operands: narrowest
104
+ # Whether each engine branch's OWN kernels compute float64 / complex128 elements, read with
105
+ # supports_fp64 (both must hold) -- a CAPABILITY: `compiled` is ATen's, which carries both wherever
106
+ # the device does; `triton` is the NeuroBrix Triton kernels' (cuda/hip lower double; Metal's
107
+ # lowering narrows it in silence, measured 2026-09-28 on the Sana 4K positional embedding). Read
108
+ # by the DtypeEngine (`config.device_supports_fp64`) and by the Triton wrappers' binding
109
+ # (`triton.dtype.triton_has_fp64` -> `nbx_tensor.set_backend_has_fp64`).
110
+ kernels_carry_fp64:
111
+ compiled: true
112
+ triton: true
113
+ # Software-pipelining budget — see nvidia/volta.yml for the schema.
114
+ #
115
+ # validation_status: conservative_pending_first_light. cp.async is a
116
+ # PTX instruction and does not exist on CDNA; Triton's AMD backend
117
+ # pipelines through LDS by a different mechanism, so Volta's measured
118
+ # fault does not transfer and neither does Ampere's clearance. Until an
119
+ # MI-series card measures it, the cap is 2: clamping can only cost
120
+ # throughput, while allowing unvalidated pipelining could cost
121
+ # correctness. Raising this is a first-light task
122
+ # (docs/internal/amd_first_light.md), not a guess to make from here.
123
+ pipelining:
124
+ max_num_stages: 2
125
+
126
+ # Autotune correctness screen. The engine runs every candidate config once and
127
+ # compares its result against a reference config's before timing any of them,
128
+ # because an autotuner that ranks on speed alone selects whichever WRONG
129
+ # kernel is fastest — a kernel that writes half its output does half the
130
+ # stores and wins. Measured on Apple 2026-09-07: fp16 mm [64,32]@[32,64] chose
131
+ # a config that left half the columns zero.
132
+ #
133
+ # These are the tolerances that separate "a different but valid summation
134
+ # order" from "a different answer". Two configs with different block sizes
135
+ # reduce in a different order, so their results differ in the last bits; a
136
+ # config that drops output differs by the scale of the output itself. The
137
+ # gap between those two is several orders of magnitude, and these sit in it.
138
+ #
139
+ # Relative to the reference's own magnitude: max|a - b| / max|b|. Integer
140
+ # and boolean results are compared BIT-IDENTICALLY and ignore this table —
141
+ # there is no valid reordering that changes an integer.
142
+ autotune_screen_rtol:
143
+ float16: 2.0e-2
144
+ bfloat16: 4.0e-2
145
+ float32: 1.0e-4
146
+ float64: 1.0e-8
147
+ int64: 0.0 # an integer result (the MoE alignment's routing tables) is met exactly
148
+
149
+ # Above this many bytes of buffer, the autotune correctness screen does not
150
+ # run. Screening copies every argument out and back once per candidate, so a
151
+ # very large tensor turns a tuning step into hundreds of megabytes of traffic
152
+ # — and on unified memory that pressure is the machine's, not a card's.
153
+ # MEASURED 2026-09-07: unbounded screening of a 151936-wide softmax perturbed
154
+ # six unrelated tests in the same process. A skipped screen is announced, not
155
+ # silent.
156
+ autotune_screen_max_bytes: 33554432
157
+
158
+ autotune:
159
+ buckets:
160
+ # elements — an element-wise launch's element count (`kernels/ops/elementwise_launch.py`), NEVER the `default`
161
+ # dimension ladder (`autotune_bucket.ladder_for` refuses it). NOT measured on this architecture (no such device on
162
+ # either machine): the four classes measured on V100-SXM2 2026-10-23 (nvidia/volta.yml, launch-bound under 65 536
163
+ # elements, bandwidth classes above) and confirmed on apple_m4_pro 2026-10-24 — the measurement on this
164
+ # architecture is owed (docs/reference/owed-proofs.md, "element-wise ladder per architecture").
165
+ elements:
166
+ - {up_to: 65536, step: 65536}
167
+ - {up_to: 1048576, step: 1048576}
168
+ - {up_to: 16777216, step: 16777216}
169
+ - {up_to: null, step: 68719476736}
170
+ default:
171
+ - {up_to: 64, step: 1}
172
+ - {up_to: 256, step: 16}
173
+ - {up_to: 1024, step: 32}
174
+ - {up_to: 8192, step: 128}
175
+ # Above 8 192 a QUARTER-OCTAVE, not a 512-step. The 512 tail was decided by a sweep
176
+ # that ran to about 4 096 and never met a request-scale dimension: a vocoder's batched
177
+ # GEMM keys on the WAVEFORM and reaches 1 963 520, which a 512-step cuts into some four
178
+ # thousand buckets — 1 400 of one model's 1 522 distinct M values sat above 8 192.
179
+ # Measured 2026-09-22 on both classes, two shapes (the vocoder's B=1,N=1,K=9 and a
180
+ # GEMM at N=K=512), each octave bucket carrying three or four measured values with its
181
+ # TOP as representative: 0.0 % median loss, 0.2 % max at ONE octave bucket. The rows
182
+ # below are finer than the octave that was measured, so they cost no more than it did.
183
+ # The first three octaves above the knee keep a NARROW step. Measured directly on the
184
+ # rows as shipped (the upscalers' N=360, K=180; three sizes inside each bucket with
185
+ # its TOP among them, 2026-09-22): a quarter-octave there cost 0.0 % median but
186
+ # **5.2 %** at the 10 240 bucket and 1.2 % at 16 384 — the loss lives just above the
187
+ # knee, where a quarter of an OCTAVE is still a quarter of the VALUE. Beyond 65 536
188
+ # the same sweep measured 0.0 % median and at most 0.6 %, so the quarter-octave stands.
189
+ # The convolution-width ladder below keeps its quarter-octave: its own sweep measured
190
+ # 0.0 % median AND max there, on both classes and two channel counts.
191
+ - {up_to: 16384, step: 512}
192
+ - {up_to: 32768, step: 1024}
193
+ - {up_to: 65536, step: 2048}
194
+ - {up_to: 131072, step: 16384}
195
+ - {up_to: 262144, step: 32768}
196
+ - {up_to: 524288, step: 65536}
197
+ - {up_to: 1048576, step: 131072}
198
+ - {up_to: 2097152, step: 262144}
199
+ - {up_to: null, step: 524288}
200
+ # The width of a ONE-ROW convolution (a 1-D convolution over a sequence: a vocoder's
201
+ # samples, a mel spectrogram's frames) is the request's length, unbounded by any
202
+ # resolution — chatterbox's vocoder reaches 444 721 samples for 18 s of speech. Above the
203
+ # GEMM ladder it steps by a quarter-octave (≤ 25 % of the value), so a census meets every
204
+ # class of a speech length in ~100 runs instead of ~1 000; the loss of that step is owed a
205
+ # measurement on both classes (bucket_loss.py) before the ladder is called final.
206
+ W:
207
+ - {up_to: 64, step: 1}
208
+ - {up_to: 256, step: 16}
209
+ - {up_to: 1024, step: 32}
210
+ - {up_to: 8192, step: 128}
211
+ - {up_to: 16384, step: 2048}
212
+ - {up_to: 32768, step: 4096}
213
+ - {up_to: 65536, step: 8192}
214
+ - {up_to: 131072, step: 16384}
215
+ - {up_to: 262144, step: 32768}
216
+ - {up_to: 524288, step: 65536}
217
+ - {up_to: null, step: 131072}
218
+
219
+ # The flash kernel at a power-of-two head dim >= 128 is NOT measured on this architecture: the zero-pad
220
+ # detour stays (launch_keys.flash_headdim_detour). Declared, never left absent: true only where the
221
+ # correctness oracle was run with the detour off on this arch and stack (Volta, Triton 3.8, 2026-10-03).
222
+ flash:
223
+ pow2_head_dim_correct: false
224
+
225
+ # Convolution weight storage order (launch_keys.conv_weight_layout): KCRS, the container's own,
226
+ # until this arch measures KRSC (the M4 Pro measured +46-63 % on its 3x3 keys, 2026-10-07).
227
+ conv:
228
+ weight_layout: KCRS
@@ -0,0 +1,227 @@
1
+ # The library's half of amd/cdna3.yml: the keys nbxtensor reads (docs/nbxtensor/device_keys.txt),
2
+ # moved with their sources by tools/split_vendor_files.py. NeuroBrix's half stays in
3
+ # src/neurobrix/config/vendors/amd/cdna3.yml; the engine reads the two merged.
4
+
5
+ architecture: cdna3
6
+ compute_capability: "gfx942" # MI300X (MI300A = gfx940/gfx941)
7
+
8
+ block_sizes:
9
+ # Default block size for simple kernels
10
+ default: 1024
11
+
12
+ # Batched Matrix Multiply configuration
13
+ bmm:
14
+ block_m: 64
15
+ block_n: 64
16
+ block_k: 16
17
+ num_warps: 4
18
+
19
+ # Convolution configuration
20
+ conv2d:
21
+ block_h: 16
22
+ block_w: 16
23
+ num_warps: 4
24
+
25
+ # Generic reduction block size
26
+ reduction: 1024
27
+ # M=1 dequant-GEMV occupancy rule — see nvidia/volta.yml for the
28
+ # full rationale (pinned parity BLOCK_N under-fills small-N grids;
29
+ # the wrapper halves BLOCK_N until the grid reaches min_programs).
30
+ # 608 = 2 waves x 304 CUs (MI300X); validation_status: analytical.
31
+ # Key absent or 0 -> no adaptation.
32
+ dequant_gemv:
33
+ min_programs: 608
34
+
35
+ # Scaled Dot-Product Attention block size thresholds.
36
+ # Schema documented in volta.yml. Decode entries first.
37
+ # Values inherited from CDNA1/2 (conservative for 64 KB). MI300's
38
+ # 160 KB LDS allows larger tiles — unmeasured, see the memory note.
39
+ sdpa_thresholds:
40
+ # Decode path (seqlen_q ≤ 16)
41
+ - seqlen_q_le: 16
42
+ head_dim_ge: 256
43
+ block_m: 16
44
+ block_n: 16
45
+ num_warps: 4
46
+ - seqlen_q_le: 16
47
+ block_m: 16
48
+ block_n: 32
49
+ num_warps: 4
50
+ # Prefill path (seqlen_q > 16)
51
+ - head_dim_ge: 256
52
+ block_m: 16
53
+ block_n: 16
54
+ num_warps: 4
55
+ - head_dim_ge: 128
56
+ block_m: 32
57
+ block_n: 32
58
+ num_warps: 4
59
+ - head_dim_lt: 128
60
+ block_m: 64
61
+ block_n: 64
62
+ num_warps: 4
63
+
64
+ memory:
65
+ max_shared_memory_per_block: 163840 # 160 KB LDS per CU (CDNA3)
66
+ max_registers_per_block: 65536
67
+ # AMD schedules in 64-wide WAVEFRONTS where NVIDIA uses 32-wide warps.
68
+ # Named `warp_size` for schema uniformity, the same convention
69
+ # apple_silicon.yml follows for its SIMD groups: one hardware concept has
70
+ # ONE key across every profile, so a consumer never branches on vendor to
71
+ # find it. Declaring it as `wavefront_size` meant a reader asking for
72
+ # `memory.warp_size` got nothing on AMD and would fall back to 32 — wrong
73
+ # by 2x, silently, on every CDNA card.
74
+ warp_size: 64
75
+ # The registers ONE lane may address for ordinary (non-matrix) code: the 256 architectural VGPRs V0-V255; the
76
+ # 256 AccVGPRs beside them in the same file serve the matrix (MFMA) instructions and spills, not a tile's elements
77
+ # (AMD Instinct MI300 / CDNA3 ISA reference guide, "VGPRs": up to 512 per wave, 256 of each type; CDNA2 the same,
78
+ # ORNL CDNA2 memory-hierarchy slides). Read by ops/_configs.fits_thread_registers (elements a thread holds).
79
+ max_registers_per_thread: 256
80
+ # SDPA deterministic-routing budget (R10 schema parity with
81
+ # volta.yml). 0 = NOT APPLICABLE: the flash-attention
82
+ # non-determinism diagnosed in P-TRITON-MOE-DETERMINISM-RESIDUAL
83
+ # is an NVIDIA Volta-SIMT MMA issue. ROCm/HIP uses a different
84
+ # Triton backend and matrix-core path; the Volta race does not
85
+ # transfer. Left 0 (no routing) until/unless empirically shown
86
+ # otherwise on CDNA hardware. hand_curated_from_docs.
87
+ sdpa_math_max_scores_bytes: 0
88
+ # Row block (alignment and floor) of the chunked deterministic
89
+ # math prefill; the chunk-halving retry on a refused allocation
90
+ # never goes below it.
91
+ sdpa_math_min_chunk_rows: 128
92
+ # Allocator pool: bytes the free-list may keep PARKED per device as a
93
+ # fraction of that device's memory (2026-09-02, pool default-on gate).
94
+ # Beyond it the largest parked blocks go back to the driver, bounding
95
+ # the pool's contribution to the driver watermark (measured +3.4 GB on
96
+ # the xlong int4 row unbounded). 0 = unbounded.
97
+ alloc_pool_parked_cap_fraction: 0.50
98
+ precision:
99
+ # Attention operands that disagree in dtype (an fp16 GEMM stored fp32 feeding V) all take the
100
+ # narrowest of the three, the compiled engine's alignment: the half attention stays on the matrix
101
+ # unit (V100, 2026-10-08: 1.16 s/op aligned narrowest vs 22.0 s/op on the scalar flash aligned widest).
102
+ attention_operands: narrowest
103
+ # Whether each engine branch's OWN kernels compute float64 / complex128 elements, read with
104
+ # supports_fp64 (both must hold) -- a CAPABILITY: `compiled` is ATen's, which carries both wherever
105
+ # the device does; `triton` is the NeuroBrix Triton kernels' (cuda/hip lower double; Metal's
106
+ # lowering narrows it in silence, measured 2026-09-28 on the Sana 4K positional embedding). Read
107
+ # by the DtypeEngine (`config.device_supports_fp64`) and by the Triton wrappers' binding
108
+ # (`triton.dtype.triton_has_fp64` -> `nbx_tensor.set_backend_has_fp64`).
109
+ kernels_carry_fp64:
110
+ compiled: true
111
+ triton: true
112
+ # Software-pipelining budget — see nvidia/volta.yml for the schema.
113
+ #
114
+ # validation_status: conservative_pending_first_light. cp.async is a
115
+ # PTX instruction and does not exist on CDNA; Triton's AMD backend
116
+ # pipelines through LDS by a different mechanism, so Volta's measured
117
+ # fault does not transfer and neither does Ampere's clearance. Until an
118
+ # MI-series card measures it, the cap is 2: clamping can only cost
119
+ # throughput, while allowing unvalidated pipelining could cost
120
+ # correctness. Raising this is a first-light task
121
+ # (docs/internal/amd_first_light.md), not a guess to make from here.
122
+ pipelining:
123
+ max_num_stages: 2
124
+
125
+ # Autotune correctness screen. The engine runs every candidate config once and
126
+ # compares its result against a reference config's before timing any of them,
127
+ # because an autotuner that ranks on speed alone selects whichever WRONG
128
+ # kernel is fastest — a kernel that writes half its output does half the
129
+ # stores and wins. Measured on Apple 2026-09-07: fp16 mm [64,32]@[32,64] chose
130
+ # a config that left half the columns zero.
131
+ #
132
+ # These are the tolerances that separate "a different but valid summation
133
+ # order" from "a different answer". Two configs with different block sizes
134
+ # reduce in a different order, so their results differ in the last bits; a
135
+ # config that drops output differs by the scale of the output itself. The
136
+ # gap between those two is several orders of magnitude, and these sit in it.
137
+ #
138
+ # Relative to the reference's own magnitude: max|a - b| / max|b|. Integer
139
+ # and boolean results are compared BIT-IDENTICALLY and ignore this table —
140
+ # there is no valid reordering that changes an integer.
141
+ autotune_screen_rtol:
142
+ float16: 2.0e-2
143
+ bfloat16: 4.0e-2
144
+ float32: 1.0e-4
145
+ float64: 1.0e-8
146
+ int64: 0.0 # an integer result (the MoE alignment's routing tables) is met exactly
147
+
148
+ # Above this many bytes of buffer, the autotune correctness screen does not
149
+ # run. Screening copies every argument out and back once per candidate, so a
150
+ # very large tensor turns a tuning step into hundreds of megabytes of traffic
151
+ # — and on unified memory that pressure is the machine's, not a card's.
152
+ # MEASURED 2026-09-07: unbounded screening of a 151936-wide softmax perturbed
153
+ # six unrelated tests in the same process. A skipped screen is announced, not
154
+ # silent.
155
+ autotune_screen_max_bytes: 33554432
156
+
157
+ autotune:
158
+ buckets:
159
+ # elements — an element-wise launch's element count (`kernels/ops/elementwise_launch.py`), NEVER the `default`
160
+ # dimension ladder (`autotune_bucket.ladder_for` refuses it). NOT measured on this architecture (no such device on
161
+ # either machine): the four classes measured on V100-SXM2 2026-10-23 (nvidia/volta.yml, launch-bound under 65 536
162
+ # elements, bandwidth classes above) and confirmed on apple_m4_pro 2026-10-24 — the measurement on this
163
+ # architecture is owed (docs/reference/owed-proofs.md, "element-wise ladder per architecture").
164
+ elements:
165
+ - {up_to: 65536, step: 65536}
166
+ - {up_to: 1048576, step: 1048576}
167
+ - {up_to: 16777216, step: 16777216}
168
+ - {up_to: null, step: 68719476736}
169
+ default:
170
+ - {up_to: 64, step: 1}
171
+ - {up_to: 256, step: 16}
172
+ - {up_to: 1024, step: 32}
173
+ - {up_to: 8192, step: 128}
174
+ # Above 8 192 a QUARTER-OCTAVE, not a 512-step. The 512 tail was decided by a sweep
175
+ # that ran to about 4 096 and never met a request-scale dimension: a vocoder's batched
176
+ # GEMM keys on the WAVEFORM and reaches 1 963 520, which a 512-step cuts into some four
177
+ # thousand buckets — 1 400 of one model's 1 522 distinct M values sat above 8 192.
178
+ # Measured 2026-09-22 on both classes, two shapes (the vocoder's B=1,N=1,K=9 and a
179
+ # GEMM at N=K=512), each octave bucket carrying three or four measured values with its
180
+ # TOP as representative: 0.0 % median loss, 0.2 % max at ONE octave bucket. The rows
181
+ # below are finer than the octave that was measured, so they cost no more than it did.
182
+ # The first three octaves above the knee keep a NARROW step. Measured directly on the
183
+ # rows as shipped (the upscalers' N=360, K=180; three sizes inside each bucket with
184
+ # its TOP among them, 2026-09-22): a quarter-octave there cost 0.0 % median but
185
+ # **5.2 %** at the 10 240 bucket and 1.2 % at 16 384 — the loss lives just above the
186
+ # knee, where a quarter of an OCTAVE is still a quarter of the VALUE. Beyond 65 536
187
+ # the same sweep measured 0.0 % median and at most 0.6 %, so the quarter-octave stands.
188
+ # The convolution-width ladder below keeps its quarter-octave: its own sweep measured
189
+ # 0.0 % median AND max there, on both classes and two channel counts.
190
+ - {up_to: 16384, step: 512}
191
+ - {up_to: 32768, step: 1024}
192
+ - {up_to: 65536, step: 2048}
193
+ - {up_to: 131072, step: 16384}
194
+ - {up_to: 262144, step: 32768}
195
+ - {up_to: 524288, step: 65536}
196
+ - {up_to: 1048576, step: 131072}
197
+ - {up_to: 2097152, step: 262144}
198
+ - {up_to: null, step: 524288}
199
+ # The width of a ONE-ROW convolution (a 1-D convolution over a sequence: a vocoder's
200
+ # samples, a mel spectrogram's frames) is the request's length, unbounded by any
201
+ # resolution — chatterbox's vocoder reaches 444 721 samples for 18 s of speech. Above the
202
+ # GEMM ladder it steps by a quarter-octave (≤ 25 % of the value), so a census meets every
203
+ # class of a speech length in ~100 runs instead of ~1 000; the loss of that step is owed a
204
+ # measurement on both classes (bucket_loss.py) before the ladder is called final.
205
+ W:
206
+ - {up_to: 64, step: 1}
207
+ - {up_to: 256, step: 16}
208
+ - {up_to: 1024, step: 32}
209
+ - {up_to: 8192, step: 128}
210
+ - {up_to: 16384, step: 2048}
211
+ - {up_to: 32768, step: 4096}
212
+ - {up_to: 65536, step: 8192}
213
+ - {up_to: 131072, step: 16384}
214
+ - {up_to: 262144, step: 32768}
215
+ - {up_to: 524288, step: 65536}
216
+ - {up_to: null, step: 131072}
217
+
218
+ # The flash kernel at a power-of-two head dim >= 128 is NOT measured on this architecture: the zero-pad
219
+ # detour stays (launch_keys.flash_headdim_detour). Declared, never left absent: true only where the
220
+ # correctness oracle was run with the detour off on this arch and stack (Volta, Triton 3.8, 2026-10-03).
221
+ flash:
222
+ pow2_head_dim_correct: false
223
+
224
+ # Convolution weight storage order (launch_keys.conv_weight_layout): KCRS, the container's own,
225
+ # until this arch measures KRSC (the M4 Pro measured +46-63 % on its 3x3 keys, 2026-10-07).
226
+ conv:
227
+ weight_layout: KCRS