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