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,845 @@
|
|
|
1
|
+
"""Reduction wrappers: sum, mean, prod, min/max, argmin/argmax, all/any, std/var, cumulative scans. Cut out of wrappers.py by family (M2, 2026-10-29), unchanged; shared launch layer and run context stay in wrappers.py."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import triton
|
|
7
|
+
from nbxtensor.ops.autotune_bucket import bucket_of as _bucket_of
|
|
8
|
+
from nbxtensor.ops import launch_keys as _lk
|
|
9
|
+
from nbxtensor.tensor import NBXTensor
|
|
10
|
+
from nbxtensor.dtype.nbx_dtype import NBXDtype, dtype_size
|
|
11
|
+
from nbxtensor.memory.allocator import DeviceAllocator
|
|
12
|
+
from nbxtensor.backend.runtime import set_device
|
|
13
|
+
from nbxtensor.shape import MAX_NDIM as _NBX_MAX_NDIM, broadcast_shapes, max_linear_offset
|
|
14
|
+
from nbxtensor.dtype.itemsize import canonical_name
|
|
15
|
+
from nbxtensor.dtype.promotion import binary_result, float_math_input
|
|
16
|
+
from nbxtensor.dtype.nbx_dtype import parse_dtype
|
|
17
|
+
from nbxtensor.memory.allocator import DeviceOOMError
|
|
18
|
+
from nbxtensor.backend.capabilities import fa_min_tile as _fa_min_tile
|
|
19
|
+
from nbxtensor.backend.capabilities import reduce_tile_max as _reduce_tile_max
|
|
20
|
+
from nbxtensor.backend.faults import device_fault_buffer, device_fault_code_cached, fault_channel
|
|
21
|
+
from nbxtensor.tensor import _upload_int64_array as _nbx_upload_int64, _saturating_cast as _nbx_saturating_cast
|
|
22
|
+
from nbxtensor.ops._configs import sdpa_block_ceiling as _sdpa_block_ceiling
|
|
23
|
+
from nbxtensor.ops._configs import sdpa_launch_meta as _sdpa_launch_meta
|
|
24
|
+
from nbxtensor.ops._configs import matrix_unit as _matrix_unit, matrix_unit_mm_tile as _matrix_unit_mm_tile
|
|
25
|
+
from nbxtensor.ops._configs import largest_tile_within_smem as _largest_tile_within_smem
|
|
26
|
+
from nbxtensor.backend import launcher as _nbx_launcher
|
|
27
|
+
from nbxtensor.backend.launcher import install as _install_launcher
|
|
28
|
+
from nbxtensor.ops.relu import relu_forward_kernel
|
|
29
|
+
from nbxtensor.ops.silu import silu_forward_kernel
|
|
30
|
+
from nbxtensor.ops.gelu import gelu_forward_kernel
|
|
31
|
+
from nbxtensor.ops.sigmoid import sigmoid_forward_kernel
|
|
32
|
+
from nbxtensor.ops.tanh import tanh_forward_kernel
|
|
33
|
+
from nbxtensor.ops.hardsigmoid import hardsigmoid_forward_kernel
|
|
34
|
+
from nbxtensor.ops.hardswish import hardswish_forward_kernel
|
|
35
|
+
from nbxtensor.ops.leaky_relu import leaky_relu_forward_kernel
|
|
36
|
+
from nbxtensor.ops.elu import elu_forward_kernel
|
|
37
|
+
from nbxtensor.ops.mish import mish_forward_kernel
|
|
38
|
+
from nbxtensor.ops.selu import selu_forward_kernel
|
|
39
|
+
from nbxtensor.ops.neg import neg_forward_kernel
|
|
40
|
+
from nbxtensor.ops.exp import exp_forward_kernel
|
|
41
|
+
from nbxtensor.ops.sin import sin_forward_kernel
|
|
42
|
+
from nbxtensor.ops.cos import cos_forward_kernel
|
|
43
|
+
from nbxtensor.ops.rsqrt import rsqrt_forward_kernel
|
|
44
|
+
from nbxtensor.ops.sqrt import sqrt_forward_kernel
|
|
45
|
+
from nbxtensor.ops.abs import abs_forward_kernel
|
|
46
|
+
from nbxtensor.ops.log import log_forward_kernel
|
|
47
|
+
from nbxtensor.ops.reciprocal import reciprocal_forward_kernel
|
|
48
|
+
from nbxtensor.ops.pow import pow_forward_kernel
|
|
49
|
+
from nbxtensor.ops.clamp import clamp_forward_kernel
|
|
50
|
+
from nbxtensor.ops.erf import erf_forward_kernel
|
|
51
|
+
from nbxtensor.ops.copy import copy_forward_kernel
|
|
52
|
+
from nbxtensor.ops.add import add_forward_kernel, add_scalar_kernel, add_scalar_dev_kernel, add_bias_broadcast_kernel
|
|
53
|
+
from nbxtensor.ops.binary_strided import add_strided_nd_kernel, mul_strided_nd_kernel, sub_strided_nd_kernel, div_strided_nd_kernel, add_scalar_strided_nd_kernel, mul_scalar_strided_nd_kernel
|
|
54
|
+
from nbxtensor.ops.mul import mul_forward_kernel, mul_scalar_kernel, mul_scalar_dev_kernel
|
|
55
|
+
from nbxtensor.ops.div import div_forward_kernel, div_scalar_kernel, div_scalar_dev_kernel, int_div_kernel
|
|
56
|
+
from nbxtensor.ops.sub import sub_forward_kernel, rsub_forward_kernel
|
|
57
|
+
from nbxtensor.ops.where import where_forward_kernel
|
|
58
|
+
from nbxtensor.ops.maximum import maximum_forward_kernel
|
|
59
|
+
from nbxtensor.ops.minimum import minimum_forward_kernel
|
|
60
|
+
from nbxtensor.ops.masked_fill import masked_fill_forward_kernel
|
|
61
|
+
from nbxtensor.ops.gt import gt_forward_kernel, gt_scalar_kernel
|
|
62
|
+
from nbxtensor.ops.ge import ge_forward_kernel, ge_scalar_kernel
|
|
63
|
+
from nbxtensor.ops.lt import lt_forward_kernel, lt_scalar_kernel
|
|
64
|
+
from nbxtensor.ops.eq import eq_forward_kernel, eq_scalar_kernel
|
|
65
|
+
from nbxtensor.ops.ne import ne_forward_kernel, ne_scalar_kernel
|
|
66
|
+
from nbxtensor.ops.layernorm import layer_norm_forward_kernel
|
|
67
|
+
from nbxtensor.ops.rmsnorm import rms_norm_forward_kernel
|
|
68
|
+
from nbxtensor.ops.softmax import softmax_forward_kernel, softmax_forward_looped_kernel
|
|
69
|
+
from nbxtensor.ops.matmul import matmul_kernel, addmm_kernel
|
|
70
|
+
from nbxtensor.ops._autotune_policy import NBX_FORCE_FP32_ACCUM
|
|
71
|
+
from nbxtensor.ops.fused_moe import fused_moe_kernel, silu_and_mul_kernel, silu_mul_split_kernel
|
|
72
|
+
from nbxtensor.ops.dtype_convert import bf16_to_fp16_kernel
|
|
73
|
+
from nbxtensor.ops.embedding import embedding_kernel, EMBEDDING_OOB
|
|
74
|
+
from nbxtensor.ops.sum import sum_forward_kernel
|
|
75
|
+
from nbxtensor.ops.mean import mean_forward_kernel
|
|
76
|
+
from nbxtensor.ops.amax import amax_forward_kernel
|
|
77
|
+
from nbxtensor.ops.glu import glu_forward_kernel
|
|
78
|
+
from nbxtensor.ops.le import le_forward_kernel, le_scalar_kernel
|
|
79
|
+
from nbxtensor.ops.softplus import softplus_forward_kernel
|
|
80
|
+
from nbxtensor.ops.dropout import dropout_inference_kernel
|
|
81
|
+
from nbxtensor.ops.upsample_nearest2d import upsample_nearest2d_kernel
|
|
82
|
+
from nbxtensor.ops.groupnorm import group_norm_forward_kernel
|
|
83
|
+
from nbxtensor.ops.index_select import index_select_kernel, INDEX_SELECT_OOB
|
|
84
|
+
from nbxtensor.ops.triu import triu_kernel, triu_batch_kernel
|
|
85
|
+
from nbxtensor.ops.tril import tril_kernel, tril_batch_kernel
|
|
86
|
+
from nbxtensor.ops.argmax import argmax_kernel_1, argmax_kernel_2, argmax_kernel_inner
|
|
87
|
+
from nbxtensor.ops.argmin import argmin_kernel_1, argmin_kernel_2, argmin_kernel
|
|
88
|
+
from nbxtensor.ops.conv2d import conv2d_forward_kernel
|
|
89
|
+
from nbxtensor.ops.depthwise_conv2d import depthwise_conv2d_kernel
|
|
90
|
+
from nbxtensor.ops.batch_norm import batch_norm_forward_kernel
|
|
91
|
+
from nbxtensor.ops.cumsum import scan_part_sum_kernel, add_base_sum_kernel
|
|
92
|
+
from nbxtensor.ops.scatter_op import scatter_kernel, scatter_add_kernel, scatter_reduce_amax_kernel, scatter_reduce_amin_kernel
|
|
93
|
+
from nbxtensor.ops.gather_op import gather_kernel
|
|
94
|
+
from nbxtensor.ops.avg_pool2d import avg_pool2d_forward_kernel
|
|
95
|
+
from nbxtensor.ops.max_pool2d import max_pool2d_forward_kernel
|
|
96
|
+
from nbxtensor.ops.max_pool3d import max_pool3d_forward_kernel
|
|
97
|
+
from nbxtensor.ops.cross_entropy import cross_entropy_loss_forward_kernel
|
|
98
|
+
from nbxtensor.ops.exp2 import exp2_forward_kernel
|
|
99
|
+
from nbxtensor.ops.tan import tan_forward_kernel
|
|
100
|
+
from nbxtensor.ops.celu import celu_forward_kernel
|
|
101
|
+
from nbxtensor.ops.log_sigmoid import log_sigmoid_forward_kernel
|
|
102
|
+
from nbxtensor.ops.isfinite import isfinite_forward_kernel
|
|
103
|
+
from nbxtensor.ops.isinf import isinf_forward_kernel
|
|
104
|
+
from nbxtensor.ops.isnan import isnan_forward_kernel
|
|
105
|
+
from nbxtensor.ops.nan_to_num import nan_to_num_forward_kernel
|
|
106
|
+
from nbxtensor.ops.threshold import threshold_forward_kernel
|
|
107
|
+
from nbxtensor.ops.floor import floor_forward_kernel, ceil_forward_kernel, round_forward_kernel, trunc_forward_kernel
|
|
108
|
+
from nbxtensor.ops.addcdiv import addcdiv_forward_kernel
|
|
109
|
+
from nbxtensor.ops.addcmul import addcmul_forward_kernel
|
|
110
|
+
from nbxtensor.ops.all_reduce import all_kernel_mid, all_kernel_result, all_kernel_dim
|
|
111
|
+
from nbxtensor.ops.any_reduce import any_kernel_mid, any_kernel_result, any_kernel_dim
|
|
112
|
+
from nbxtensor.ops.bitwise_and import bitwise_and_forward_kernel
|
|
113
|
+
from nbxtensor.ops.bitwise_or import bitwise_or_forward_kernel
|
|
114
|
+
from nbxtensor.ops.bitwise_not import bitwise_not_forward_kernel
|
|
115
|
+
from nbxtensor.ops.logical_and import logical_and_forward_kernel
|
|
116
|
+
from nbxtensor.ops.logical_or import logical_or_forward_kernel
|
|
117
|
+
from nbxtensor.ops.logical_not import logical_not_forward_kernel
|
|
118
|
+
from nbxtensor.ops.lerp import lerp_tensor_forward_kernel, lerp_scalar_head_kernel, lerp_scalar_tail_kernel
|
|
119
|
+
from nbxtensor.ops.dot_op import dot_kernel_small, dot_kernel_partial, dot_kernel_reduce
|
|
120
|
+
from nbxtensor.ops.flip_op import flip_1d_kernel, flip_strided_kernel
|
|
121
|
+
from nbxtensor.ops.cat_op import cat_copy_kernel_4
|
|
122
|
+
from nbxtensor.ops.fill_op import fill_kernel
|
|
123
|
+
from nbxtensor.ops.arange_op import arange_kernel
|
|
124
|
+
from nbxtensor.ops.prod import prod_kernel_mid, prod_kernel_result, prod_kernel
|
|
125
|
+
from nbxtensor.ops.min_reduce import min_kernel_mid, min_kernel_result, min_kernel
|
|
126
|
+
from nbxtensor.ops.max_reduce import max_kernel_mid, max_kernel_result, max_kernel
|
|
127
|
+
from nbxtensor.ops.baddbmm_op import baddbmm_kernel
|
|
128
|
+
from nbxtensor.ops.addmv_op import addmv_kernel
|
|
129
|
+
from nbxtensor.ops.mse_loss import mse_loss_partial_kernel, mse_loss_reduce_kernel, mse_loss_none_kernel
|
|
130
|
+
from nbxtensor.ops.nllloss import nll_loss_forward_kernel
|
|
131
|
+
from nbxtensor.ops.std import std_map_kernel, std_reduce_kernel, std_dim_kernel
|
|
132
|
+
from nbxtensor.ops.var import var_kernel_1, var_kernel_2, var_welford_kernel
|
|
133
|
+
from nbxtensor.ops.index_add import index_add_gather_kernel
|
|
134
|
+
from nbxtensor.ops.index_put_op import index_put_kernel, INDEX_PUT_OOB
|
|
135
|
+
from nbxtensor.ops.sort_op import (radix_sort_histogram_kernel,
|
|
136
|
+
radix_sort_scatter_kernel,
|
|
137
|
+
radix_sort_tile_counts_kernel,
|
|
138
|
+
radix_sort_tile_prefix_kernel)
|
|
139
|
+
from nbxtensor.ops.rope import rope_forward_kernel
|
|
140
|
+
from nbxtensor.ops.pixel_shuffle import (
|
|
141
|
+
pixel_shuffle_kernel,
|
|
142
|
+
pixel_shuffle_broadcast_aware_kernel,
|
|
143
|
+
)
|
|
144
|
+
from nbxtensor.ops.pixel_unshuffle import pixel_unshuffle_kernel
|
|
145
|
+
from nbxtensor.ops.upsample_bilinear2d import upsample_bilinear2d_kernel
|
|
146
|
+
from nbxtensor.ops.adaptive_avg_pool2d import adaptive_avg_pool2d_kernel
|
|
147
|
+
from nbxtensor.ops.conv_depthwise2d import conv_depthwise2d_kernel
|
|
148
|
+
from nbxtensor.ops.scaled_softmax import scaled_softmax_kernel
|
|
149
|
+
from nbxtensor.ops.vector_norm import (
|
|
150
|
+
l2_norm_kernel, l1_norm_kernel, linf_norm_kernel, l0_norm_kernel, lp_norm_kernel,
|
|
151
|
+
l2_norm_pass1_kernel, l2_norm_pass2_kernel,
|
|
152
|
+
linf_norm_pass1_kernel, linf_norm_pass2_kernel,
|
|
153
|
+
)
|
|
154
|
+
from nbxtensor.ops.addr import addr_kernel
|
|
155
|
+
from nbxtensor.ops.logical_xor import logical_xor_kernel
|
|
156
|
+
from nbxtensor.ops.bitwise_left_shift import bitwise_left_shift_kernel
|
|
157
|
+
from nbxtensor.ops.bitwise_right_shift import bitwise_right_shift_kernel
|
|
158
|
+
from nbxtensor.ops.rand_op import rand_kernel, randn_kernel
|
|
159
|
+
from nbxtensor.ops.clamp_min import clamp_min_forward_kernel
|
|
160
|
+
from nbxtensor.ops.conv_transpose2d import conv_transpose2d_kernel
|
|
161
|
+
from nbxtensor.ops.cummax import scan_part_max_kernel
|
|
162
|
+
from nbxtensor.ops.cummin import scan_part_min_kernel
|
|
163
|
+
from nbxtensor.ops.count_nonzero import count_nonzero_kernel
|
|
164
|
+
from nbxtensor.ops.trace_op import trace_kernel
|
|
165
|
+
from nbxtensor.ops.linspace_op import linspace_kernel
|
|
166
|
+
from nbxtensor.ops.full_op import full_kernel
|
|
167
|
+
from nbxtensor.ops.stack_op import stack_copy_kernel
|
|
168
|
+
from nbxtensor.ops.repeat_op import repeat_1d_kernel
|
|
169
|
+
from nbxtensor.ops.upsample_nearest3d import upsample_nearest3d_kernel
|
|
170
|
+
from nbxtensor.ops.weight_norm import weight_norm_kernel_first, weight_norm_kernel_last
|
|
171
|
+
from nbxtensor.ops.repeat_interleave import repeat_interleave_tensor_kernel
|
|
172
|
+
from nbxtensor.ops.elementwise_launch import ew_meta as _ew_meta, ew_grid as _ew_grid
|
|
173
|
+
from nbxtensor.ops import tiling_sizes as _ts
|
|
174
|
+
import math
|
|
175
|
+
from nbxtensor.ops import elementwise_wrappers as _ew
|
|
176
|
+
from nbxtensor.ops import wrappers as _core
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _clamp_reduce_tile(bm, bn):
|
|
180
|
+
"""(block_m, block_n) clamped so a 2-D reduce tile fits the backend's cap.
|
|
181
|
+
|
|
182
|
+
A 2-D axis reduce stages BLOCK_M*BLOCK_N one element per thread; above the
|
|
183
|
+
cap (Metal 1024, cuda/hip far higher, so inert there) the lowering refuses
|
|
184
|
+
-- l2_norm on swin2SR at 8192, weight_norm on Kokoro at 16384. Shrinking
|
|
185
|
+
BLOCK_N adds loop iterations and changes no result; BLOCK_M is kept because
|
|
186
|
+
a caller may use it for its grid. THE clamp, one place: std/var/norm and
|
|
187
|
+
weight_norm all call it, a twin copy being a fix that lands in only one.
|
|
188
|
+
"""
|
|
189
|
+
cap = _reduce_tile_max()
|
|
190
|
+
if bm * bn > cap:
|
|
191
|
+
bn = max(1, cap // bm)
|
|
192
|
+
return bm, bn
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# The argmax row tile: a power-of-two cap on the vocabulary row a single
|
|
196
|
+
# program scans, and the warp count that scans it. 4096 with Triton's default
|
|
197
|
+
# 4 warps is what every architecture used before this became readable.
|
|
198
|
+
_ARGMAX_TILE = (4096, 4)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# The argmin-over-a-dim tile. Its kernel takes BLOCK_M rows and a BLOCK_N
|
|
202
|
+
# column cap; the adopted 4 x 4096 with 4 warps.
|
|
203
|
+
_ARGMIN_TILE = (4, 4096, 4)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _argmin_tile() -> tuple:
|
|
207
|
+
"""`(BLOCK_M, BLOCK_N cap, num_warps)` from `block_sizes.argmin`.
|
|
208
|
+
|
|
209
|
+
Companion to `_argmax_tile`; argmin's kernel carries a row block as well
|
|
210
|
+
as a column cap, so it has its own entry rather than sharing one.
|
|
211
|
+
"""
|
|
212
|
+
bm, bn, warps = _ARGMIN_TILE
|
|
213
|
+
try:
|
|
214
|
+
from nbxtensor.ops._configs import active_vendor_profile
|
|
215
|
+
cfg = (active_vendor_profile().get("block_sizes", {}) or {}).get("argmin")
|
|
216
|
+
if isinstance(cfg, dict):
|
|
217
|
+
bm = int(cfg.get("block_m") or bm)
|
|
218
|
+
bn = int(cfg.get("tile_n") or bn)
|
|
219
|
+
warps = int(cfg.get("num_warps") or warps)
|
|
220
|
+
except Exception:
|
|
221
|
+
pass
|
|
222
|
+
return bm, bn, warps
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _argmax_tile() -> tuple:
|
|
226
|
+
"""`(TILE_N cap, num_warps)` for the row-wise argmax, from
|
|
227
|
+
`block_sizes.argmax` in config/vendors/<vendor>/<arch>.yml.
|
|
228
|
+
|
|
229
|
+
argmax is a MULTI-VALUE reduce — it carries a value and its index — and a
|
|
230
|
+
backend may need the whole tile to fit its threadgroup to aggregate the
|
|
231
|
+
pair. That is a property of the hardware and its compiler, so it is
|
|
232
|
+
written where such properties are written. Absent key / no profile -> the
|
|
233
|
+
values every architecture used before, so nothing measured moves.
|
|
234
|
+
"""
|
|
235
|
+
cap, warps = _ARGMAX_TILE
|
|
236
|
+
try:
|
|
237
|
+
from nbxtensor.ops._configs import active_vendor_profile
|
|
238
|
+
cfg = (active_vendor_profile().get("block_sizes", {}) or {}).get("argmax")
|
|
239
|
+
if isinstance(cfg, dict):
|
|
240
|
+
cap = int(cfg.get("tile_n") or cap)
|
|
241
|
+
warps = int(cfg.get("num_warps") or warps)
|
|
242
|
+
except Exception:
|
|
243
|
+
pass
|
|
244
|
+
return cap, warps
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# ===========================================================================
|
|
248
|
+
# REDUCTION WRAPPERS
|
|
249
|
+
# ===========================================================================
|
|
250
|
+
|
|
251
|
+
def _reduce_over_dims(single_fn, x, dims, keepdim, **kw):
|
|
252
|
+
"""Reduce ``x`` over MULTIPLE dims via one single-dim reduction.
|
|
253
|
+
|
|
254
|
+
The per-reduction wrappers below each handle a single ``dim`` (or a 1-elem
|
|
255
|
+
list) by movedim+flatten to 2D; a list of dims used to collapse to its
|
|
256
|
+
first element (``dim = dim[0]``), silently reducing only one axis. This
|
|
257
|
+
helper makes the multi-dim case correct: permute the reduced dims to the
|
|
258
|
+
end, flatten them into ONE axis, reduce that axis with ``single_fn`` (the
|
|
259
|
+
same wrapper, called with an int dim). Correct for separable reductions
|
|
260
|
+
(sum/mean/amax) AND non-separable ones (std/var — the correction divides
|
|
261
|
+
by the TOTAL reduced count, which the single flattened axis preserves).
|
|
262
|
+
R33-pure: permute/contiguous/reshape + the wrapper's own kernel.
|
|
263
|
+
"""
|
|
264
|
+
nd = x.ndim
|
|
265
|
+
dims = sorted(int(d) % nd for d in dims)
|
|
266
|
+
kept = [d for d in range(nd) if d not in dims]
|
|
267
|
+
red = 1
|
|
268
|
+
for d in dims:
|
|
269
|
+
red *= x.shape[d]
|
|
270
|
+
xp = x.permute(*(kept + dims)).contiguous()
|
|
271
|
+
flat_shape = [x.shape[d] for d in kept] + [red]
|
|
272
|
+
xf = xp.reshape(*flat_shape) # [...kept..., prod(reduced)]
|
|
273
|
+
out = single_fn(xf, dim=len(kept), keepdim=False, **kw)
|
|
274
|
+
if keepdim:
|
|
275
|
+
full = list(x.shape)
|
|
276
|
+
for d in dims:
|
|
277
|
+
full[d] = 1
|
|
278
|
+
out = out.reshape(*full) # kept dims keep original order
|
|
279
|
+
return out
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def mean_wrapper(x, dim=None, keepdim=False, dtype=None) :
|
|
283
|
+
"""Mean reduction. Reduces over one dim, a 1-elem list, or (via
|
|
284
|
+
_reduce_over_dims) an arbitrary list of dims. `dtype`: aten::mean's keyword, the input cast to it first."""
|
|
285
|
+
dtype = _core._reduction_dtype("mean", dtype)
|
|
286
|
+
if dtype is not None and x._dtype != dtype:
|
|
287
|
+
x = x.to(dtype)
|
|
288
|
+
if isinstance(dim, (list, tuple)) and len(dim) > 1:
|
|
289
|
+
return _reduce_over_dims(mean_wrapper, x, dim, keepdim)
|
|
290
|
+
if dim is None:
|
|
291
|
+
# Full reduction — flatten and reduce
|
|
292
|
+
x_flat = x.contiguous().view(-1)
|
|
293
|
+
batch_dim = 1
|
|
294
|
+
feat_dim = x_flat.numel()
|
|
295
|
+
x_2d = x_flat.unsqueeze(0)
|
|
296
|
+
else:
|
|
297
|
+
if isinstance(dim, (list, tuple)):
|
|
298
|
+
dim = dim[0]
|
|
299
|
+
dim = dim % x.ndim
|
|
300
|
+
feat_dim = x.shape[dim]
|
|
301
|
+
batch_dim = x.numel() // feat_dim
|
|
302
|
+
x_perm = x.movedim(dim, -1).contiguous()
|
|
303
|
+
x_2d = x_perm.reshape(batch_dim, feat_dim)
|
|
304
|
+
|
|
305
|
+
output = NBXTensor.empty(batch_dim, dtype=NBXDtype.float32, device=x.device)
|
|
306
|
+
# rows per program, the feature tile and the warps: the certified configuration of this key (chantier 1), the
|
|
307
|
+
# key the derived census forms (`launch_keys.row_reduce_launches`)
|
|
308
|
+
grid = lambda META: (triton.cdiv(batch_dim, META['BLOCK_SIZE_BATCH']),)
|
|
309
|
+
set_device(x_2d)
|
|
310
|
+
mean_forward_kernel[grid](
|
|
311
|
+
x_2d, output,
|
|
312
|
+
batch_dim, feat_dim, _lk.bucket_of("M", batch_dim), _lk.softmax_feat_bucket(feat_dim),
|
|
313
|
+
x_2d.stride(0), x_2d.stride(1),
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
if dim is None:
|
|
317
|
+
return output.squeeze(0).to(x.dtype)
|
|
318
|
+
|
|
319
|
+
shape = list(x.shape)
|
|
320
|
+
if keepdim:
|
|
321
|
+
shape[dim] = 1
|
|
322
|
+
else:
|
|
323
|
+
shape.pop(dim)
|
|
324
|
+
return output.to(x.dtype).view(shape)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def sum_wrapper(x, dim=None, keepdim=False, dtype=None) :
|
|
328
|
+
"""Sum reduction.
|
|
329
|
+
|
|
330
|
+
Output dtype follows PyTorch ``torch.sum`` promotion: floating inputs keep
|
|
331
|
+
their dtype; bool/integer inputs promote to int64. Casting the (fp32-
|
|
332
|
+
accumulated) result back to a narrow input dtype silently overflows — e.g.
|
|
333
|
+
summing a bool mask of 354 True elements and casting to uint8 wraps to
|
|
334
|
+
354 % 256 = 98 (the chatterbox s3gen mel-length mask bug). Accumulation
|
|
335
|
+
stays fp32 either way (exact for counts well under the 2^24 mantissa).
|
|
336
|
+
|
|
337
|
+
A multi-dim reduction (``dim`` a list with >1 entry, e.g. the Wan RoPE
|
|
338
|
+
grid-size sum over [0,1,2,4]) is reduced atomically via _reduce_over_dims;
|
|
339
|
+
a single dim / 1-elem list keeps the fast path below unchanged.
|
|
340
|
+
"""
|
|
341
|
+
dtype = _core._reduction_dtype("sum", dtype)
|
|
342
|
+
if dtype is not None and x._dtype != dtype:
|
|
343
|
+
x = x.to(dtype)
|
|
344
|
+
if isinstance(dim, (list, tuple)) and len(dim) > 1:
|
|
345
|
+
return _reduce_over_dims(sum_wrapper, x, dim, keepdim)
|
|
346
|
+
# Complex sum = (sum real, sum imag), summed over the same dim. The flat
|
|
347
|
+
# kernel would reduce the interleaved re/im storage on the wrong stride.
|
|
348
|
+
# Route via the real view: the appended [.,2] axis is NOT reduced (dim is
|
|
349
|
+
# resolved on the complex rank), so re/im are summed independently.
|
|
350
|
+
if isinstance(x, NBXTensor) and x.is_complex():
|
|
351
|
+
d = (dim[0] if isinstance(dim, (list, tuple)) else dim)
|
|
352
|
+
d = d % x.ndim
|
|
353
|
+
outr = sum_wrapper(x.view_as_real(), d, keepdim)
|
|
354
|
+
return outr.view_as_complex()
|
|
355
|
+
# x.dtype is a triton dtype handle (not NBXDtype) — gate on the tensor's
|
|
356
|
+
# own is_floating_point() rather than dtype membership.
|
|
357
|
+
out_dtype = x.dtype if x.is_floating_point() else NBXDtype.int64
|
|
358
|
+
|
|
359
|
+
if dim is None:
|
|
360
|
+
x_flat = x.contiguous().view(-1)
|
|
361
|
+
batch_dim = 1
|
|
362
|
+
feat_dim = x_flat.numel()
|
|
363
|
+
x_2d = x_flat.unsqueeze(0)
|
|
364
|
+
else:
|
|
365
|
+
if isinstance(dim, (list, tuple)):
|
|
366
|
+
dim = dim[0]
|
|
367
|
+
dim = dim % x.ndim
|
|
368
|
+
feat_dim = x.shape[dim]
|
|
369
|
+
batch_dim = x.numel() // feat_dim
|
|
370
|
+
x_perm = x.movedim(dim, -1).contiguous()
|
|
371
|
+
x_2d = x_perm.reshape(batch_dim, feat_dim)
|
|
372
|
+
|
|
373
|
+
output = NBXTensor.empty(batch_dim, dtype=NBXDtype.float32, device=x.device)
|
|
374
|
+
# rows per program, the feature tile and the warps: the certified configuration of this key (chantier 1), the
|
|
375
|
+
# key the derived census forms (`launch_keys.row_reduce_launches`)
|
|
376
|
+
grid = lambda META: (triton.cdiv(batch_dim, META['BLOCK_SIZE_BATCH']),)
|
|
377
|
+
set_device(x_2d)
|
|
378
|
+
sum_forward_kernel[grid](
|
|
379
|
+
x_2d, output,
|
|
380
|
+
batch_dim, feat_dim, _lk.bucket_of("M", batch_dim), _lk.softmax_feat_bucket(feat_dim),
|
|
381
|
+
x_2d.stride(0), x_2d.stride(1),
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
if dim is None:
|
|
385
|
+
return output.squeeze(0).to(out_dtype)
|
|
386
|
+
|
|
387
|
+
shape = list(x.shape)
|
|
388
|
+
if keepdim:
|
|
389
|
+
shape[dim] = 1
|
|
390
|
+
else:
|
|
391
|
+
shape.pop(dim)
|
|
392
|
+
return output.to(out_dtype).view(shape)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def amax_wrapper(x, dim=None, keepdim=False) :
|
|
396
|
+
"""Max reduction (one dim, a 1-elem list, or an arbitrary list of dims)."""
|
|
397
|
+
if isinstance(dim, (list, tuple)) and len(dim) > 1:
|
|
398
|
+
return _reduce_over_dims(amax_wrapper, x, dim, keepdim)
|
|
399
|
+
if dim is None:
|
|
400
|
+
x_flat = x.contiguous().view(-1)
|
|
401
|
+
batch_dim = 1
|
|
402
|
+
feat_dim = x_flat.numel()
|
|
403
|
+
x_2d = x_flat.unsqueeze(0)
|
|
404
|
+
else:
|
|
405
|
+
if isinstance(dim, (list, tuple)):
|
|
406
|
+
dim = dim[0]
|
|
407
|
+
dim = dim % x.ndim
|
|
408
|
+
feat_dim = x.shape[dim]
|
|
409
|
+
batch_dim = x.numel() // feat_dim
|
|
410
|
+
x_perm = x.movedim(dim, -1).contiguous()
|
|
411
|
+
x_2d = x_perm.reshape(batch_dim, feat_dim)
|
|
412
|
+
|
|
413
|
+
output = NBXTensor.empty(batch_dim, dtype=x.dtype, device=x.device)
|
|
414
|
+
# rows per program, the feature tile and the warps: the certified configuration of this key (chantier 1), the
|
|
415
|
+
# key the derived census forms (`launch_keys.row_reduce_launches`)
|
|
416
|
+
grid = lambda META: (triton.cdiv(batch_dim, META['BLOCK_SIZE_BATCH']),)
|
|
417
|
+
set_device(x_2d)
|
|
418
|
+
amax_forward_kernel[grid](
|
|
419
|
+
x_2d, output,
|
|
420
|
+
batch_dim, feat_dim, _lk.bucket_of("M", batch_dim), _lk.softmax_feat_bucket(feat_dim),
|
|
421
|
+
x_2d.stride(0), x_2d.stride(1),
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
if dim is None:
|
|
425
|
+
return output.squeeze(0)
|
|
426
|
+
|
|
427
|
+
shape = list(x.shape)
|
|
428
|
+
if keepdim:
|
|
429
|
+
shape[dim] = 1
|
|
430
|
+
else:
|
|
431
|
+
shape.pop(dim)
|
|
432
|
+
return output.view(shape)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def argmax_wrapper(x, dim=None, keepdim=False) :
|
|
436
|
+
"""Argmax reduction. Wrapper from FlagGems."""
|
|
437
|
+
import math
|
|
438
|
+
if dim is None:
|
|
439
|
+
M = x.numel()
|
|
440
|
+
block_size = triton.next_power_of_2(math.ceil(math.sqrt(M)))
|
|
441
|
+
mid_size = triton.cdiv(M, block_size)
|
|
442
|
+
block_mid = triton.next_power_of_2(mid_size)
|
|
443
|
+
|
|
444
|
+
mid_value = NBXTensor.empty((mid_size,), dtype=x.dtype, device=x.device)
|
|
445
|
+
mid_index = NBXTensor.empty((mid_size,), dtype=NBXDtype.int64, device=x.device)
|
|
446
|
+
out = NBXTensor.empty([], dtype=NBXDtype.int64, device=x.device)
|
|
447
|
+
|
|
448
|
+
set_device(x.contiguous())
|
|
449
|
+
argmax_kernel_1[(mid_size, 1, 1)](x.contiguous(), mid_value, mid_index, M, block_size)
|
|
450
|
+
set_device(mid_value)
|
|
451
|
+
argmax_kernel_2[(1, 1, 1)](mid_value, mid_index, out, mid_size, block_mid)
|
|
452
|
+
return out
|
|
453
|
+
else:
|
|
454
|
+
dim = dim % x.ndim
|
|
455
|
+
N = x.shape[dim]
|
|
456
|
+
M = x.numel() // N
|
|
457
|
+
x = x.contiguous()
|
|
458
|
+
shape_list = list(x.shape)
|
|
459
|
+
shape_list[dim] = 1
|
|
460
|
+
out_index = NBXTensor.empty(shape_list, dtype=NBXDtype.int64, device=x.device)
|
|
461
|
+
if not keepdim:
|
|
462
|
+
out_index = out_index.squeeze(dim)
|
|
463
|
+
|
|
464
|
+
cap, warps = _argmax_tile()
|
|
465
|
+
TILE_N = min(triton.next_power_of_2(N), cap)
|
|
466
|
+
grid = (M, 1, 1)
|
|
467
|
+
set_device(x)
|
|
468
|
+
argmax_kernel_inner[grid](x, out_index, M, N, TILE_N=TILE_N,
|
|
469
|
+
ONE_TILE_PER_CTA=(TILE_N >= N),
|
|
470
|
+
num_warps=warps)
|
|
471
|
+
return out_index
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def argmin_wrapper(x, dim=None, keepdim=False) :
|
|
475
|
+
"""Argmin reduction. Wrapper from FlagGems (adapted from argmax)."""
|
|
476
|
+
import math
|
|
477
|
+
if dim is None:
|
|
478
|
+
M = x.numel()
|
|
479
|
+
block_size = triton.next_power_of_2(math.ceil(math.sqrt(M)))
|
|
480
|
+
mid_size = triton.cdiv(M, block_size)
|
|
481
|
+
block_mid = triton.next_power_of_2(mid_size)
|
|
482
|
+
|
|
483
|
+
mid_value = NBXTensor.empty((mid_size,), dtype=x.dtype, device=x.device)
|
|
484
|
+
mid_index = NBXTensor.empty((mid_size,), dtype=NBXDtype.int64, device=x.device)
|
|
485
|
+
out = NBXTensor.empty([], dtype=NBXDtype.int64, device=x.device)
|
|
486
|
+
|
|
487
|
+
set_device(x.contiguous())
|
|
488
|
+
argmin_kernel_1[(mid_size, 1, 1)](x.contiguous(), mid_value, mid_index, M, block_size)
|
|
489
|
+
set_device(mid_value)
|
|
490
|
+
argmin_kernel_2[(1, 1, 1)](mid_value, mid_index, out, mid_size, block_mid)
|
|
491
|
+
return out
|
|
492
|
+
else:
|
|
493
|
+
dim = dim % x.ndim
|
|
494
|
+
N = x.shape[dim]
|
|
495
|
+
M = x.numel() // N
|
|
496
|
+
x = x.contiguous()
|
|
497
|
+
shape = x.shape
|
|
498
|
+
N = shape[dim]
|
|
499
|
+
M = 1
|
|
500
|
+
for i in range(dim):
|
|
501
|
+
M *= shape[i]
|
|
502
|
+
K = x.numel() // M // N
|
|
503
|
+
|
|
504
|
+
shape_list = list(shape)
|
|
505
|
+
shape_list[dim] = 1
|
|
506
|
+
out_index = NBXTensor.empty(shape_list, dtype=NBXDtype.int64, device=x.device)
|
|
507
|
+
if not keepdim:
|
|
508
|
+
out_index = out_index.squeeze(dim)
|
|
509
|
+
|
|
510
|
+
_amin_bm, _amin_cap, _amin_warps = _argmin_tile()
|
|
511
|
+
BLOCK_N = min(_amin_cap, triton.next_power_of_2(N))
|
|
512
|
+
BLOCK_M = _amin_bm
|
|
513
|
+
grid = (triton.cdiv(M, BLOCK_M), K)
|
|
514
|
+
set_device(x)
|
|
515
|
+
argmin_kernel[grid](x, out_index, M, N, K, BLOCK_M, BLOCK_N,
|
|
516
|
+
num_warps=_amin_warps)
|
|
517
|
+
return out_index
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
# ===========================================================================
|
|
521
|
+
# CUMSUM WRAPPER — Extracted from FlagGems (1D scan-then-fan)
|
|
522
|
+
# ===========================================================================
|
|
523
|
+
|
|
524
|
+
def cumsum_wrapper(x, dim: int = 0, dtype=None) :
|
|
525
|
+
"""Cumulative sum along dimension. Wrapper from FlagGems.
|
|
526
|
+
|
|
527
|
+
`dtype` mirrors aten::cumsum's dtype kwarg (vendor cu_seqlens passes
|
|
528
|
+
int32): per ATen semantics the INPUT is cast to `dtype` BEFORE
|
|
529
|
+
accumulation. Accepted as string or NBXDtype; unknown strings raise
|
|
530
|
+
(ZERO FALLBACK)."""
|
|
531
|
+
_out_dtype = dtype
|
|
532
|
+
if isinstance(_out_dtype, str):
|
|
533
|
+
_name = _out_dtype.replace("torch.", "")
|
|
534
|
+
_out_dtype = getattr(NBXDtype, _name, None)
|
|
535
|
+
if _out_dtype is None:
|
|
536
|
+
raise RuntimeError(
|
|
537
|
+
f"ZERO FALLBACK: cumsum dtype '{dtype}' is not a known "
|
|
538
|
+
f"NBXDtype.")
|
|
539
|
+
if _out_dtype is not None and x.dtype != _out_dtype:
|
|
540
|
+
x = x.to(_out_dtype)
|
|
541
|
+
dim = dim % x.ndim
|
|
542
|
+
|
|
543
|
+
# Reshape to [batch, scan_dim] where scan_dim is the cumsum axis
|
|
544
|
+
scan_size = x.shape[dim]
|
|
545
|
+
batch_size = x.numel() // scan_size
|
|
546
|
+
|
|
547
|
+
# Move cumsum dim to last, flatten batch dims
|
|
548
|
+
x_perm = x.movedim(dim, -1).contiguous()
|
|
549
|
+
x_2d = x_perm.reshape(batch_size, scan_size)
|
|
550
|
+
|
|
551
|
+
BLOCK_SIZE = min(triton.next_power_of_2(scan_size), 4096)
|
|
552
|
+
|
|
553
|
+
# Process each row independently
|
|
554
|
+
output_2d = NBXTensor.empty_like(x_2d)
|
|
555
|
+
for row in range(batch_size):
|
|
556
|
+
row_in = x_2d[row]
|
|
557
|
+
row_out = output_2d[row]
|
|
558
|
+
part_num = triton.cdiv(scan_size, BLOCK_SIZE)
|
|
559
|
+
partial_sum = NBXTensor.empty(part_num, dtype=NBXDtype.float32, device=x.device)
|
|
560
|
+
|
|
561
|
+
set_device(row_in)
|
|
562
|
+
scan_part_sum_kernel[(part_num,)](
|
|
563
|
+
row_in, row_out, partial_sum, scan_size, part_num, BLOCK_SIZE=BLOCK_SIZE)
|
|
564
|
+
|
|
565
|
+
if part_num > 1:
|
|
566
|
+
for i in range(1, part_num):
|
|
567
|
+
partial_sum[i] += partial_sum[i - 1]
|
|
568
|
+
set_device(row_out)
|
|
569
|
+
add_base_sum_kernel[(part_num,)](
|
|
570
|
+
row_out, partial_sum, scan_size, part_num, BLOCK_SIZE=BLOCK_SIZE)
|
|
571
|
+
|
|
572
|
+
result = output_2d.view_as(x_perm).movedim(-1, dim)
|
|
573
|
+
if _out_dtype is not None and result.dtype != _out_dtype:
|
|
574
|
+
result = result.to(_out_dtype)
|
|
575
|
+
return result
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
# ---------------------------------------------------------------------------
|
|
579
|
+
# All / Any (boolean reductions)
|
|
580
|
+
# ---------------------------------------------------------------------------
|
|
581
|
+
|
|
582
|
+
def all_wrapper(x, dim=None, keepdim=False) :
|
|
583
|
+
"""Test if all elements are non-zero. Two-pass global reduction."""
|
|
584
|
+
import math
|
|
585
|
+
x = x.contiguous()
|
|
586
|
+
if dim is None:
|
|
587
|
+
M = x.numel()
|
|
588
|
+
BLOCK_SIZE = triton.next_power_of_2(math.ceil(math.sqrt(M)))
|
|
589
|
+
mid_size = triton.cdiv(M, BLOCK_SIZE)
|
|
590
|
+
BLOCK_MID = triton.next_power_of_2(mid_size)
|
|
591
|
+
mid = NBXTensor.empty(mid_size, dtype=NBXDtype.bool_, device=x.device)
|
|
592
|
+
out = NBXTensor.empty([], dtype=NBXDtype.bool_, device=x.device)
|
|
593
|
+
set_device(x)
|
|
594
|
+
all_kernel_mid[(mid_size,)](x, mid, M, mid_size, BLOCK_SIZE=BLOCK_SIZE)
|
|
595
|
+
set_device(mid)
|
|
596
|
+
all_kernel_result[(1,)](mid, out, mid_size, BLOCK_MID=BLOCK_MID)
|
|
597
|
+
return out
|
|
598
|
+
else:
|
|
599
|
+
dim = dim % x.ndim
|
|
600
|
+
shape = list(x.shape)
|
|
601
|
+
N = shape[dim]
|
|
602
|
+
M = x.numel() // N
|
|
603
|
+
x_perm = x.movedim(dim, -1).contiguous().reshape(M, N)
|
|
604
|
+
out = NBXTensor.empty(M, dtype=NBXDtype.bool_, device=x.device)
|
|
605
|
+
BLOCK_N = min(4096, triton.next_power_of_2(N))
|
|
606
|
+
_red_bm, _red_bn, _red_warps = _ew._reduction_2d_tile()
|
|
607
|
+
grid = (triton.cdiv(M, _red_bm),)
|
|
608
|
+
set_device(x_perm)
|
|
609
|
+
all_kernel_dim[grid](x_perm, out, M, N, BLOCK_M=_red_bm, BLOCK_N=BLOCK_N,
|
|
610
|
+
num_warps=_red_warps)
|
|
611
|
+
shape[dim] = 1
|
|
612
|
+
result = out.view(shape)
|
|
613
|
+
if not keepdim:
|
|
614
|
+
result = result.squeeze(dim)
|
|
615
|
+
return result
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def any_wrapper(x, dim=None, keepdim=False) :
|
|
619
|
+
"""Test if any element is non-zero. Two-pass global reduction."""
|
|
620
|
+
import math
|
|
621
|
+
x = x.contiguous()
|
|
622
|
+
if dim is None:
|
|
623
|
+
M = x.numel()
|
|
624
|
+
BLOCK_SIZE = triton.next_power_of_2(math.ceil(math.sqrt(M)))
|
|
625
|
+
mid_size = triton.cdiv(M, BLOCK_SIZE)
|
|
626
|
+
BLOCK_MID = triton.next_power_of_2(mid_size)
|
|
627
|
+
mid = NBXTensor.empty(mid_size, dtype=NBXDtype.bool_, device=x.device)
|
|
628
|
+
out = NBXTensor.empty([], dtype=NBXDtype.bool_, device=x.device)
|
|
629
|
+
set_device(x)
|
|
630
|
+
any_kernel_mid[(mid_size,)](x, mid, M, mid_size, BLOCK_SIZE=BLOCK_SIZE)
|
|
631
|
+
set_device(mid)
|
|
632
|
+
any_kernel_result[(1,)](mid, out, mid_size, BLOCK_MID=BLOCK_MID)
|
|
633
|
+
return out
|
|
634
|
+
else:
|
|
635
|
+
dim = dim % x.ndim
|
|
636
|
+
shape = list(x.shape)
|
|
637
|
+
N = shape[dim]
|
|
638
|
+
M = x.numel() // N
|
|
639
|
+
x_perm = x.movedim(dim, -1).contiguous().reshape(M, N)
|
|
640
|
+
out = NBXTensor.empty(M, dtype=NBXDtype.bool_, device=x.device)
|
|
641
|
+
BLOCK_N = min(4096, triton.next_power_of_2(N))
|
|
642
|
+
_red_bm, _red_bn, _red_warps = _ew._reduction_2d_tile()
|
|
643
|
+
grid = (triton.cdiv(M, _red_bm),)
|
|
644
|
+
set_device(x_perm)
|
|
645
|
+
any_kernel_dim[grid](x_perm, out, M, N, BLOCK_M=_red_bm, BLOCK_N=BLOCK_N,
|
|
646
|
+
num_warps=_red_warps)
|
|
647
|
+
shape[dim] = 1
|
|
648
|
+
result = out.view(shape)
|
|
649
|
+
if not keepdim:
|
|
650
|
+
result = result.squeeze(dim)
|
|
651
|
+
return result
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
# ---------------------------------------------------------------------------
|
|
655
|
+
# Prod (product reduction)
|
|
656
|
+
# ---------------------------------------------------------------------------
|
|
657
|
+
|
|
658
|
+
def prod_wrapper(x, dim=None, keepdim=False) :
|
|
659
|
+
"""Product reduction. Two-pass global or dim-specific."""
|
|
660
|
+
import math
|
|
661
|
+
x = x.contiguous()
|
|
662
|
+
if dim is None:
|
|
663
|
+
M = x.numel()
|
|
664
|
+
BLOCK_SIZE = triton.next_power_of_2(math.ceil(math.sqrt(M)))
|
|
665
|
+
mid_size = triton.cdiv(M, BLOCK_SIZE)
|
|
666
|
+
BLOCK_MID = triton.next_power_of_2(mid_size)
|
|
667
|
+
mid = NBXTensor.empty(mid_size, dtype=x.dtype, device=x.device)
|
|
668
|
+
out = NBXTensor.empty([], dtype=x.dtype, device=x.device)
|
|
669
|
+
set_device(x.view(-1))
|
|
670
|
+
prod_kernel_mid[(mid_size,)](x.view(-1), mid, M, BLOCK_SIZE=BLOCK_SIZE)
|
|
671
|
+
set_device(mid)
|
|
672
|
+
prod_kernel_result[(1,)](mid, out, mid_size, BLOCK_MID=BLOCK_MID)
|
|
673
|
+
return out
|
|
674
|
+
else:
|
|
675
|
+
dim = dim % x.ndim
|
|
676
|
+
shape = list(x.shape)
|
|
677
|
+
N = shape[dim]
|
|
678
|
+
M = x.numel() // N
|
|
679
|
+
x_perm = x.movedim(dim, -1).contiguous().reshape(M, N)
|
|
680
|
+
out = NBXTensor.empty(M, dtype=x.dtype, device=x.device)
|
|
681
|
+
_red_bm, _red_bn, _red_warps = _ew._reduction_2d_tile()
|
|
682
|
+
grid = (triton.cdiv(M, _red_bm),)
|
|
683
|
+
set_device(x_perm)
|
|
684
|
+
prod_kernel[grid](x_perm, out, M, N,
|
|
685
|
+
BLOCK_M=_red_bm, BLOCK_N=_red_bn,
|
|
686
|
+
num_warps=_red_warps)
|
|
687
|
+
shape[dim] = 1
|
|
688
|
+
result = out.view(shape)
|
|
689
|
+
if not keepdim:
|
|
690
|
+
result = result.squeeze(dim)
|
|
691
|
+
return result
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
# ---------------------------------------------------------------------------
|
|
695
|
+
# Std / Var
|
|
696
|
+
# ---------------------------------------------------------------------------
|
|
697
|
+
|
|
698
|
+
def std_wrapper(x, dim=None, correction=1, keepdim=False) :
|
|
699
|
+
"""Standard deviation. Global (map-reduce), single-dim, or multi-dim (the
|
|
700
|
+
reduced dims are flattened to one axis so the correction divides by the
|
|
701
|
+
total reduced count — matching torch.std over a list of dims)."""
|
|
702
|
+
import math
|
|
703
|
+
x = x.contiguous()
|
|
704
|
+
if isinstance(dim, (list, tuple)) and len(dim) > 1:
|
|
705
|
+
return _reduce_over_dims(std_wrapper, x, dim, keepdim, correction=correction)
|
|
706
|
+
if dim is None:
|
|
707
|
+
N = x.numel()
|
|
708
|
+
BLOCK_N = min(triton.next_power_of_2(math.ceil(math.sqrt(N))), 4096)
|
|
709
|
+
num_blocks = triton.cdiv(N, BLOCK_N)
|
|
710
|
+
tmp_sum = NBXTensor.empty(num_blocks, dtype=NBXDtype.float32, device=x.device)
|
|
711
|
+
tmp_sum_sq = NBXTensor.empty(num_blocks, dtype=NBXDtype.float32, device=x.device)
|
|
712
|
+
out = NBXTensor.empty([], dtype=NBXDtype.float32, device=x.device)
|
|
713
|
+
set_device(x.view(-1))
|
|
714
|
+
std_map_kernel[(num_blocks,)](x.view(-1), tmp_sum, tmp_sum_sq, N, BLOCK_N=BLOCK_N)
|
|
715
|
+
BLOCK_SIZE = triton.next_power_of_2(num_blocks)
|
|
716
|
+
set_device(tmp_sum)
|
|
717
|
+
std_reduce_kernel[(1,)](
|
|
718
|
+
tmp_sum, tmp_sum_sq, out, N, float(correction), num_blocks,
|
|
719
|
+
BLOCK_SIZE=BLOCK_SIZE)
|
|
720
|
+
return out.to(x.dtype)
|
|
721
|
+
else:
|
|
722
|
+
if isinstance(dim, (list, tuple)):
|
|
723
|
+
dim = dim[0]
|
|
724
|
+
dim = dim % x.ndim
|
|
725
|
+
N = x.shape[dim]
|
|
726
|
+
M = x.numel() // N
|
|
727
|
+
x_perm = x.movedim(dim, -1).contiguous()
|
|
728
|
+
x_2d = x_perm.reshape(M, N)
|
|
729
|
+
out_flat = NBXTensor.empty(M, dtype=NBXDtype.float32, device=x.device)
|
|
730
|
+
grid, _bm, _bn = _ew._reduction_tile(M)
|
|
731
|
+
set_device(x_2d)
|
|
732
|
+
std_dim_kernel[grid](
|
|
733
|
+
x_2d, out_flat,
|
|
734
|
+
x_2d.stride(0), x_2d.stride(1),
|
|
735
|
+
M, N, float(correction),
|
|
736
|
+
BLOCK_M=_bm, BLOCK_N=_bn,
|
|
737
|
+
num_warps=4,
|
|
738
|
+
)
|
|
739
|
+
shape = list(x.shape)
|
|
740
|
+
if keepdim:
|
|
741
|
+
shape[dim] = 1
|
|
742
|
+
else:
|
|
743
|
+
shape.pop(dim)
|
|
744
|
+
return out_flat.to(x.dtype).view(shape)
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
def var_wrapper(x, dim=None, correction=1, keepdim=False) :
|
|
748
|
+
"""Variance. Global (Welford), single-dim, or multi-dim (reduced dims
|
|
749
|
+
flattened to one axis → correction over the total reduced count)."""
|
|
750
|
+
import math
|
|
751
|
+
x = x.contiguous()
|
|
752
|
+
if isinstance(dim, (list, tuple)) and len(dim) > 1:
|
|
753
|
+
return _reduce_over_dims(var_wrapper, x, dim, keepdim, correction=correction)
|
|
754
|
+
if dim is None:
|
|
755
|
+
N = x.numel()
|
|
756
|
+
BLOCK_N = min(triton.next_power_of_2(math.ceil(math.sqrt(N))), 4096)
|
|
757
|
+
num_blocks = triton.cdiv(N, BLOCK_N)
|
|
758
|
+
acc = NBXTensor.empty(num_blocks, dtype=NBXDtype.float32, device=x.device)
|
|
759
|
+
average = NBXTensor.empty(num_blocks, dtype=NBXDtype.float32, device=x.device)
|
|
760
|
+
count = NBXTensor.empty(num_blocks, dtype=NBXDtype.float32, device=x.device)
|
|
761
|
+
out = NBXTensor.empty([], dtype=NBXDtype.float32, device=x.device)
|
|
762
|
+
set_device(x.view(-1))
|
|
763
|
+
var_kernel_1[(num_blocks,)](x.view(-1), acc, average, count, N, BLOCK_N=BLOCK_N)
|
|
764
|
+
BLOCK_NUM = triton.next_power_of_2(num_blocks)
|
|
765
|
+
set_device(acc)
|
|
766
|
+
var_kernel_2[(1,)](
|
|
767
|
+
acc, average, count, out, N, float(correction), num_blocks,
|
|
768
|
+
BLOCK_N=BLOCK_NUM)
|
|
769
|
+
return out.to(x.dtype)
|
|
770
|
+
else:
|
|
771
|
+
if isinstance(dim, (list, tuple)):
|
|
772
|
+
dim = dim[0]
|
|
773
|
+
dim = dim % x.ndim
|
|
774
|
+
N = x.shape[dim]
|
|
775
|
+
M = x.numel() // N
|
|
776
|
+
x_perm = x.movedim(dim, -1).contiguous()
|
|
777
|
+
x_2d = x_perm.reshape(M, N)
|
|
778
|
+
out_flat = NBXTensor.empty(M, dtype=NBXDtype.float32, device=x.device)
|
|
779
|
+
grid, _bm, _bn = _ew._reduction_tile(M)
|
|
780
|
+
set_device(x_2d)
|
|
781
|
+
var_welford_kernel[grid](x_2d, out_flat, M, N, float(correction),
|
|
782
|
+
BLOCK_M=_bm, BLOCK_N=_bn,
|
|
783
|
+
num_warps=4)
|
|
784
|
+
shape = list(x.shape)
|
|
785
|
+
if keepdim:
|
|
786
|
+
shape[dim] = 1
|
|
787
|
+
else:
|
|
788
|
+
shape.pop(dim)
|
|
789
|
+
return out_flat.to(x.dtype).view(shape)
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def scatter_reduce_wrapper(input, dim: int, index,
|
|
793
|
+
src, reduce: str,
|
|
794
|
+
include_self: bool = True) :
|
|
795
|
+
"""scatter_reduce: accumulate src into input along dim using reduce mode.
|
|
796
|
+
Supported modes: sum, amax, amin. All use Triton atomic ops."""
|
|
797
|
+
input = input.contiguous()
|
|
798
|
+
src = src.contiguous()
|
|
799
|
+
index = index.contiguous()
|
|
800
|
+
dim = dim % input.ndim
|
|
801
|
+
|
|
802
|
+
if include_self:
|
|
803
|
+
out = input.clone()
|
|
804
|
+
else:
|
|
805
|
+
if reduce == "sum" or reduce == "add":
|
|
806
|
+
out = NBXTensor.zeros_like(input)
|
|
807
|
+
elif reduce == "amax":
|
|
808
|
+
out = NBXTensor.empty_like(input, float('-inf'))
|
|
809
|
+
elif reduce == "amin":
|
|
810
|
+
out = NBXTensor.empty_like(input, float('inf'))
|
|
811
|
+
else:
|
|
812
|
+
out = input.clone()
|
|
813
|
+
|
|
814
|
+
N = index.numel()
|
|
815
|
+
if N == 0:
|
|
816
|
+
return out
|
|
817
|
+
|
|
818
|
+
outer_size = 1
|
|
819
|
+
for i in range(dim):
|
|
820
|
+
outer_size *= index.shape[i]
|
|
821
|
+
inner_size = 1
|
|
822
|
+
for i in range(dim + 1, index.ndim):
|
|
823
|
+
inner_size *= index.shape[i]
|
|
824
|
+
dim_size = index.shape[dim]
|
|
825
|
+
|
|
826
|
+
stride_args = (
|
|
827
|
+
src, index, out, N,
|
|
828
|
+
out.stride(dim),
|
|
829
|
+
src.stride(0) if dim > 0 else 0, src.stride(dim), src.stride(-1) if dim < src.ndim - 1 else 0,
|
|
830
|
+
index.stride(0) if dim > 0 else 0, index.stride(dim), index.stride(-1) if dim < index.ndim - 1 else 0,
|
|
831
|
+
out.stride(0) if dim > 0 else 0, out.stride(-1) if dim < out.ndim - 1 else 0,
|
|
832
|
+
outer_size, dim_size, inner_size,
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
set_device(out)
|
|
836
|
+
if reduce == "sum" or reduce == "add":
|
|
837
|
+
scatter_add_kernel[_ew._1d_grid(N)](*stride_args, **_ew_meta(N))
|
|
838
|
+
elif reduce == "amax":
|
|
839
|
+
scatter_reduce_amax_kernel[_ew._1d_grid(N)](*stride_args, **_ew_meta(N))
|
|
840
|
+
elif reduce == "amin":
|
|
841
|
+
scatter_reduce_amin_kernel[_ew._1d_grid(N)](*stride_args, **_ew_meta(N))
|
|
842
|
+
else:
|
|
843
|
+
raise RuntimeError(f"[--triton] scatter_reduce mode '{reduce}' not implemented")
|
|
844
|
+
|
|
845
|
+
return out
|