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/div.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Division — pure @triton.jit kernel."""
|
|
2
|
+
|
|
3
|
+
import triton
|
|
4
|
+
import triton.language as tl
|
|
5
|
+
|
|
6
|
+
@triton.jit
|
|
7
|
+
def div_forward_kernel(
|
|
8
|
+
x_ptr, y_ptr, output_ptr,
|
|
9
|
+
n_elements,
|
|
10
|
+
BLOCK_SIZE: tl.constexpr,
|
|
11
|
+
):
|
|
12
|
+
"""out = x / y (tensor / tensor)"""
|
|
13
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
14
|
+
offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
|
|
15
|
+
mask = offset < n_elements
|
|
16
|
+
|
|
17
|
+
x = tl.load(x_ptr + offset, mask=mask)
|
|
18
|
+
y = tl.load(y_ptr + offset, mask=mask)
|
|
19
|
+
tl.store(output_ptr + offset, x / y, mask=mask)
|
|
20
|
+
|
|
21
|
+
@triton.jit
|
|
22
|
+
def div_scalar_kernel(
|
|
23
|
+
x_ptr, output_ptr,
|
|
24
|
+
n_elements,
|
|
25
|
+
scalar,
|
|
26
|
+
BLOCK_SIZE: tl.constexpr,
|
|
27
|
+
):
|
|
28
|
+
"""out = x / scalar"""
|
|
29
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
30
|
+
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)
|
|
31
|
+
mask = offset < n_elements
|
|
32
|
+
|
|
33
|
+
x = tl.load(x_ptr + offset, mask=mask)
|
|
34
|
+
tl.store(output_ptr + offset, x / scalar, mask=mask)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@triton.jit
|
|
38
|
+
def div_scalar_dev_kernel(
|
|
39
|
+
x_ptr, s_ptr, output_ptr,
|
|
40
|
+
n_elements,
|
|
41
|
+
BLOCK_SIZE: tl.constexpr,
|
|
42
|
+
):
|
|
43
|
+
"""out = x / s where s is a 0-d DEVICE tensor. Bit-exact mirror
|
|
44
|
+
of div_scalar_kernel (host float(s) -> f32 arg == load -> f64 ->
|
|
45
|
+
f32). Device-scalar increment 2026-08-15."""
|
|
46
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
47
|
+
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)
|
|
48
|
+
mask = offset < n_elements
|
|
49
|
+
s = tl.load(s_ptr).to(tl.float64).to(tl.float32)
|
|
50
|
+
x = tl.load(x_ptr + offset, mask=mask)
|
|
51
|
+
tl.store(output_ptr + offset, x / s, mask=mask)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@triton.jit
|
|
55
|
+
def int_div_kernel(
|
|
56
|
+
x_ptr, y_ptr, output_ptr,
|
|
57
|
+
n_elements,
|
|
58
|
+
FLOOR: tl.constexpr,
|
|
59
|
+
BLOCK_SIZE: tl.constexpr,
|
|
60
|
+
):
|
|
61
|
+
"""out = x // y on integers, computed in the integers: truncated toward zero (C), or toward
|
|
62
|
+
-inf when FLOOR (ATen's floor_divide). Exact at every magnitude of the dtype, where a float
|
|
63
|
+
round-trip is not: Metal's float32 divide is not correctly rounded (-3403868 / 13 gave
|
|
64
|
+
-261836.02, floor -261837; 4435 of 10000 quotients differ from IEEE, 2026-10-08)."""
|
|
65
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
66
|
+
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)
|
|
67
|
+
mask = offset < n_elements
|
|
68
|
+
|
|
69
|
+
x = tl.load(x_ptr + offset, mask=mask, other=0)
|
|
70
|
+
y = tl.load(y_ptr + offset, mask=mask, other=1)
|
|
71
|
+
q = x // y
|
|
72
|
+
if FLOOR:
|
|
73
|
+
r = x - q * y
|
|
74
|
+
q = q - ((r != 0) & ((r < 0) != (y < 0))).to(q.dtype)
|
|
75
|
+
tl.store(output_ptr + offset, q, mask=mask)
|
nbxtensor/ops/dot_op.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Dot product — pure @triton.jit kernels.
|
|
2
|
+
|
|
3
|
+
Ported from FlagGems dot (Apache-2.0 license).
|
|
4
|
+
Two-phase reduction for large N: partial sums then final reduce.
|
|
5
|
+
Single-phase for small N.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import triton
|
|
9
|
+
import triton.language as tl
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@triton.jit
|
|
13
|
+
def dot_kernel_small(
|
|
14
|
+
x_ptr, y_ptr, out_ptr,
|
|
15
|
+
N,
|
|
16
|
+
BLOCK_SIZE: tl.constexpr,
|
|
17
|
+
):
|
|
18
|
+
"""Single-block dot product for small vectors (N < 4096).
|
|
19
|
+
|
|
20
|
+
Accumulates in fp32 for numerical stability.
|
|
21
|
+
"""
|
|
22
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
23
|
+
block_start = pid * BLOCK_SIZE
|
|
24
|
+
offsets = block_start + tl.arange(0, BLOCK_SIZE)
|
|
25
|
+
mask = offsets < N
|
|
26
|
+
|
|
27
|
+
x = tl.load(x_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
28
|
+
y = tl.load(y_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
29
|
+
|
|
30
|
+
result = tl.sum(x * y)
|
|
31
|
+
tl.store(out_ptr, result)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@triton.jit
|
|
35
|
+
def dot_kernel_partial(
|
|
36
|
+
x_ptr, y_ptr, mid_ptr,
|
|
37
|
+
N,
|
|
38
|
+
BLOCK_SIZE: tl.constexpr,
|
|
39
|
+
):
|
|
40
|
+
"""Phase 1: compute partial dot products per block.
|
|
41
|
+
|
|
42
|
+
Each block computes sum(x[block] * y[block]) and stores to mid_ptr[pid].
|
|
43
|
+
"""
|
|
44
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
45
|
+
block_start = pid * BLOCK_SIZE
|
|
46
|
+
offsets = block_start + tl.arange(0, BLOCK_SIZE)
|
|
47
|
+
mask = offsets < N
|
|
48
|
+
|
|
49
|
+
x = tl.load(x_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
50
|
+
y = tl.load(y_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
51
|
+
|
|
52
|
+
partial_sum = tl.sum(x * y)
|
|
53
|
+
tl.store(mid_ptr + pid, partial_sum)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@triton.jit
|
|
57
|
+
def dot_kernel_reduce(
|
|
58
|
+
mid_ptr, out_ptr,
|
|
59
|
+
M,
|
|
60
|
+
BLOCK_MID: tl.constexpr,
|
|
61
|
+
):
|
|
62
|
+
"""Phase 2: reduce partial sums into final scalar result."""
|
|
63
|
+
offsets = tl.arange(0, BLOCK_MID)
|
|
64
|
+
mask = offsets < M
|
|
65
|
+
mid_val = tl.load(mid_ptr + offsets, mask=mask, other=0.0)
|
|
66
|
+
result = tl.sum(mid_val)
|
|
67
|
+
tl.store(out_ptr, result)
|
nbxtensor/ops/dropout.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Dropout — pure @triton.jit kernel.
|
|
2
|
+
|
|
3
|
+
At inference time (train=False), dropout is identity (passthrough).
|
|
4
|
+
This kernel implements the identity passthrough for inference mode.
|
|
5
|
+
Training dropout with Philox RNG would be a separate kernel.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import triton
|
|
9
|
+
import triton.language as tl
|
|
10
|
+
|
|
11
|
+
@triton.jit
|
|
12
|
+
def dropout_inference_kernel(
|
|
13
|
+
x_ptr, output_ptr,
|
|
14
|
+
n_elements,
|
|
15
|
+
BLOCK_SIZE: tl.constexpr,
|
|
16
|
+
):
|
|
17
|
+
"""Dropout at inference = identity copy."""
|
|
18
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
19
|
+
offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE) # 64-bit from the program id: the product itself wraps past 2^31 elements (register 58)
|
|
20
|
+
mask = offset < n_elements
|
|
21
|
+
|
|
22
|
+
x = tl.load(x_ptr + offset, mask=mask)
|
|
23
|
+
tl.store(output_ptr + offset, x, mask=mask)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""GPU dtype conversion kernels — bf16↔fp16 via bit manipulation.
|
|
2
|
+
|
|
3
|
+
Eliminates CPU-side numpy conversion during weight loading.
|
|
4
|
+
Raw bf16 bytes are H2D copied as uint16, then converted on GPU.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import triton
|
|
8
|
+
import triton.language as tl
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@triton.jit
|
|
12
|
+
def bf16_to_fp16_kernel(
|
|
13
|
+
src_ptr, # uint16 (bf16 raw bits) on GPU
|
|
14
|
+
dst_ptr, # fp16 output on GPU
|
|
15
|
+
N, # total number of elements
|
|
16
|
+
BLOCK: tl.constexpr,
|
|
17
|
+
):
|
|
18
|
+
"""Convert bf16 → fp16 on GPU via fp32 intermediate.
|
|
19
|
+
|
|
20
|
+
bf16 bits: [sign(1)][exp(8)][mantissa(7)]
|
|
21
|
+
fp32 bits: [sign(1)][exp(8)][mantissa(23)] ← bf16 << 16
|
|
22
|
+
fp16 bits: [sign(1)][exp(5)][mantissa(10)] ← GPU truncates fp32→fp16
|
|
23
|
+
|
|
24
|
+
The GPU handles fp32→fp16 truncation natively (with rounding).
|
|
25
|
+
"""
|
|
26
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
27
|
+
offs = pid.to(tl.int64) * BLOCK + tl.arange(0, BLOCK) # 64-bit from the program id (register 58)
|
|
28
|
+
mask = offs < N
|
|
29
|
+
|
|
30
|
+
# Load bf16 raw bits (stored as int16, same 2-byte layout)
|
|
31
|
+
raw_i16 = tl.load(src_ptr + offs, mask=mask, other=0)
|
|
32
|
+
# Mask to 16 bits to prevent sign extension when widening to uint32
|
|
33
|
+
raw = (raw_i16.to(tl.int32) & 0xFFFF).to(tl.uint32)
|
|
34
|
+
|
|
35
|
+
# bf16 → fp32: shift left 16 bits, bitcast to float32
|
|
36
|
+
fp32_bits = raw << 16
|
|
37
|
+
fp32_vals = fp32_bits.to(tl.float32, bitcast=True)
|
|
38
|
+
|
|
39
|
+
# fp32 → fp16: GPU truncates natively
|
|
40
|
+
fp16_vals = fp32_vals.to(tl.float16)
|
|
41
|
+
|
|
42
|
+
tl.store(dst_ptr + offs, fp16_vals, mask=mask)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""The launch configuration of every element-wise kernel, certified (chantier 1).
|
|
2
|
+
|
|
3
|
+
An element-wise kernel reads and writes each element once: its time is the memory's, and the program's tile and warps
|
|
4
|
+
move it. Measured on V100 (2026-10-23, `campaigns/2026_10_12_mq25_gate/stable/c1rest/ew_bench.json`: add, mul, exp,
|
|
5
|
+
silu, gelu, erf, pow and a copy, fp32 and fp16, 4 096 to 16 777 216 elements, 15 tiles x warps): at 16 M elements the
|
|
6
|
+
best of the 15 is within 0.3 % (max 1.4 %) for every operation of the configuration that is best for the copy; below
|
|
7
|
+
65 536 elements the launch itself dominates. The OPERATION does not move the optimum — the element count does, by
|
|
8
|
+
class. So the element-wise kernels share ONE key: the class of the launch's element count (`autotune.buckets.elements`,
|
|
9
|
+
the profile's ladder, else its `default`), certified on the copy below, and every element-wise launch reads its tile
|
|
10
|
+
and warps through `ew_meta` — one memoized resolution per class and process, through the autotuner's own door
|
|
11
|
+
(`ops/_configs.nbx_autotune`: the census record, the certified directory, the refusal of a confirmation run).
|
|
12
|
+
|
|
13
|
+
The copy is in fp32 (the widest element a launch of this class commonly moves); a tile changes no bit of any
|
|
14
|
+
element-wise result — each element is computed alone — so its oracle is identity.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import triton
|
|
18
|
+
import triton.language as tl
|
|
19
|
+
|
|
20
|
+
from nbxtensor.ops._configs import nbx_autotune
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _ew_configs():
|
|
24
|
+
"""Tile x warps; the configuration every element-wise launch ran before certification (1 024 x 4) is among them."""
|
|
25
|
+
return [triton.Config({'BLOCK_SIZE': block}, num_warps=warps)
|
|
26
|
+
for block in (256, 512, 1024, 2048, 4096) for warps in (2, 4, 8)]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@nbx_autotune(configs=_ew_configs(), key=['N_BUCKET'], cache_results=True)
|
|
30
|
+
@triton.jit
|
|
31
|
+
def ew_launch_kernel(x_ptr, y_ptr, n_elements, N_BUCKET, BLOCK_SIZE: tl.constexpr):
|
|
32
|
+
"""y = x over n_elements: the element-wise class's representative."""
|
|
33
|
+
pid = tl.program_id(0).to(tl.int64)
|
|
34
|
+
offset = pid.to(tl.int64) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
|
|
35
|
+
mask = offset < n_elements
|
|
36
|
+
tl.store(y_ptr + offset, tl.load(x_ptr + offset, mask=mask), mask=mask)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
_MEMO = {} # {the element count's class: {'BLOCK_SIZE': ..., 'num_warps': ...}} — one resolution per process
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def ew_bucket(n_elements: int) -> int:
|
|
43
|
+
"""The class of an element-wise launch of `n_elements` (`autotune.buckets.elements`, else the profile's
|
|
44
|
+
`default`): the key `launch_keys.elementwise_launches` forms for the census."""
|
|
45
|
+
from nbxtensor.ops.autotune_bucket import bucket_of
|
|
46
|
+
return bucket_of("elements", max(1, int(n_elements)))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def ew_meta(n_elements: int) -> dict:
|
|
50
|
+
"""The tile and warps of an element-wise launch of `n_elements`: its class's certified configuration (a
|
|
51
|
+
confirmation run refuses a class the directory lacks, by name; another run sweeps it once), read once per class
|
|
52
|
+
and process. The resolution launches the copy above at the class's floor — the fewest elements that form it, so
|
|
53
|
+
never more than the launch that asks — on a scratch buffer of the current device, through the autotuner's door."""
|
|
54
|
+
nb = ew_bucket(n_elements)
|
|
55
|
+
hit = _MEMO.get(nb)
|
|
56
|
+
if hit is not None:
|
|
57
|
+
return hit
|
|
58
|
+
from nbxtensor.ops.autotune_bucket import class_floor
|
|
59
|
+
from nbxtensor.tensor import NBXTensor
|
|
60
|
+
from nbxtensor.dtype.nbx_dtype import NBXDtype
|
|
61
|
+
from nbxtensor.ops.launch_observer import launch_observer
|
|
62
|
+
_census = launch_observer() # the application's launch observer (dry run), if any
|
|
63
|
+
from nbxtensor.ops.autotune_cache import key_of
|
|
64
|
+
rep = class_floor("elements", nb)
|
|
65
|
+
buf = NBXTensor.empty((rep,), dtype=NBXDtype.float32, device='cuda')
|
|
66
|
+
args = (buf, buf, rep, nb)
|
|
67
|
+
ew_launch_kernel[lambda META: (triton.cdiv(rep, META['BLOCK_SIZE']),)](*args)
|
|
68
|
+
cfg = ew_launch_kernel.cache.get(key_of(ew_launch_kernel, args, {}))
|
|
69
|
+
if cfg is None:
|
|
70
|
+
if _census.active(): # a census shadow launches nothing: no configuration exists, none is needed
|
|
71
|
+
first = ew_launch_kernel.configs[0]
|
|
72
|
+
return {'BLOCK_SIZE': first.kwargs['BLOCK_SIZE'], 'num_warps': first.num_warps}
|
|
73
|
+
raise RuntimeError(f"element-wise class {nb}: the copy's autotuner ran and holds no configuration for it")
|
|
74
|
+
hit = {'BLOCK_SIZE': int(cfg.kwargs['BLOCK_SIZE']), 'num_warps': int(cfg.num_warps)}
|
|
75
|
+
_MEMO[nb] = hit
|
|
76
|
+
return hit
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def ew_grid(n_elements: int, meta: dict) -> tuple:
|
|
80
|
+
"""The 1-D grid of an element-wise launch at its configuration."""
|
|
81
|
+
return (triton.cdiv(int(n_elements), meta['BLOCK_SIZE']),)
|