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.
- nbxtensor/THIRD_PARTY_NOTICES.md +287 -0
- nbxtensor/__init__.py +17 -0
- nbxtensor/backend/__init__.py +1 -0
- nbxtensor/backend/capabilities.py +207 -0
- nbxtensor/backend/cpu/__init__.py +1 -0
- nbxtensor/backend/cpu/blas.py +102 -0
- nbxtensor/backend/cpu/pool.py +204 -0
- nbxtensor/backend/cpu_backend.py +162 -0
- nbxtensor/backend/device_facts.py +105 -0
- nbxtensor/backend/device_files.py +129 -0
- nbxtensor/backend/device_names.py +18 -0
- nbxtensor/backend/devices/amd/cdna.yml +228 -0
- nbxtensor/backend/devices/amd/cdna2.yml +228 -0
- nbxtensor/backend/devices/amd/cdna3.yml +227 -0
- nbxtensor/backend/devices/apple/apple_m1.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m1_max.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m1_pro.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m1_ultra.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m2.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m2_max.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m2_pro.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m2_ultra.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m3.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m3_max.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m3_pro.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m3_ultra.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m4.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m4_max.yml +266 -0
- nbxtensor/backend/devices/apple/apple_m4_pro.yml +308 -0
- nbxtensor/backend/devices/apple/apple_m5.yml +269 -0
- nbxtensor/backend/devices/apple/apple_m5_max.yml +269 -0
- nbxtensor/backend/devices/apple/apple_m5_pro.yml +269 -0
- nbxtensor/backend/devices/apple/apple_m5_ultra.yml +269 -0
- nbxtensor/backend/devices/apple/apple_m6.yml +269 -0
- nbxtensor/backend/devices/apple/apple_silicon.yml +263 -0
- nbxtensor/backend/devices/nvidia/ampere.yml +214 -0
- nbxtensor/backend/devices/nvidia/hopper.yml +213 -0
- nbxtensor/backend/devices/nvidia/volta.yml +411 -0
- nbxtensor/backend/faults.py +151 -0
- nbxtensor/backend/host_memory.py +185 -0
- nbxtensor/backend/launcher.py +2350 -0
- nbxtensor/backend/launcher_contract.py +429 -0
- nbxtensor/backend/metal_backend.py +661 -0
- nbxtensor/backend/metal_device.py +1274 -0
- nbxtensor/backend/process_memory.py +73 -0
- nbxtensor/backend/replay_graph.py +322 -0
- nbxtensor/backend/runtime.py +409 -0
- nbxtensor/backend/triton_ext_driver.py +735 -0
- nbxtensor/dtype/__init__.py +1 -0
- nbxtensor/dtype/convert.py +107 -0
- nbxtensor/dtype/dtypes.yml +70 -0
- nbxtensor/dtype/itemsize.py +166 -0
- nbxtensor/dtype/nbx_dtype.py +72 -0
- nbxtensor/dtype/operands.py +158 -0
- nbxtensor/dtype/outputs.py +64 -0
- nbxtensor/dtype/policy.py +155 -0
- nbxtensor/dtype/policy.yml +51 -0
- nbxtensor/dtype/promotion.py +112 -0
- nbxtensor/host.py +55 -0
- nbxtensor/io/__init__.py +1 -0
- nbxtensor/io/read_rate.py +197 -0
- nbxtensor/io/safetensors.py +314 -0
- nbxtensor/memory/__init__.py +9 -0
- nbxtensor/memory/allocator.py +1988 -0
- nbxtensor/memory/arena.py +75 -0
- nbxtensor/memory/device_memory.py +150 -0
- nbxtensor/memory/device_transfer.py +154 -0
- nbxtensor/memory/layout.py +43 -0
- nbxtensor/memory/memory_pool.py +191 -0
- nbxtensor/memory/metal.py +96 -0
- nbxtensor/memory/oom_advice.py +91 -0
- nbxtensor/memory/pointer_tables.py +323 -0
- nbxtensor/memory/pool.py +507 -0
- nbxtensor/memory/shadow.py +43 -0
- nbxtensor/memory/slab.py +273 -0
- nbxtensor/memory/trace_replay.py +122 -0
- nbxtensor/memory/traces/sana-video-2b-720p.16g.2026-11-02.tsv +13610 -0
- nbxtensor/memory/vmm.py +118 -0
- nbxtensor/ops/__init__.py +1 -0
- nbxtensor/ops/_autotune_policy.py +90 -0
- nbxtensor/ops/_common.py +32 -0
- nbxtensor/ops/_configs.py +1041 -0
- nbxtensor/ops/_cost.py +231 -0
- nbxtensor/ops/abs.py +17 -0
- nbxtensor/ops/adaptive_avg_pool2d.py +161 -0
- nbxtensor/ops/add.py +96 -0
- nbxtensor/ops/addcdiv.py +29 -0
- nbxtensor/ops/addcmul.py +29 -0
- nbxtensor/ops/addmv_op.py +64 -0
- nbxtensor/ops/addr.py +68 -0
- nbxtensor/ops/all_reduce.py +83 -0
- nbxtensor/ops/amax.py +40 -0
- nbxtensor/ops/any_reduce.py +83 -0
- nbxtensor/ops/arange_op.py +27 -0
- nbxtensor/ops/argmax.py +107 -0
- nbxtensor/ops/argmin.py +93 -0
- nbxtensor/ops/atan2.py +71 -0
- nbxtensor/ops/attention_wrappers.py +1648 -0
- nbxtensor/ops/autotune_bucket.py +137 -0
- nbxtensor/ops/autotune_cache.py +430 -0
- nbxtensor/ops/autotune_certified.py +1262 -0
- nbxtensor/ops/autotune_refusals.py +380 -0
- nbxtensor/ops/autotune_settings.py +58 -0
- nbxtensor/ops/avg_pool2d.py +73 -0
- nbxtensor/ops/baddbmm_op.py +132 -0
- nbxtensor/ops/batch_norm.py +163 -0
- nbxtensor/ops/binary_strided.py +196 -0
- nbxtensor/ops/bitwise_and.py +26 -0
- nbxtensor/ops/bitwise_left_shift.py +47 -0
- nbxtensor/ops/bitwise_not.py +24 -0
- nbxtensor/ops/bitwise_or.py +26 -0
- nbxtensor/ops/bitwise_right_shift.py +47 -0
- nbxtensor/ops/bucketize.py +37 -0
- nbxtensor/ops/cat_op.py +87 -0
- nbxtensor/ops/celu.py +20 -0
- nbxtensor/ops/clamp.py +24 -0
- nbxtensor/ops/clamp_min.py +22 -0
- nbxtensor/ops/conv2d.py +265 -0
- nbxtensor/ops/conv2d_m8n8k4.py +165 -0
- nbxtensor/ops/conv_depthwise2d.py +154 -0
- nbxtensor/ops/conv_transpose2d.py +148 -0
- nbxtensor/ops/conv_wrappers.py +1482 -0
- nbxtensor/ops/copy.py +18 -0
- nbxtensor/ops/copy_op.py +39 -0
- nbxtensor/ops/cos.py +17 -0
- nbxtensor/ops/count_nonzero.py +64 -0
- nbxtensor/ops/cross_entropy.py +67 -0
- nbxtensor/ops/cummax.py +109 -0
- nbxtensor/ops/cummin.py +105 -0
- nbxtensor/ops/cumsum.py +244 -0
- nbxtensor/ops/decode_attn_vec.py +162 -0
- nbxtensor/ops/depthwise_conv2d.py +132 -0
- nbxtensor/ops/dequant_gemv.py +190 -0
- nbxtensor/ops/dft.py +67 -0
- nbxtensor/ops/dispatch.py +1228 -0
- nbxtensor/ops/div.py +75 -0
- nbxtensor/ops/dot_op.py +67 -0
- nbxtensor/ops/dropout.py +23 -0
- nbxtensor/ops/dtype_convert.py +42 -0
- nbxtensor/ops/elementwise_launch.py +81 -0
- nbxtensor/ops/elementwise_wrappers.py +2315 -0
- nbxtensor/ops/elu.py +20 -0
- nbxtensor/ops/embedding.py +69 -0
- nbxtensor/ops/eq.py +32 -0
- nbxtensor/ops/erf.py +18 -0
- nbxtensor/ops/exp.py +17 -0
- nbxtensor/ops/exp2.py +18 -0
- nbxtensor/ops/fft_op.py +125 -0
- nbxtensor/ops/fill_op.py +20 -0
- nbxtensor/ops/flash_attention.py +307 -0
- nbxtensor/ops/flash_attention_m8n8k4.py +384 -0
- nbxtensor/ops/flash_decode.py +78 -0
- nbxtensor/ops/flip_op.py +60 -0
- nbxtensor/ops/floor.py +90 -0
- nbxtensor/ops/full_op.py +24 -0
- nbxtensor/ops/fused_moe.py +417 -0
- nbxtensor/ops/fused_moe_m8n8k4.py +99 -0
- nbxtensor/ops/fused_upsample_conv.py +413 -0
- nbxtensor/ops/gather_op.py +52 -0
- nbxtensor/ops/ge.py +32 -0
- nbxtensor/ops/gelu.py +31 -0
- nbxtensor/ops/gemv_vec.py +80 -0
- nbxtensor/ops/glu.py +43 -0
- nbxtensor/ops/grid_sampler.py +145 -0
- nbxtensor/ops/group_norm_tiled.py +67 -0
- nbxtensor/ops/groupnorm.py +123 -0
- nbxtensor/ops/gt.py +32 -0
- nbxtensor/ops/hardsigmoid.py +18 -0
- nbxtensor/ops/hardswish.py +19 -0
- nbxtensor/ops/im2col.py +57 -0
- nbxtensor/ops/index_add.py +95 -0
- nbxtensor/ops/index_put_op.py +92 -0
- nbxtensor/ops/index_select.py +121 -0
- nbxtensor/ops/index_wrappers.py +770 -0
- nbxtensor/ops/isfinite.py +20 -0
- nbxtensor/ops/isinf.py +20 -0
- nbxtensor/ops/isnan.py +18 -0
- nbxtensor/ops/launch_keys.py +1054 -0
- nbxtensor/ops/launch_observer.py +54 -0
- nbxtensor/ops/layernorm.py +71 -0
- nbxtensor/ops/le.py +35 -0
- nbxtensor/ops/leaky_relu.py +19 -0
- nbxtensor/ops/lerp.py +76 -0
- nbxtensor/ops/linalg_wrappers.py +1370 -0
- nbxtensor/ops/linspace_op.py +47 -0
- nbxtensor/ops/log.py +17 -0
- nbxtensor/ops/log_sigmoid.py +23 -0
- nbxtensor/ops/logical_and.py +26 -0
- nbxtensor/ops/logical_not.py +24 -0
- nbxtensor/ops/logical_or.py +26 -0
- nbxtensor/ops/logical_xor.py +37 -0
- nbxtensor/ops/loss_wrappers.py +282 -0
- nbxtensor/ops/lt.py +32 -0
- nbxtensor/ops/masked_fill.py +21 -0
- nbxtensor/ops/matmul.py +377 -0
- nbxtensor/ops/matmul_m8n8k4.py +235 -0
- nbxtensor/ops/max_pool2d.py +74 -0
- nbxtensor/ops/max_pool3d.py +93 -0
- nbxtensor/ops/max_reduce.py +91 -0
- nbxtensor/ops/maximum.py +18 -0
- nbxtensor/ops/mean.py +40 -0
- nbxtensor/ops/min_reduce.py +91 -0
- nbxtensor/ops/minimum.py +18 -0
- nbxtensor/ops/mish.py +22 -0
- nbxtensor/ops/mma_m8n8k4.py +152 -0
- nbxtensor/ops/moe_align.py +195 -0
- nbxtensor/ops/moe_decode_vec.py +374 -0
- nbxtensor/ops/moe_device_residency.py +141 -0
- nbxtensor/ops/moe_wrappers.py +345 -0
- nbxtensor/ops/mse_loss.py +79 -0
- nbxtensor/ops/mul.py +51 -0
- nbxtensor/ops/nan_to_num.py +23 -0
- nbxtensor/ops/ne.py +32 -0
- nbxtensor/ops/neg.py +17 -0
- nbxtensor/ops/nllloss.py +124 -0
- nbxtensor/ops/nonzero.py +33 -0
- nbxtensor/ops/nonzero_op.py +62 -0
- nbxtensor/ops/norm_wrappers.py +579 -0
- nbxtensor/ops/ones_op.py +20 -0
- nbxtensor/ops/oracles/__init__.py +6 -0
- nbxtensor/ops/oracles/conv2d_fp64.py +450 -0
- nbxtensor/ops/pad_op.py +159 -0
- nbxtensor/ops/paged_decode_attn.py +215 -0
- nbxtensor/ops/pixel_shuffle.py +144 -0
- nbxtensor/ops/pixel_unshuffle.py +72 -0
- nbxtensor/ops/pow.py +137 -0
- nbxtensor/ops/prod.py +81 -0
- nbxtensor/ops/rand_op.py +52 -0
- nbxtensor/ops/random_wrappers.py +366 -0
- nbxtensor/ops/reciprocal.py +17 -0
- nbxtensor/ops/reduction_wrappers.py +845 -0
- nbxtensor/ops/relu.py +18 -0
- nbxtensor/ops/remainder.py +46 -0
- nbxtensor/ops/repeat_interleave.py +48 -0
- nbxtensor/ops/repeat_op.py +132 -0
- nbxtensor/ops/residual_chain.py +374 -0
- nbxtensor/ops/rmsnorm.py +68 -0
- nbxtensor/ops/rope.py +142 -0
- nbxtensor/ops/rsqrt.py +17 -0
- nbxtensor/ops/scaled_softmax.py +96 -0
- nbxtensor/ops/scatter_op.py +139 -0
- nbxtensor/ops/screen_oracle.py +479 -0
- nbxtensor/ops/selu.py +22 -0
- nbxtensor/ops/shape_wrappers.py +1032 -0
- nbxtensor/ops/sigmoid.py +19 -0
- nbxtensor/ops/silu.py +27 -0
- nbxtensor/ops/sin.py +17 -0
- nbxtensor/ops/softmax.py +169 -0
- nbxtensor/ops/softplus.py +27 -0
- nbxtensor/ops/sort_op.py +304 -0
- nbxtensor/ops/spectral_wrappers.py +481 -0
- nbxtensor/ops/sqrt.py +17 -0
- nbxtensor/ops/stack_op.py +84 -0
- nbxtensor/ops/std.py +113 -0
- nbxtensor/ops/strided_copy.py +200 -0
- nbxtensor/ops/sub.py +35 -0
- nbxtensor/ops/sum.py +40 -0
- nbxtensor/ops/tan.py +19 -0
- nbxtensor/ops/tanh.py +21 -0
- nbxtensor/ops/threshold.py +19 -0
- nbxtensor/ops/tiling.yml +91 -0
- nbxtensor/ops/tiling_policy.py +43 -0
- nbxtensor/ops/tiling_sizes.py +370 -0
- nbxtensor/ops/topk.py +267 -0
- nbxtensor/ops/trace_op.py +64 -0
- nbxtensor/ops/tril.py +64 -0
- nbxtensor/ops/triu.py +62 -0
- nbxtensor/ops/unfold_op.py +37 -0
- nbxtensor/ops/unique_op.py +97 -0
- nbxtensor/ops/upsample_bilinear2d.py +106 -0
- nbxtensor/ops/upsample_nearest2d.py +52 -0
- nbxtensor/ops/upsample_nearest3d.py +61 -0
- nbxtensor/ops/var.py +136 -0
- nbxtensor/ops/vector_norm.py +216 -0
- nbxtensor/ops/weight_norm.py +104 -0
- nbxtensor/ops/where.py +39 -0
- nbxtensor/ops/wrappers.py +825 -0
- nbxtensor/ops/zeros_op.py +20 -0
- nbxtensor/quant/__init__.py +1 -0
- nbxtensor/quant/quantized_tensor.py +187 -0
- nbxtensor/random/__init__.py +1 -0
- nbxtensor/random/mt_randn.py +154 -0
- nbxtensor/random/rng_pin.py +59 -0
- nbxtensor/random/rng_stream.py +118 -0
- nbxtensor/random/seeded_draw.py +223 -0
- nbxtensor/shape/__init__.py +157 -0
- nbxtensor/tensor.py +1867 -0
- nbxtensor-0.0.1.dist-info/METADATA +379 -0
- nbxtensor-0.0.1.dist-info/RECORD +291 -0
- nbxtensor-0.0.1.dist-info/WHEEL +4 -0
- nbxtensor-0.0.1.dist-info/licenses/LICENSE +189 -0
nbxtensor/ops/std.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Standard deviation — pure @triton.jit kernels.
|
|
2
|
+
|
|
3
|
+
Global reduction via map-reduce (sum + sum_sq) and dim-specific two-pass
|
|
4
|
+
(mean, then variance). Extracted from FlagGems (Apache-2.0).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import triton
|
|
8
|
+
import triton.language as tl
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
# Global reduction: map-reduce
|
|
13
|
+
# ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
@triton.jit
|
|
16
|
+
def std_map_kernel(X, Tmp_sum, Tmp_sum_sq, N, BLOCK_N: tl.constexpr):
|
|
17
|
+
"""Pass 1: compute partial sum and sum-of-squares per block."""
|
|
18
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
19
|
+
offset = pid * BLOCK_N + tl.arange(0, BLOCK_N)
|
|
20
|
+
mask = offset < N
|
|
21
|
+
x = tl.load(X + offset, mask=mask, other=0.0).to(tl.float32)
|
|
22
|
+
sum_val = tl.sum(x, axis=0)
|
|
23
|
+
sum_sq_val = tl.sum(x * x, axis=0)
|
|
24
|
+
tl.store(Tmp_sum + pid, sum_val)
|
|
25
|
+
tl.store(Tmp_sum_sq + pid, sum_sq_val)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@triton.jit
|
|
29
|
+
def std_reduce_kernel(
|
|
30
|
+
Tmp_sum, Tmp_sum_sq, Out, N, correction, BLOCK_NUM, BLOCK_SIZE: tl.constexpr
|
|
31
|
+
):
|
|
32
|
+
"""Pass 2: combine blocks and compute std = sqrt(var)."""
|
|
33
|
+
total_sum_acc = tl.zeros((BLOCK_SIZE,), dtype=tl.float32)
|
|
34
|
+
total_sum_sq_acc = tl.zeros((BLOCK_SIZE,), dtype=tl.float32)
|
|
35
|
+
for off in range(0, BLOCK_NUM, BLOCK_SIZE):
|
|
36
|
+
offset = off + tl.arange(0, BLOCK_SIZE)
|
|
37
|
+
mask = offset < BLOCK_NUM
|
|
38
|
+
tmp_sum_vals = tl.load(Tmp_sum + offset, mask=mask, other=0.0).to(tl.float32)
|
|
39
|
+
tmp_sum_sq_vals = tl.load(Tmp_sum_sq + offset, mask=mask, other=0.0).to(
|
|
40
|
+
tl.float32
|
|
41
|
+
)
|
|
42
|
+
total_sum_acc += tmp_sum_vals
|
|
43
|
+
total_sum_sq_acc += tmp_sum_sq_vals
|
|
44
|
+
total_sum = tl.sum(total_sum_acc, axis=0)
|
|
45
|
+
total_sum_sq = tl.sum(total_sum_sq_acc, axis=0)
|
|
46
|
+
mean = total_sum / N
|
|
47
|
+
var = (total_sum_sq / N) - (mean * mean)
|
|
48
|
+
var = var * N / tl.maximum(N - correction, 1.0)
|
|
49
|
+
safe_var = tl.maximum(var, 0.0)
|
|
50
|
+
std_dev = tl.sqrt(safe_var)
|
|
51
|
+
tl.store(Out, std_dev.to(Out.dtype.element_ty))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# Dim-specific: two-pass (mean, then variance)
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
@triton.jit
|
|
59
|
+
def std_dim_kernel(
|
|
60
|
+
X,
|
|
61
|
+
Out,
|
|
62
|
+
stride_x_row,
|
|
63
|
+
stride_x_col,
|
|
64
|
+
M,
|
|
65
|
+
N,
|
|
66
|
+
correction,
|
|
67
|
+
BLOCK_M: tl.constexpr,
|
|
68
|
+
BLOCK_N: tl.constexpr,
|
|
69
|
+
):
|
|
70
|
+
"""Compute std along compressed inner dim N.
|
|
71
|
+
|
|
72
|
+
X: [M, N] (dim-compressed, strided) → Out: [M]
|
|
73
|
+
Two-pass: first compute mean, then sum of squared deviations.
|
|
74
|
+
"""
|
|
75
|
+
pid_group = tl.program_id(0).to(tl.int64)
|
|
76
|
+
start_row = pid_group * BLOCK_M
|
|
77
|
+
row_offsets = start_row + tl.arange(0, BLOCK_M)
|
|
78
|
+
row_mask = row_offsets < M
|
|
79
|
+
|
|
80
|
+
# Pass 1: compute mean
|
|
81
|
+
mean_acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
|
|
82
|
+
x_row_ptrs = X + row_offsets[:, None] * stride_x_row
|
|
83
|
+
|
|
84
|
+
for off in range(0, N, BLOCK_N):
|
|
85
|
+
col_offsets = off + tl.arange(0, BLOCK_N)
|
|
86
|
+
col_mask = col_offsets < N
|
|
87
|
+
x_ptrs = x_row_ptrs + col_offsets[None, :] * stride_x_col
|
|
88
|
+
final_mask = row_mask[:, None] & col_mask[None, :]
|
|
89
|
+
x = tl.load(x_ptrs, mask=final_mask, other=0.0)
|
|
90
|
+
mean_acc += x.to(tl.float32)
|
|
91
|
+
|
|
92
|
+
mean = tl.sum(mean_acc, axis=1) / N
|
|
93
|
+
|
|
94
|
+
# Pass 2: compute variance
|
|
95
|
+
var_acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
|
|
96
|
+
for off in range(0, N, BLOCK_N):
|
|
97
|
+
col_offsets = off + tl.arange(0, BLOCK_N)
|
|
98
|
+
col_mask = col_offsets < N
|
|
99
|
+
x_ptrs = x_row_ptrs + col_offsets[None, :] * stride_x_col
|
|
100
|
+
final_mask = row_mask[:, None] & col_mask[None, :]
|
|
101
|
+
x = tl.load(x_ptrs, mask=final_mask, other=0.0)
|
|
102
|
+
diff = x.to(tl.float32) - mean[:, None]
|
|
103
|
+
var_acc += tl.where(final_mask, diff * diff, 0.0)
|
|
104
|
+
|
|
105
|
+
var = tl.sum(var_acc, axis=1)
|
|
106
|
+
|
|
107
|
+
denom = N - correction
|
|
108
|
+
var = var / tl.maximum(denom, 1e-12)
|
|
109
|
+
safe_var = tl.maximum(var, 0.0)
|
|
110
|
+
std_dev = tl.sqrt(safe_var)
|
|
111
|
+
|
|
112
|
+
out_ptrs = Out + row_offsets
|
|
113
|
+
tl.store(out_ptrs, std_dev.to(Out.dtype.element_ty), mask=row_mask)
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Strided ↔ contiguous copy kernels — N-D scalable, Triton-JIT.
|
|
2
|
+
|
|
3
|
+
Two operations:
|
|
4
|
+
|
|
5
|
+
* `strided_copy_kernel` — read from a non-contiguous (strided) source,
|
|
6
|
+
write to a contiguous destination. Used by
|
|
7
|
+
`NBXTensor.clone` / `NBXTensor.contiguous`
|
|
8
|
+
whenever the source is a view (permute,
|
|
9
|
+
transpose, narrow, expand, ...).
|
|
10
|
+
|
|
11
|
+
* `strided_scatter_kernel` — read from a contiguous source, write to a
|
|
12
|
+
non-contiguous destination. Used by
|
|
13
|
+
`NBXTensor.__setitem__` (KV cache indexed
|
|
14
|
+
writes into a narrow view).
|
|
15
|
+
|
|
16
|
+
* `strided_copy_nd_kernel` — read from a strided source, write to a
|
|
17
|
+
strided destination, converting the dtype on
|
|
18
|
+
the store with `copy_kernel`'s exact protected
|
|
19
|
+
fp16 rounding. One launch where `__setitem__`,
|
|
20
|
+
`copy_` and `.to()` used to take a contiguous
|
|
21
|
+
copy of the source, a cast of that copy and a
|
|
22
|
+
scatter of the cast (three launches and two
|
|
23
|
+
transients per KV-cache write, 2026-09-07).
|
|
24
|
+
|
|
25
|
+
Both kernels are parameterised by `NDIM: tl.constexpr`. Triton
|
|
26
|
+
specialises and caches one compiled kernel per distinct ndim
|
|
27
|
+
encountered at runtime: the per-dimension index decomposition loop is
|
|
28
|
+
unrolled at compile time via `tl.static_range(NDIM)`.
|
|
29
|
+
|
|
30
|
+
The shape and stride vectors are passed as GPU pointers to small int64
|
|
31
|
+
arrays (NDIM elements each). The kernel loads them inside the JIT body,
|
|
32
|
+
so callers can handle any tensor up to PyTorch's 25-D hard limit
|
|
33
|
+
without recompiling the code. A 6-D PixArt patchify clone, an 8-D
|
|
34
|
+
SANA-Video VAE reshape, and a hypothetical 10-12-D multi-view 4D-scene
|
|
35
|
+
permute all route through the same kernel text.
|
|
36
|
+
|
|
37
|
+
Why this matters: the previous version was hardcoded to 5 dims
|
|
38
|
+
(`d0..d4`, `s0..s4`). The wrapper silently dropped higher dims via
|
|
39
|
+
`[1] * (5 - ndim)` returning `[]` for ndim > 5. 6-D PixArt clones
|
|
40
|
+
produced out-of-bounds reads past the source allocation — silently
|
|
41
|
+
corrupted data (Alpha) or `cudaErrorIllegalAddress` (Sigma), and
|
|
42
|
+
8-D SANA-Video VAE clones had been unreachable entirely.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
import triton
|
|
46
|
+
import triton.language as tl
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@triton.jit
|
|
50
|
+
def strided_copy_kernel(
|
|
51
|
+
src_ptr, dst_ptr,
|
|
52
|
+
n_elements,
|
|
53
|
+
shape_ptr, # GPU pointer → NDIM int64 shape values (source)
|
|
54
|
+
stride_ptr, # GPU pointer → NDIM int64 stride values (source)
|
|
55
|
+
BLOCK_SIZE: tl.constexpr,
|
|
56
|
+
NDIM: tl.constexpr,
|
|
57
|
+
WIDE: tl.constexpr = True,
|
|
58
|
+
):
|
|
59
|
+
"""Copy strided src → contiguous dst. Dimensions are unrolled at
|
|
60
|
+
compile time via the NDIM constexpr; shape/strides are loaded from
|
|
61
|
+
GPU scratch buffers so the kernel text is identical for every
|
|
62
|
+
ndim Triton specialises.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
src_ptr: Source tensor data pointer (may be non-contiguous).
|
|
66
|
+
dst_ptr: Destination tensor data pointer (contiguous).
|
|
67
|
+
n_elements: Total elements to copy (= src._numel).
|
|
68
|
+
shape_ptr: Pointer to NDIM int64 shape values (source shape).
|
|
69
|
+
stride_ptr: Pointer to NDIM int64 stride values (source strides).
|
|
70
|
+
BLOCK_SIZE: Elements per thread block (constexpr).
|
|
71
|
+
NDIM: Rank of the tensors (constexpr; triggers
|
|
72
|
+
specialisation + kernel cache entry).
|
|
73
|
+
"""
|
|
74
|
+
if WIDE:
|
|
75
|
+
offsets = tl.program_id(0).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)
|
|
76
|
+
else:
|
|
77
|
+
offsets = tl.program_id(0) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
|
|
78
|
+
mask = offsets < n_elements
|
|
79
|
+
|
|
80
|
+
# Decompose the flat offset into multi-dim indices, walking dims
|
|
81
|
+
# from the innermost (NDIM-1) outward. At each step, `remaining %
|
|
82
|
+
# d` gives the current-dim index and `remaining // d` feeds the
|
|
83
|
+
# next outer dim. The src_offsets accumulator multiplies each
|
|
84
|
+
# per-dim index by the source's stride for that dim — this is
|
|
85
|
+
# what lets the kernel read from a non-contiguous layout while
|
|
86
|
+
# writing contiguously.
|
|
87
|
+
remaining = offsets
|
|
88
|
+
src_offsets = tl.zeros_like(offsets)
|
|
89
|
+
for i in tl.static_range(NDIM):
|
|
90
|
+
dim = NDIM - 1 - i
|
|
91
|
+
d = tl.load(shape_ptr + dim)
|
|
92
|
+
s = tl.load(stride_ptr + dim)
|
|
93
|
+
if not WIDE:
|
|
94
|
+
d = d.to(tl.int32)
|
|
95
|
+
s = s.to(tl.int32)
|
|
96
|
+
idx = remaining % d
|
|
97
|
+
remaining = remaining // d
|
|
98
|
+
src_offsets = src_offsets + idx * s
|
|
99
|
+
|
|
100
|
+
vals = tl.load(src_ptr + src_offsets, mask=mask)
|
|
101
|
+
tl.store(dst_ptr + offsets, vals, mask=mask)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@triton.jit
|
|
105
|
+
def strided_scatter_kernel(
|
|
106
|
+
src_ptr, dst_ptr,
|
|
107
|
+
n_elements,
|
|
108
|
+
shape_ptr, # GPU pointer → NDIM int64 shape values (destination)
|
|
109
|
+
stride_ptr, # GPU pointer → NDIM int64 stride values (destination)
|
|
110
|
+
BLOCK_SIZE: tl.constexpr,
|
|
111
|
+
NDIM: tl.constexpr,
|
|
112
|
+
WIDE: tl.constexpr = True,
|
|
113
|
+
):
|
|
114
|
+
"""Scatter contiguous src → strided dst. Inverse of
|
|
115
|
+
`strided_copy_kernel`. Same N-D specialisation strategy.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
src_ptr: Source tensor data pointer (contiguous).
|
|
119
|
+
dst_ptr: Destination tensor data pointer (may be non-
|
|
120
|
+
contiguous — e.g. a narrow view into a KV cache).
|
|
121
|
+
n_elements: Total elements to scatter (= dst._numel).
|
|
122
|
+
shape_ptr: Pointer to NDIM int64 shape values (dst shape).
|
|
123
|
+
stride_ptr: Pointer to NDIM int64 stride values (dst strides).
|
|
124
|
+
BLOCK_SIZE: Elements per thread block.
|
|
125
|
+
NDIM: Rank of the tensors (constexpr).
|
|
126
|
+
"""
|
|
127
|
+
if WIDE:
|
|
128
|
+
offsets = tl.program_id(0).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)
|
|
129
|
+
else:
|
|
130
|
+
offsets = tl.program_id(0) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
|
|
131
|
+
mask = offsets < n_elements
|
|
132
|
+
|
|
133
|
+
remaining = offsets
|
|
134
|
+
dst_offsets = tl.zeros_like(offsets)
|
|
135
|
+
for i in tl.static_range(NDIM):
|
|
136
|
+
dim = NDIM - 1 - i
|
|
137
|
+
d = tl.load(shape_ptr + dim)
|
|
138
|
+
s = tl.load(stride_ptr + dim)
|
|
139
|
+
if not WIDE:
|
|
140
|
+
d = d.to(tl.int32)
|
|
141
|
+
s = s.to(tl.int32)
|
|
142
|
+
idx = remaining % d
|
|
143
|
+
remaining = remaining // d
|
|
144
|
+
dst_offsets = dst_offsets + idx * s
|
|
145
|
+
|
|
146
|
+
vals = tl.load(src_ptr + offsets, mask=mask)
|
|
147
|
+
tl.store(dst_ptr + dst_offsets, vals, mask=mask)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@triton.jit
|
|
151
|
+
def strided_copy_nd_kernel(
|
|
152
|
+
src_ptr, dst_ptr,
|
|
153
|
+
n_elements,
|
|
154
|
+
shape_ptr, # GPU pointer → NDIM int64 extents (shared by src and dst)
|
|
155
|
+
src_stride_ptr, # GPU pointer → NDIM int64 source strides (0 on a broadcast dim)
|
|
156
|
+
dst_stride_ptr, # GPU pointer → NDIM int64 destination strides
|
|
157
|
+
BLOCK_SIZE: tl.constexpr,
|
|
158
|
+
NDIM: tl.constexpr,
|
|
159
|
+
WIDE: tl.constexpr = True,
|
|
160
|
+
SATURATE_F16: tl.constexpr = False,
|
|
161
|
+
):
|
|
162
|
+
"""Copy strided src → strided dst, casting on the store.
|
|
163
|
+
|
|
164
|
+
The flat element index is decomposed once into the multi-index and
|
|
165
|
+
each side's offset accumulates its own strides, so any pair of
|
|
166
|
+
layouts of the same extents copies in one pass — a broadcast source
|
|
167
|
+
(stride 0) included. SATURATE_F16 is the protected float16 downcast
|
|
168
|
+
of `copy_kernel`, the same expression, so a cast through this kernel
|
|
169
|
+
is bit-identical to a cast through `copy_kernel` after `contiguous()`.
|
|
170
|
+
"""
|
|
171
|
+
if WIDE:
|
|
172
|
+
offsets = tl.program_id(0).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)
|
|
173
|
+
else:
|
|
174
|
+
offsets = tl.program_id(0) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
|
|
175
|
+
mask = offsets < n_elements
|
|
176
|
+
|
|
177
|
+
remaining = offsets
|
|
178
|
+
src_offsets = tl.zeros_like(offsets)
|
|
179
|
+
dst_offsets = tl.zeros_like(offsets)
|
|
180
|
+
for i in tl.static_range(NDIM):
|
|
181
|
+
dim = NDIM - 1 - i
|
|
182
|
+
d = tl.load(shape_ptr + dim)
|
|
183
|
+
ss = tl.load(src_stride_ptr + dim)
|
|
184
|
+
ds = tl.load(dst_stride_ptr + dim)
|
|
185
|
+
if not WIDE:
|
|
186
|
+
d = d.to(tl.int32)
|
|
187
|
+
ss = ss.to(tl.int32)
|
|
188
|
+
ds = ds.to(tl.int32)
|
|
189
|
+
idx = remaining % d
|
|
190
|
+
remaining = remaining // d
|
|
191
|
+
src_offsets = src_offsets + idx * ss
|
|
192
|
+
dst_offsets = dst_offsets + idx * ds
|
|
193
|
+
|
|
194
|
+
vals = tl.load(src_ptr + src_offsets, mask=mask)
|
|
195
|
+
if SATURATE_F16:
|
|
196
|
+
f = vals.to(tl.float32)
|
|
197
|
+
is_finite = (f == f) & (f != float("inf")) & (f != float("-inf"))
|
|
198
|
+
clamped = tl.minimum(tl.maximum(f, -65504.0), 65504.0)
|
|
199
|
+
vals = tl.where(is_finite, clamped, f)
|
|
200
|
+
tl.store(dst_ptr + dst_offsets, vals, mask=mask)
|
nbxtensor/ops/sub.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Subtraction — pure @triton.jit kernel."""
|
|
2
|
+
|
|
3
|
+
import triton
|
|
4
|
+
import triton.language as tl
|
|
5
|
+
|
|
6
|
+
@triton.jit
|
|
7
|
+
def sub_forward_kernel(
|
|
8
|
+
x_ptr, y_ptr, output_ptr,
|
|
9
|
+
n_elements,
|
|
10
|
+
alpha,
|
|
11
|
+
BLOCK_SIZE: tl.constexpr,
|
|
12
|
+
):
|
|
13
|
+
"""out = x - alpha * y"""
|
|
14
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
15
|
+
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)
|
|
16
|
+
mask = offset < n_elements
|
|
17
|
+
|
|
18
|
+
x = tl.load(x_ptr + offset, mask=mask)
|
|
19
|
+
y = tl.load(y_ptr + offset, mask=mask)
|
|
20
|
+
tl.store(output_ptr + offset, x - alpha * y, mask=mask)
|
|
21
|
+
|
|
22
|
+
@triton.jit
|
|
23
|
+
def rsub_forward_kernel(
|
|
24
|
+
x_ptr, output_ptr,
|
|
25
|
+
n_elements,
|
|
26
|
+
scalar,
|
|
27
|
+
BLOCK_SIZE: tl.constexpr,
|
|
28
|
+
):
|
|
29
|
+
"""out = scalar - x (reverse subtraction)"""
|
|
30
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
31
|
+
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)
|
|
32
|
+
mask = offset < n_elements
|
|
33
|
+
|
|
34
|
+
x = tl.load(x_ptr + offset, mask=mask)
|
|
35
|
+
tl.store(output_ptr + offset, scalar - x, mask=mask)
|
nbxtensor/ops/sum.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Sum reduction — pure @triton.jit kernel, the row walked in tiles of the certified width."""
|
|
2
|
+
|
|
3
|
+
import triton
|
|
4
|
+
import triton.language as tl
|
|
5
|
+
|
|
6
|
+
from nbxtensor.ops._configs import nbx_autotune, row_reduce_configs, prune_row_reduce
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@nbx_autotune(configs=row_reduce_configs(), key=['BATCH_BUCKET', 'FEAT_BUCKET'],
|
|
10
|
+
prune_configs_by={'early_config_prune': prune_row_reduce}, cache_results=True)
|
|
11
|
+
@triton.jit
|
|
12
|
+
def sum_forward_kernel(
|
|
13
|
+
input_ptr, output_ptr,
|
|
14
|
+
batch_dim, feat_dim, BATCH_BUCKET, FEAT_BUCKET,
|
|
15
|
+
input_batch_stride, input_feat_stride,
|
|
16
|
+
BLOCK_SIZE_BATCH: tl.constexpr,
|
|
17
|
+
BLOCK_SIZE_FEAT: tl.constexpr,
|
|
18
|
+
):
|
|
19
|
+
"""Sum reduction over the last dimension: input [batch_dim, feat_dim] -> output [batch_dim].
|
|
20
|
+
|
|
21
|
+
The first tile is reduced alone and every further tile combined into it, so a row that fits one
|
|
22
|
+
tile is reduced by exactly the instructions it was before the loop existed.
|
|
23
|
+
"""
|
|
24
|
+
batch_pid = tl.program_id(0).to(tl.int64)
|
|
25
|
+
batch_offset = batch_pid * BLOCK_SIZE_BATCH + tl.arange(0, BLOCK_SIZE_BATCH)
|
|
26
|
+
feat_offset = tl.arange(0, BLOCK_SIZE_FEAT)
|
|
27
|
+
batch_mask = batch_offset < batch_dim
|
|
28
|
+
row_ptr = input_ptr + input_batch_stride * batch_offset[:, None]
|
|
29
|
+
|
|
30
|
+
feat_mask = feat_offset < feat_dim
|
|
31
|
+
inp = tl.load(row_ptr + input_feat_stride * feat_offset[None, :],
|
|
32
|
+
mask=batch_mask[:, None] & feat_mask[None, :], other=0.0).to(tl.float32)
|
|
33
|
+
result = tl.sum(inp, axis=1)
|
|
34
|
+
for start in range(BLOCK_SIZE_FEAT, feat_dim, BLOCK_SIZE_FEAT):
|
|
35
|
+
offs = start + feat_offset
|
|
36
|
+
feat_mask = offs < feat_dim
|
|
37
|
+
inp = tl.load(row_ptr + input_feat_stride * offs[None, :].to(tl.int64),
|
|
38
|
+
mask=batch_mask[:, None] & feat_mask[None, :], other=0.0).to(tl.float32)
|
|
39
|
+
result += tl.sum(inp, axis=1)
|
|
40
|
+
tl.store(output_ptr + batch_offset, result, mask=batch_mask)
|
nbxtensor/ops/tan.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Tan (tangent) — pure @triton.jit kernel. Logic from FlagGems."""
|
|
2
|
+
|
|
3
|
+
import triton
|
|
4
|
+
import triton.language as tl
|
|
5
|
+
|
|
6
|
+
@triton.jit
|
|
7
|
+
def tan_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
|
+
x_fp32 = x.to(tl.float32)
|
|
18
|
+
out = tl.sin(x_fp32) / tl.cos(x_fp32)
|
|
19
|
+
tl.store(output_ptr + offset, out, mask=mask)
|
nbxtensor/ops/tanh.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Tanh — pure @triton.jit kernel."""
|
|
2
|
+
|
|
3
|
+
import triton
|
|
4
|
+
import triton.language as tl
|
|
5
|
+
|
|
6
|
+
from ._common import sigmoid
|
|
7
|
+
|
|
8
|
+
@triton.jit
|
|
9
|
+
def tanh_forward_kernel(
|
|
10
|
+
input_ptr, output_ptr,
|
|
11
|
+
n_elements,
|
|
12
|
+
BLOCK_SIZE: tl.constexpr,
|
|
13
|
+
):
|
|
14
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
15
|
+
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)
|
|
16
|
+
mask = offset < n_elements
|
|
17
|
+
|
|
18
|
+
x = tl.load(input_ptr + offset, mask=mask)
|
|
19
|
+
x_fp32 = x.to(tl.float32)
|
|
20
|
+
out = 2.0 * sigmoid(2.0 * x_fp32) - 1.0
|
|
21
|
+
tl.store(output_ptr + offset, out, mask=mask)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Threshold activation — pure @triton.jit kernel. Logic from FlagGems."""
|
|
2
|
+
|
|
3
|
+
import triton
|
|
4
|
+
import triton.language as tl
|
|
5
|
+
|
|
6
|
+
@triton.jit
|
|
7
|
+
def threshold_forward_kernel(
|
|
8
|
+
input_ptr, output_ptr,
|
|
9
|
+
n_elements,
|
|
10
|
+
threshold_val, value,
|
|
11
|
+
BLOCK_SIZE: tl.constexpr,
|
|
12
|
+
):
|
|
13
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
14
|
+
offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
|
|
15
|
+
mask = offset < n_elements
|
|
16
|
+
|
|
17
|
+
x = tl.load(input_ptr + offset, mask=mask)
|
|
18
|
+
out = tl.where(x > threshold_val, x, value)
|
|
19
|
+
tl.store(output_ptr + offset, out, mask=mask)
|
nbxtensor/ops/tiling.yml
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# The TilingEngine's sizes — every engine-wide value a memory split is cut by.
|
|
2
|
+
#
|
|
3
|
+
# Read by the TilingEngine's sizing half and nowhere else — `nbxtensor/ops/tiling_sizes.py`, for
|
|
4
|
+
# both engine branches; a missing key is refused by name. Values that belong to an ARCHITECTURE stay in its hardware
|
|
5
|
+
# profile (config/vendors/<vendor>/<arch>.yml): memory.sdpa_math_max_scores_bytes,
|
|
6
|
+
# memory.sdpa_math_scores_device_fraction, memory.sdpa_math_min_chunk_rows,
|
|
7
|
+
# memory.sdpa_math_max_chunks, tiling.extent_lattice.
|
|
8
|
+
#
|
|
9
|
+
# Each value carries its SOURCE: the reasoning, measurement or workstream that set it.
|
|
10
|
+
|
|
11
|
+
conv3d:
|
|
12
|
+
# 1 GiB. The per-transient bound of the chunked temporal path, and the fold size above which
|
|
13
|
+
# the one-shot path's peak is priced at all: small and validated convolutions never chunk
|
|
14
|
+
# (P-TRITON-LIVE-SET-AUDIT; Allegro-TI2V vae_encoder at 720x1280x12f fp32, 5.66 GB a plane ->
|
|
15
|
+
# 30.4 GB live on a 32 GB V100 in triton only; the decision made Prism's, 2026-09-29).
|
|
16
|
+
chunk_bytes: 1073741824
|
|
17
|
+
# 256 MiB. The fixed slack added to the one-shot path's priced peak (conv3d_need).
|
|
18
|
+
slack_bytes: 268435456
|
|
19
|
+
|
|
20
|
+
conv2d:
|
|
21
|
+
# 4 GiB. A convolution whose output exceeds it streams in bands along H; it leaves headroom for
|
|
22
|
+
# weights, activations and arena overhead on a V100 32 GB (P-SANA-4KPX-RUNTIME Step 1). A
|
|
23
|
+
# one-shot conv3d whose conv2d output exceeds it holds one band's worth more.
|
|
24
|
+
band_bytes: 4294967296
|
|
25
|
+
# Bands of about half the band budget: the other half covers the transient input slice and the
|
|
26
|
+
# kernel's intermediate (P-SANA-4KPX-RUNTIME Step 1, `_conv2d_band_streamed`).
|
|
27
|
+
band_budget_divisor: 2
|
|
28
|
+
|
|
29
|
+
sdpa:
|
|
30
|
+
# 2 GiB. The fp32 scores bound a non-power-of-two head dim routes on when the architecture
|
|
31
|
+
# declares no `memory.sdpa_math_max_scores_bytes` (the scores budget LLM-class prefills chunk
|
|
32
|
+
# under a handful of times: 4k context -> 2 chunks, 16k -> 16; P-NONDET-LONG-ROW).
|
|
33
|
+
non_pow2_head_scores_bytes: 2147483648
|
|
34
|
+
|
|
35
|
+
op_level:
|
|
36
|
+
# 0.85 of the card, minus the component's resident weights: the budget an op's transient is
|
|
37
|
+
# measured against — overflow detection, the op-level plan and the conv3d chunk decision share
|
|
38
|
+
# it, or they disagree about which upsamples are free (`_tiling_aware_zero_alloc_uids`).
|
|
39
|
+
op_budget_card_fraction: 0.85
|
|
40
|
+
# 0.65 of the card, minus the conv output that stays full-resolution allocated: one band's
|
|
41
|
+
# budget for an upsample->conv fusion pair or a standalone convolution (S5, P-SANA-4KPX).
|
|
42
|
+
conv_band_card_fraction: 0.65
|
|
43
|
+
# 256 MB: the smallest per-band budget a band factor is computed against (a budget under it,
|
|
44
|
+
# "< 256 MB usable", is raised to it).
|
|
45
|
+
band_budget_floor_bytes: 268435456
|
|
46
|
+
# A tiled op runs in at least two bands.
|
|
47
|
+
min_band_factor: 2
|
|
48
|
+
# Band factors round up to a power of two for halo alignment, at most 64.
|
|
49
|
+
max_band_factor: 64
|
|
50
|
+
# An upsample whose output exceeds 25 % of the card is worth fusing into its conv even when the
|
|
51
|
+
# conv does not overflow (typical: 16 GB on a 32 GB card).
|
|
52
|
+
upsample_overflow_card_fraction: 0.25
|
|
53
|
+
rms_norm:
|
|
54
|
+
# 20 % of the card: an rms_norm whose output exceeds it runs in H bands — a stricter bound
|
|
55
|
+
# skipped the exactly-8 GB tensors of Sana 4Kpx on a 32 GB card.
|
|
56
|
+
overflow_card_fraction: 0.20
|
|
57
|
+
# One band's budget: 0.10 of the card (tightened from 0.65 because S5 chains carry 5-7 GiB of
|
|
58
|
+
# state into the rms_norm dispatch and each band's fp32 cast must fit beside it; the comment
|
|
59
|
+
# beside the code said 0.20, the code has carried 0.10).
|
|
60
|
+
band_card_fraction: 0.10
|
|
61
|
+
# At least four bands.
|
|
62
|
+
min_band_factor: 4
|
|
63
|
+
# At most eight: sixteen produced a numerically wrong output at Sana 4Kpx's rms_norm::27
|
|
64
|
+
# (post-chain wrapper, NHWC view of non-contiguous storage); eight was validated on 32 GB.
|
|
65
|
+
max_band_factor: 8
|
|
66
|
+
residual_chain:
|
|
67
|
+
# A residual chain (fork -> >=3 ops -> merge) streams in bands of at most 1 GiB at runtime
|
|
68
|
+
# (P-PRISM-NEVER-REFUSE v2 S5, 2026-05-13).
|
|
69
|
+
band_target_bytes: 1073741824
|
|
70
|
+
# A chain streams in at least two bands (the solver's chain rule carried the conv band floor,
|
|
71
|
+
# 2, so a change of that floor moved this one silently; it is its own value now).
|
|
72
|
+
min_band_factor: 2
|
|
73
|
+
# Its band factor rounds up to a power of two, at most 32.
|
|
74
|
+
max_band_factor: 32
|
|
75
|
+
# 1.6 GB: a chain is detected only when its base tensor (fp32, conservative) reaches it —
|
|
76
|
+
# 1.6 GB at fp32, ~0.8 GB at bf16 (S5).
|
|
77
|
+
min_base_bytes_fp32: 1600000000
|
|
78
|
+
|
|
79
|
+
overlap:
|
|
80
|
+
# A tile's overlap is its extent // 8, at least 4 to ensure some blending (TilingEngine's
|
|
81
|
+
# data-driven init; Prism's decode and encode tilings follow the same proportional law).
|
|
82
|
+
spatial_divisor: 8
|
|
83
|
+
spatial_min: 4
|
|
84
|
+
# A temporal tile overlaps its neighbour by t_tile // 4 frames (Prism's linear-class tiling).
|
|
85
|
+
temporal_divisor: 4
|
|
86
|
+
|
|
87
|
+
inplace:
|
|
88
|
+
# 1 GiB. A residual add or an element-wise unary writes into the buffer of its dead input when
|
|
89
|
+
# its output reaches it (P-SANA-4KPX-RUNTIME 2026-05-05, multi-branch fusion fix vector B; the
|
|
90
|
+
# unary rewrite uses the same figure, real-esrgan-x8 at 1024x1024 on a 16 GB V100).
|
|
91
|
+
min_bytes: 1073741824
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""The tiling policy's default: the split sizes the tiling rules read (`tiling.yml`, beside this module).
|
|
2
|
+
|
|
3
|
+
The library owns the file and reads it itself, so the rules run with no application around them. A caller may set
|
|
4
|
+
its own table (`set_tiling`, plain data; `None` restores the library's); NeuroBrix reads this same file through the
|
|
5
|
+
library's `tiling_sizes`. A missing file is refused by name: no split is ever cut by a size the data
|
|
6
|
+
does not state.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import copy
|
|
11
|
+
import functools
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any, Dict, Optional
|
|
14
|
+
|
|
15
|
+
_FILE = Path(__file__).resolve().parent / "tiling.yml"
|
|
16
|
+
|
|
17
|
+
__all__ = ["tiling_table", "set_tiling"]
|
|
18
|
+
|
|
19
|
+
_SET: Dict[str, Any] = {} # {"table": dict} once a caller set one
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@functools.lru_cache(maxsize=1)
|
|
23
|
+
def _raw() -> Dict[str, Any]:
|
|
24
|
+
import yaml
|
|
25
|
+
if not _FILE.is_file():
|
|
26
|
+
raise FileNotFoundError(f"ZERO FALLBACK: the tiling policy is not found: {_FILE}")
|
|
27
|
+
return yaml.safe_load(_FILE.read_text()) or {}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def tiling_table() -> Dict[str, Any]:
|
|
31
|
+
"""The policy in force: the table a caller set, else the library's file (a copy: the caller may not edit it)."""
|
|
32
|
+
return copy.deepcopy(_SET["table"] if "table" in _SET else _raw())
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def set_tiling(table: Optional[Dict[str, Any]]) -> None:
|
|
36
|
+
"""Set the split sizes the tiling rules read (a whole table, as `tiling.yml` writes it); `None` restores the
|
|
37
|
+
library's own."""
|
|
38
|
+
if table is None:
|
|
39
|
+
_SET.clear()
|
|
40
|
+
elif not isinstance(table, dict):
|
|
41
|
+
raise TypeError(f"set_tiling: a table is a dict as tiling.yml writes it, not {type(table).__name__}")
|
|
42
|
+
else:
|
|
43
|
+
_SET["table"] = copy.deepcopy(table)
|