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/addr.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Addr (outer product add) — pure @triton.jit kernel.
|
|
2
|
+
|
|
3
|
+
Computes: output = beta * input + alpha * (vec1 outer vec2)
|
|
4
|
+
|
|
5
|
+
Where vec1 is [M], vec2 is [N], input is [M, N] (broadcast-compatible),
|
|
6
|
+
and output is [M, N].
|
|
7
|
+
|
|
8
|
+
Extracted from FlagGems reference (addr.py).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import triton
|
|
12
|
+
import triton.language as tl
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@triton.jit(do_not_specialize=['beta', 'alpha'])
|
|
16
|
+
def addr_kernel(
|
|
17
|
+
input_ptr,
|
|
18
|
+
vec1_ptr,
|
|
19
|
+
vec2_ptr,
|
|
20
|
+
output_ptr,
|
|
21
|
+
beta,
|
|
22
|
+
alpha,
|
|
23
|
+
M, N,
|
|
24
|
+
stride_input_m,
|
|
25
|
+
stride_input_n,
|
|
26
|
+
stride_vec1,
|
|
27
|
+
stride_vec2,
|
|
28
|
+
stride_output_m,
|
|
29
|
+
stride_output_n,
|
|
30
|
+
BLOCK_M: tl.constexpr,
|
|
31
|
+
BLOCK_N: tl.constexpr,
|
|
32
|
+
):
|
|
33
|
+
"""Outer product add: out = beta * input + alpha * (vec1 outer vec2).
|
|
34
|
+
|
|
35
|
+
Grid: (cdiv(M, BLOCK_M), cdiv(N, BLOCK_N))
|
|
36
|
+
"""
|
|
37
|
+
pid_m = tl.program_id(0).to(tl.int64)
|
|
38
|
+
pid_n = tl.program_id(1).to(tl.int64)
|
|
39
|
+
|
|
40
|
+
offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
|
|
41
|
+
offs_n = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)
|
|
42
|
+
|
|
43
|
+
mask_m = offs_m < M
|
|
44
|
+
mask_n = offs_n < N
|
|
45
|
+
mask_2d = mask_m[:, None] & mask_n[None, :]
|
|
46
|
+
|
|
47
|
+
# Load vectors
|
|
48
|
+
v1 = tl.load(vec1_ptr + offs_m * stride_vec1, mask=mask_m, other=0.0).to(tl.float32)
|
|
49
|
+
v2 = tl.load(vec2_ptr + offs_n * stride_vec2, mask=mask_n, other=0.0).to(tl.float32)
|
|
50
|
+
|
|
51
|
+
# Load input matrix
|
|
52
|
+
input_ptrs = (
|
|
53
|
+
input_ptr
|
|
54
|
+
+ offs_m[:, None] * stride_input_m
|
|
55
|
+
+ offs_n[None, :] * stride_input_n
|
|
56
|
+
)
|
|
57
|
+
inp = tl.load(input_ptrs, mask=mask_2d, other=0.0).to(tl.float32)
|
|
58
|
+
|
|
59
|
+
# Compute: beta * input + alpha * outer(vec1, vec2)
|
|
60
|
+
result = beta * inp + alpha * (v1[:, None] * v2[None, :])
|
|
61
|
+
|
|
62
|
+
# Store
|
|
63
|
+
output_ptrs = (
|
|
64
|
+
output_ptr
|
|
65
|
+
+ offs_m[:, None] * stride_output_m
|
|
66
|
+
+ offs_n[None, :] * stride_output_n
|
|
67
|
+
)
|
|
68
|
+
tl.store(output_ptrs, result, mask=mask_2d)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""All reduction (logical AND) — pure @triton.jit kernels.
|
|
2
|
+
|
|
3
|
+
Tests if ALL elements evaluate to True (non-zero).
|
|
4
|
+
Global two-pass reduction and dim-specific kernel.
|
|
5
|
+
Extracted from FlagGems (Apache-2.0).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import triton
|
|
9
|
+
import triton.language as tl
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@triton.jit
|
|
13
|
+
def reduce_all(a, b):
|
|
14
|
+
return a & b
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Global reduction: two-pass
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
@triton.jit
|
|
22
|
+
def all_kernel_mid(
|
|
23
|
+
inp,
|
|
24
|
+
mid,
|
|
25
|
+
n_elements,
|
|
26
|
+
mid_size,
|
|
27
|
+
BLOCK_SIZE: tl.constexpr,
|
|
28
|
+
):
|
|
29
|
+
"""Pass 1: check if all elements in this block are non-zero."""
|
|
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
|
+
inp_ptrs = inp + offset
|
|
33
|
+
mask = offset < n_elements
|
|
34
|
+
inp_val = tl.load(inp_ptrs, mask=mask, other=1.0)
|
|
35
|
+
all_val = tl.reduce(inp_val != 0, axis=0, combine_fn=reduce_all)
|
|
36
|
+
mid_ptr = mid + pid
|
|
37
|
+
tl.store(mid_ptr, all_val)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@triton.jit
|
|
41
|
+
def all_kernel_result(mid, out, MID_SIZE, BLOCK_MID: tl.constexpr):
|
|
42
|
+
"""Pass 2: combine partial results into scalar bool."""
|
|
43
|
+
offset = tl.arange(0, BLOCK_MID)
|
|
44
|
+
mid_ptrs = mid + offset
|
|
45
|
+
mask = offset < MID_SIZE
|
|
46
|
+
mid_val = tl.load(mid_ptrs, mask=mask, other=1).to(tl.int1)
|
|
47
|
+
all_val = tl.reduce(mid_val, axis=0, combine_fn=reduce_all)
|
|
48
|
+
tl.store(out, all_val)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
# Dim-specific: all along one axis
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
@triton.jit
|
|
56
|
+
def all_kernel_dim(
|
|
57
|
+
inp,
|
|
58
|
+
out,
|
|
59
|
+
M,
|
|
60
|
+
N,
|
|
61
|
+
BLOCK_M: tl.constexpr,
|
|
62
|
+
BLOCK_N: tl.constexpr,
|
|
63
|
+
):
|
|
64
|
+
"""Check all non-zero along compressed inner dim N.
|
|
65
|
+
|
|
66
|
+
inp: [M, N] (dim-compressed) → out: [M] (bool)
|
|
67
|
+
"""
|
|
68
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
69
|
+
rows = pid * BLOCK_M + tl.arange(0, BLOCK_M)[:, None]
|
|
70
|
+
inp = inp + rows * N
|
|
71
|
+
out = out + rows
|
|
72
|
+
row_mask = rows < M
|
|
73
|
+
|
|
74
|
+
_all = tl.full([BLOCK_M, BLOCK_N], value=1, dtype=tl.int1)
|
|
75
|
+
for off in range(0, N, BLOCK_N):
|
|
76
|
+
cols = off + tl.arange(0, BLOCK_N)[None, :]
|
|
77
|
+
col_mask = cols < N
|
|
78
|
+
mask = row_mask & col_mask
|
|
79
|
+
|
|
80
|
+
a = tl.load(inp + cols, mask, other=1.0)
|
|
81
|
+
_all = _all & (a != 0)
|
|
82
|
+
result = tl.reduce(_all, axis=1, combine_fn=reduce_all)
|
|
83
|
+
tl.store(out, result[:, None], row_mask)
|
nbxtensor/ops/amax.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Max 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 amax_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
|
+
"""Max 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=-float('inf'))
|
|
33
|
+
result = tl.max(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=-float('inf'))
|
|
39
|
+
result = tl.maximum(result, tl.max(inp, axis=1))
|
|
40
|
+
tl.store(output_ptr + batch_offset, result, mask=batch_mask)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Any reduction (logical OR) — pure @triton.jit kernels.
|
|
2
|
+
|
|
3
|
+
Tests if ANY element evaluates to True (non-zero).
|
|
4
|
+
Global two-pass reduction and dim-specific kernel.
|
|
5
|
+
Extracted from FlagGems (Apache-2.0).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import triton
|
|
9
|
+
import triton.language as tl
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@triton.jit
|
|
13
|
+
def reduce_any(a, b):
|
|
14
|
+
return a | b
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Global reduction: two-pass
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
@triton.jit
|
|
22
|
+
def any_kernel_mid(
|
|
23
|
+
inp,
|
|
24
|
+
mid,
|
|
25
|
+
n_elements,
|
|
26
|
+
mid_size,
|
|
27
|
+
BLOCK_SIZE: tl.constexpr,
|
|
28
|
+
):
|
|
29
|
+
"""Pass 1: check if any element in this block is non-zero."""
|
|
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
|
+
inp_ptrs = inp + offset
|
|
33
|
+
mask = offset < n_elements
|
|
34
|
+
inp_val = tl.load(inp_ptrs, mask=mask, other=0.0)
|
|
35
|
+
any_val = tl.reduce(inp_val != 0, axis=0, combine_fn=reduce_any)
|
|
36
|
+
mid_ptr = mid + pid
|
|
37
|
+
tl.store(mid_ptr, any_val)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@triton.jit
|
|
41
|
+
def any_kernel_result(mid, out, MID_SIZE, BLOCK_MID: tl.constexpr):
|
|
42
|
+
"""Pass 2: combine partial results into scalar bool."""
|
|
43
|
+
offset = tl.arange(0, BLOCK_MID)
|
|
44
|
+
mid_ptrs = mid + offset
|
|
45
|
+
mask = offset < MID_SIZE
|
|
46
|
+
mid_val = tl.load(mid_ptrs, mask=mask, other=0).to(tl.int1)
|
|
47
|
+
any_val = tl.reduce(mid_val, axis=0, combine_fn=reduce_any)
|
|
48
|
+
tl.store(out, any_val)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
# Dim-specific: any along one axis
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
@triton.jit
|
|
56
|
+
def any_kernel_dim(
|
|
57
|
+
inp,
|
|
58
|
+
out,
|
|
59
|
+
M,
|
|
60
|
+
N,
|
|
61
|
+
BLOCK_M: tl.constexpr,
|
|
62
|
+
BLOCK_N: tl.constexpr,
|
|
63
|
+
):
|
|
64
|
+
"""Check any non-zero along compressed inner dim N.
|
|
65
|
+
|
|
66
|
+
inp: [M, N] (dim-compressed) → out: [M] (bool)
|
|
67
|
+
"""
|
|
68
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
69
|
+
rows = pid * BLOCK_M + tl.arange(0, BLOCK_M)[:, None]
|
|
70
|
+
inp = inp + rows * N
|
|
71
|
+
out = out + rows
|
|
72
|
+
row_mask = rows < M
|
|
73
|
+
|
|
74
|
+
_any = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.int1)
|
|
75
|
+
for off in range(0, N, BLOCK_N):
|
|
76
|
+
cols = off + tl.arange(0, BLOCK_N)[None, :]
|
|
77
|
+
col_mask = cols < N
|
|
78
|
+
mask = row_mask & col_mask
|
|
79
|
+
|
|
80
|
+
a = tl.load(inp + cols, mask, other=0.0)
|
|
81
|
+
_any = _any | (a != 0)
|
|
82
|
+
result = tl.reduce(_any, axis=1, combine_fn=reduce_any)
|
|
83
|
+
tl.store(out, result[:, None], row_mask)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Arange — pure @triton.jit kernel.
|
|
2
|
+
|
|
3
|
+
Ported from FlagGems arange_func (Apache-2.0 license).
|
|
4
|
+
Generates sequential values: start, start+step, start+2*step, ...
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import triton
|
|
8
|
+
import triton.language as tl
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@triton.jit
|
|
12
|
+
def arange_kernel(
|
|
13
|
+
output_ptr,
|
|
14
|
+
start,
|
|
15
|
+
step,
|
|
16
|
+
n_elements,
|
|
17
|
+
BLOCK_SIZE: tl.constexpr,
|
|
18
|
+
):
|
|
19
|
+
"""Generate sequential values: output[i] = start + i * step."""
|
|
20
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
21
|
+
block_start = pid * BLOCK_SIZE
|
|
22
|
+
offsets = tl.arange(0, BLOCK_SIZE)
|
|
23
|
+
idx = block_start + offsets
|
|
24
|
+
mask = idx < n_elements
|
|
25
|
+
|
|
26
|
+
value = start + idx * step
|
|
27
|
+
tl.store(output_ptr + idx, value, mask=mask)
|
nbxtensor/ops/argmax.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Argmax — pure @triton.jit kernels. Extracted from FlagGems.
|
|
2
|
+
|
|
3
|
+
Three-kernel approach:
|
|
4
|
+
argmax_kernel_1: per-block max reduction (flat tensor, dim=None)
|
|
5
|
+
argmax_kernel_2: final reduction across blocks (flat tensor, dim=None)
|
|
6
|
+
argmax_kernel_inner: along last dim (dim=-1)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import triton
|
|
10
|
+
import triton.language as tl
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@triton.jit
|
|
14
|
+
def argmax_kernel_1(
|
|
15
|
+
inp,
|
|
16
|
+
mid_value,
|
|
17
|
+
mid_index,
|
|
18
|
+
M,
|
|
19
|
+
BLOCK_SIZE: tl.constexpr,
|
|
20
|
+
):
|
|
21
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
22
|
+
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)
|
|
23
|
+
inp_ptrs = inp + offset
|
|
24
|
+
mask = offset < M
|
|
25
|
+
inp_val = tl.load(inp_ptrs, mask=mask, other=float('-inf'))
|
|
26
|
+
max_val, max_index = tl.max(inp_val, axis=0, return_indices=True)
|
|
27
|
+
max_index = max_index + pid * BLOCK_SIZE
|
|
28
|
+
mid_value_ptr = mid_value + pid
|
|
29
|
+
max_index_ptr = mid_index + pid
|
|
30
|
+
tl.store(mid_value_ptr, max_val)
|
|
31
|
+
tl.store(max_index_ptr, max_index)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@triton.jit
|
|
35
|
+
def argmax_kernel_2(mid_value, mid_index, out, mid_size, BLOCK_MID: tl.constexpr):
|
|
36
|
+
offset = tl.arange(0, BLOCK_MID)
|
|
37
|
+
mid_ptrs = mid_value + offset
|
|
38
|
+
mask = offset < mid_size
|
|
39
|
+
mid_val = tl.load(mid_ptrs, mask=mask, other=float('-inf'))
|
|
40
|
+
index_val = tl.argmax(mid_val, axis=0)
|
|
41
|
+
mid_index_ptrs = mid_index + index_val
|
|
42
|
+
out_val = tl.load(mid_index_ptrs)
|
|
43
|
+
tl.store(out, out_val)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@triton.jit
|
|
47
|
+
def argmax_kernel_inner(
|
|
48
|
+
inp,
|
|
49
|
+
out_index,
|
|
50
|
+
M,
|
|
51
|
+
N,
|
|
52
|
+
TILE_N: tl.constexpr,
|
|
53
|
+
ONE_TILE_PER_CTA: tl.constexpr,
|
|
54
|
+
):
|
|
55
|
+
"""Argmax along the innermost (last) dimension."""
|
|
56
|
+
pid_m = tl.program_id(0).to(tl.int64)
|
|
57
|
+
|
|
58
|
+
min_value = float('-inf')
|
|
59
|
+
|
|
60
|
+
if ONE_TILE_PER_CTA:
|
|
61
|
+
n_offset = tl.arange(0, TILE_N)
|
|
62
|
+
offset = pid_m * N + n_offset
|
|
63
|
+
mask = n_offset < N
|
|
64
|
+
inp_ptrs = inp + offset
|
|
65
|
+
inp_vals = tl.load(inp_ptrs, mask=mask, other=min_value)
|
|
66
|
+
local_max, local_argmax = tl.max(
|
|
67
|
+
inp_vals, 0, return_indices=True, return_indices_tie_break_left=True
|
|
68
|
+
)
|
|
69
|
+
out_index_ptrs = out_index + pid_m
|
|
70
|
+
tl.store(out_index_ptrs, local_argmax)
|
|
71
|
+
else:
|
|
72
|
+
max_values = min_value
|
|
73
|
+
argmax_values = 0
|
|
74
|
+
|
|
75
|
+
loop_time = N // TILE_N
|
|
76
|
+
remainder = N % TILE_N
|
|
77
|
+
for start_n in range(0, loop_time):
|
|
78
|
+
n_offset = start_n * TILE_N + tl.arange(0, TILE_N)
|
|
79
|
+
offset = pid_m * N + n_offset
|
|
80
|
+
inp_ptrs = inp + offset
|
|
81
|
+
inp_vals = tl.load(inp_ptrs)
|
|
82
|
+
local_max, local_argmax = tl.max(
|
|
83
|
+
inp_vals, 0, return_indices=True, return_indices_tie_break_left=True
|
|
84
|
+
)
|
|
85
|
+
update = local_max > max_values
|
|
86
|
+
max_values = tl.where(update, local_max, max_values)
|
|
87
|
+
argmax_values = tl.where(
|
|
88
|
+
update, start_n * TILE_N + local_argmax, argmax_values
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if remainder:
|
|
92
|
+
n_offset = loop_time * TILE_N + tl.arange(0, TILE_N)
|
|
93
|
+
offset = pid_m * N + n_offset
|
|
94
|
+
mask = n_offset < N
|
|
95
|
+
inp_ptrs = inp + offset
|
|
96
|
+
inp_vals = tl.load(inp_ptrs, mask=mask, other=min_value)
|
|
97
|
+
local_max, local_argmax = tl.max(
|
|
98
|
+
inp_vals, 0, return_indices=True, return_indices_tie_break_left=True
|
|
99
|
+
)
|
|
100
|
+
update = local_max > max_values
|
|
101
|
+
max_values = tl.where(update, local_max, max_values)
|
|
102
|
+
argmax_values = tl.where(
|
|
103
|
+
update, loop_time * TILE_N + local_argmax, argmax_values
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
out_index_ptrs = out_index + pid_m
|
|
107
|
+
tl.store(out_index_ptrs, argmax_values)
|
nbxtensor/ops/argmin.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Argmin — pure @triton.jit kernels. Extracted from FlagGems.
|
|
2
|
+
|
|
3
|
+
Three-kernel approach:
|
|
4
|
+
argmin_kernel_1: per-block min reduction (flat tensor, dim=None)
|
|
5
|
+
argmin_kernel_2: final reduction across blocks (flat tensor, dim=None)
|
|
6
|
+
argmin_kernel: along arbitrary dim (MxNxK layout)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import triton
|
|
10
|
+
import triton.language as tl
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@triton.jit
|
|
14
|
+
def argmin_kernel_1(
|
|
15
|
+
inp,
|
|
16
|
+
mid_value,
|
|
17
|
+
mid_index,
|
|
18
|
+
M,
|
|
19
|
+
BLOCK_SIZE: tl.constexpr,
|
|
20
|
+
):
|
|
21
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
22
|
+
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)
|
|
23
|
+
inp_ptrs = inp + offset
|
|
24
|
+
mask = offset < M
|
|
25
|
+
|
|
26
|
+
inp_val = tl.load(inp_ptrs, mask=mask, other=float('inf'))
|
|
27
|
+
min_val, min_index = tl.min(inp_val, axis=0, return_indices=True)
|
|
28
|
+
min_index = min_index + pid * BLOCK_SIZE
|
|
29
|
+
mid_value_ptr = mid_value + pid
|
|
30
|
+
min_index_ptr = mid_index + pid
|
|
31
|
+
tl.store(mid_value_ptr, min_val)
|
|
32
|
+
tl.store(min_index_ptr, min_index)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@triton.jit
|
|
36
|
+
def argmin_kernel_2(
|
|
37
|
+
mid_value,
|
|
38
|
+
mid_index,
|
|
39
|
+
out,
|
|
40
|
+
mid_size,
|
|
41
|
+
BLOCK_MID: tl.constexpr,
|
|
42
|
+
):
|
|
43
|
+
offset = tl.arange(0, BLOCK_MID)
|
|
44
|
+
mid_ptrs = mid_value + offset
|
|
45
|
+
mask = offset < mid_size
|
|
46
|
+
mid_val = tl.load(mid_ptrs, mask=mask, other=float('inf'))
|
|
47
|
+
index_val = tl.argmin(mid_val, axis=0)
|
|
48
|
+
mid_index_ptrs = mid_index + index_val
|
|
49
|
+
out_val = tl.load(mid_index_ptrs)
|
|
50
|
+
tl.store(out, out_val)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@triton.jit
|
|
54
|
+
def argmin_kernel(
|
|
55
|
+
inp,
|
|
56
|
+
out_index,
|
|
57
|
+
M,
|
|
58
|
+
N,
|
|
59
|
+
K,
|
|
60
|
+
BLOCK_M: tl.constexpr,
|
|
61
|
+
BLOCK_N: tl.constexpr,
|
|
62
|
+
):
|
|
63
|
+
"""Argmin along an arbitrary dimension.
|
|
64
|
+
|
|
65
|
+
Input is viewed as [M, N, K] where N is the reduction dim.
|
|
66
|
+
Output shape is [M, K].
|
|
67
|
+
"""
|
|
68
|
+
pid_m = tl.program_id(0).to(tl.int64)
|
|
69
|
+
pid_k = tl.program_id(1).to(tl.int64)
|
|
70
|
+
m_offset = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
|
|
71
|
+
|
|
72
|
+
dtype = inp.type.element_ty
|
|
73
|
+
acc_type = tl.float32 if dtype is tl.bfloat16 else dtype
|
|
74
|
+
max_value = float('inf')
|
|
75
|
+
min_values = tl.full([BLOCK_M], dtype=acc_type, value=max_value)
|
|
76
|
+
argmin_values = tl.full([BLOCK_M], dtype=tl.int64, value=0)
|
|
77
|
+
for start_n in range(0, N, BLOCK_N):
|
|
78
|
+
n_offset = start_n + tl.arange(0, BLOCK_N)
|
|
79
|
+
offset = m_offset[:, None] * N * K + n_offset[None, :] * K + pid_k
|
|
80
|
+
mask = (m_offset[:, None] < M) & (n_offset[None, :] < N)
|
|
81
|
+
inp_ptrs = inp + offset
|
|
82
|
+
inp_vals = tl.load(inp_ptrs, mask=mask, other=max_value)
|
|
83
|
+
local_min, local_argmin = tl.min(
|
|
84
|
+
inp_vals, 1, return_indices=True, return_indices_tie_break_left=True
|
|
85
|
+
)
|
|
86
|
+
update = local_min < min_values
|
|
87
|
+
min_values = tl.where(update, local_min, min_values)
|
|
88
|
+
argmin_values = tl.where(update, start_n + local_argmin, argmin_values)
|
|
89
|
+
|
|
90
|
+
offset_index = m_offset * K + pid_k
|
|
91
|
+
out_index_ptrs = out_index + offset_index
|
|
92
|
+
mask1 = m_offset < M
|
|
93
|
+
tl.store(out_index_ptrs, argmin_values, mask=mask1)
|
nbxtensor/ops/atan2.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""atan2(y, x) — pure @triton.jit kernel (element-wise, fp32).
|
|
2
|
+
|
|
3
|
+
`tl.extra.CUDA.libdevice.atan2` stood here. That namespace is NVIDIA's device
|
|
4
|
+
library and does not lower on any other backend: Kokoro-82M died at
|
|
5
|
+
`aten.angle::0` (1, 11, 15361) on triton-ext with "PassManager::run failed",
|
|
6
|
+
`angle` being atan2(imag, real). Triton 3.8.0 exposes no portable `atan` either
|
|
7
|
+
(`tl.math` has abs, ceil, cos, div_rn, erf, exp, exp2, fdiv, floor, fma, log,
|
|
8
|
+
log2, rsqrt, sin, sqrt, sqrt_rn, umulhi), so the function is built here.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import triton
|
|
12
|
+
import triton.language as tl
|
|
13
|
+
|
|
14
|
+
# Triton only lets a @jit kernel read a global that is a constexpr.
|
|
15
|
+
_PI = tl.constexpr(3.14159265358979323846)
|
|
16
|
+
_PI_2 = tl.constexpr(1.57079632679489661923)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@triton.jit
|
|
20
|
+
def _atan_unit(z):
|
|
21
|
+
"""atan(z) for |z| <= 1, odd minimax polynomial in z^2.
|
|
22
|
+
|
|
23
|
+
Degree-17 odd fit (the classic SunPro/Cephes coefficients). A degree-9 fit
|
|
24
|
+
was tried first and measured 1.167e-05 max absolute error against numpy over
|
|
25
|
+
all four quadrants — too coarse for a phase feeding audio synthesis, which
|
|
26
|
+
is what `aten::angle` is here. This one is checked in the probe beside this
|
|
27
|
+
file, not asserted in the kernel.
|
|
28
|
+
"""
|
|
29
|
+
z2 = z * z
|
|
30
|
+
p = 0.0028662257
|
|
31
|
+
p = -0.0161657367 + z2 * p
|
|
32
|
+
p = 0.0429096138 + z2 * p
|
|
33
|
+
p = -0.0752896400 + z2 * p
|
|
34
|
+
p = 0.1065626393 + z2 * p
|
|
35
|
+
p = -0.1420889944 + z2 * p
|
|
36
|
+
p = 0.1999355085 + z2 * p
|
|
37
|
+
p = -0.3333314528 + z2 * p
|
|
38
|
+
return z + z * z2 * p
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@triton.jit
|
|
42
|
+
def _atan(z):
|
|
43
|
+
"""atan(z) over the whole line: fold |z| > 1 onto the unit interval."""
|
|
44
|
+
a = tl.abs(z)
|
|
45
|
+
big = a > 1.0
|
|
46
|
+
# for |z| > 1, atan(z) = pi/2 - atan(1/z), with the sign carried outside
|
|
47
|
+
u = tl.where(big, 1.0 / a, a)
|
|
48
|
+
r = _atan_unit(u)
|
|
49
|
+
r = tl.where(big, _PI_2 - r, r)
|
|
50
|
+
return tl.where(z < 0, -r, r)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@triton.jit
|
|
54
|
+
def atan2_kernel(y_ptr, x_ptr, out_ptr, n_elements, BLOCK_SIZE: tl.constexpr):
|
|
55
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
56
|
+
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)
|
|
57
|
+
mask = offs < n_elements
|
|
58
|
+
y = tl.load(y_ptr + offs, mask=mask).to(tl.float32)
|
|
59
|
+
x = tl.load(x_ptr + offs, mask=mask).to(tl.float32)
|
|
60
|
+
|
|
61
|
+
# Quadrant reconstruction, matching numpy/libm atan2:
|
|
62
|
+
# x > 0 atan(y/x)
|
|
63
|
+
# x < 0, y >= 0 atan(y/x) + pi
|
|
64
|
+
# x < 0, y < 0 atan(y/x) - pi
|
|
65
|
+
# x = 0, y > 0 +pi/2 x = 0, y < 0 -pi/2 x = y = 0 0
|
|
66
|
+
safe_x = tl.where(x == 0, 1.0, x)
|
|
67
|
+
base = _atan(y / safe_x)
|
|
68
|
+
shifted = base + tl.where(y >= 0, _PI, -_PI)
|
|
69
|
+
on_axis = tl.where(y > 0, _PI_2, tl.where(y < 0, -_PI_2, 0.0))
|
|
70
|
+
out = tl.where(x > 0, base, tl.where(x < 0, shifted, on_axis))
|
|
71
|
+
tl.store(out_ptr + offs, out, mask=mask)
|