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