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,121 @@
|
|
|
1
|
+
"""Index select — pure @triton.jit kernel.
|
|
2
|
+
|
|
3
|
+
Extracted from FlagGems (FlagOpen/FlagGems) index_select.py.
|
|
4
|
+
2D grid: rows x index blocks, with bounds checking.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import triton
|
|
8
|
+
import triton.language as tl
|
|
9
|
+
|
|
10
|
+
#: The contract this kernel enforces. Triton forbids reading a module global
|
|
11
|
+
#: from inside a @jit body, so the kernel repeats the literal; the permanent
|
|
12
|
+
#: test pins the two equal so they cannot drift.
|
|
13
|
+
INDEX_SELECT_OOB = "index_select: index out of range"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@triton.jit(debug=True)
|
|
17
|
+
def index_select_kernel(
|
|
18
|
+
inp, out, M, N, index, index_len, fault_ptr,
|
|
19
|
+
FAULT_CODE: tl.constexpr,
|
|
20
|
+
BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr,
|
|
21
|
+
):
|
|
22
|
+
"""`debug=True` keeps the `tl.device_assert` below in the compiled
|
|
23
|
+
kernel regardless of TRITON_DEBUG: an out-of-range index TRAPS (the
|
|
24
|
+
next device sync raises) exactly where torch's index_select raises.
|
|
25
|
+
The FlagGems port skipped the store instead, leaving the output
|
|
26
|
+
element as whatever the allocation held — silent, and invisible to
|
|
27
|
+
a byte gate whose two sides share the defect
|
|
28
|
+
(D-GATHER-SCATTER-OOB-SILENT, promoted to correctness 2026-09-02).
|
|
29
|
+
|
|
30
|
+
That assert is honoured on CUDA and ROCm and NOT on Metal, which
|
|
31
|
+
computes its predicate and discards it (measured 2026-09-10). This
|
|
32
|
+
kernel never went out of bounds there — its load and its store are
|
|
33
|
+
both masked by `index_valid_mask` — so what survived was exactly the
|
|
34
|
+
FlagGems silence it was written to end: the output element stayed
|
|
35
|
+
whatever the pool held. `FAULT_CODE` closes it. A non-zero code
|
|
36
|
+
makes the kernel report through the fault word, which
|
|
37
|
+
`check_device_faults` raises on at the next host observation; the
|
|
38
|
+
wrapper passes 0 where the assert is honoured, and then not one
|
|
39
|
+
instruction of it is emitted."""
|
|
40
|
+
pid_x = tl.program_id(axis=0).to(tl.int64)
|
|
41
|
+
pid_y = tl.program_id(axis=1).to(tl.int64)
|
|
42
|
+
rows_offsets = pid_x * BLOCK_M + tl.arange(0, BLOCK_M)[:, None]
|
|
43
|
+
rows_mask = rows_offsets < M
|
|
44
|
+
cols_offsets = pid_y * BLOCK_N + tl.arange(0, BLOCK_N)
|
|
45
|
+
|
|
46
|
+
out_mask = rows_mask & (cols_offsets[None, :] < index_len)
|
|
47
|
+
|
|
48
|
+
indices = tl.load(index + cols_offsets, mask=(cols_offsets < index_len), other=0)
|
|
49
|
+
# torch semantics: a NEGATIVE index counts from the end (index + N).
|
|
50
|
+
# The FlagGems port treated it as invalid and SKIPPED the store, leaving
|
|
51
|
+
# the output element as whatever the allocation held — zeros on a fresh
|
|
52
|
+
# cudaMalloc, stale data under the allocator pool (HAT's
|
|
53
|
+
# relative_position_index_OCA carries negative entries; pool gate
|
|
54
|
+
# 2026-09-02: the two HAT upscaler PNGs differed pool on vs off).
|
|
55
|
+
indices = tl.where(indices < 0, indices + N, indices)
|
|
56
|
+
valid_lower_bound = indices >= 0
|
|
57
|
+
valid_upper_bound = indices < N
|
|
58
|
+
index_valid_mask = valid_lower_bound & valid_upper_bound
|
|
59
|
+
# Masked lanes loaded `other=0` and are in range by construction.
|
|
60
|
+
tl.device_assert(index_valid_mask, "index_select: index out of range")
|
|
61
|
+
if FAULT_CODE != 0:
|
|
62
|
+
# Lanes past `index_len` loaded `other=0` and are in range by
|
|
63
|
+
# construction; they must not report. Reduce to one scalar so the
|
|
64
|
+
# store below is a single conditional word, not a vector.
|
|
65
|
+
live = cols_offsets < index_len
|
|
66
|
+
if tl.max(tl.where(live & (index_valid_mask == 0), 1, 0)) != 0:
|
|
67
|
+
tl.store(fault_ptr, FAULT_CODE)
|
|
68
|
+
|
|
69
|
+
inp_off = rows_offsets * N + indices[None, :]
|
|
70
|
+
out_off = rows_offsets * index_len + cols_offsets[None, :]
|
|
71
|
+
|
|
72
|
+
final_mask = out_mask & index_valid_mask[None, :]
|
|
73
|
+
selected = tl.load(inp + inp_off, mask=final_mask, other=0.0)
|
|
74
|
+
tl.store(out + out_off, selected, mask=final_mask)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@triton.jit(debug=True)
|
|
78
|
+
def index_select_mid_kernel(
|
|
79
|
+
inp, out, outer, N, inner, index, index_len, fault_ptr,
|
|
80
|
+
FAULT_CODE: tl.constexpr,
|
|
81
|
+
BLOCK: tl.constexpr,
|
|
82
|
+
):
|
|
83
|
+
"""Gather along a MIDDLE axis of a contiguous input read as (outer, N, inner): the output
|
|
84
|
+
(outer, index_len, inner) is written in its final layout, so the wrapper needs neither the
|
|
85
|
+
movedim copy before the gather nor the permute copy after it (the copy lever, 2026-09-07:
|
|
86
|
+
88 strided copies a decode token on TinyLlama for 44 gathers). Same values as the
|
|
87
|
+
last-axis kernel — a gather moves bytes, it computes nothing. The same out-of-range trap.
|
|
88
|
+
|
|
89
|
+
That trap needs BOTH channels, and this kernel arrived carrying only one.
|
|
90
|
+
`tl.device_assert` is honoured on CUDA and ROCm and elided on Metal, which
|
|
91
|
+
computes its predicate and discards it — so on Apple this path gathered an
|
|
92
|
+
out-of-range index in silence while its own docstring promised a trap. It
|
|
93
|
+
was not caught by the merge (no conflict: the two works touched different
|
|
94
|
+
lines) and not by a count (164 against 150 reads like noise). The failure
|
|
95
|
+
register named it: `test_out_of_range_index_is_refused_by_name[index_select]`
|
|
96
|
+
appeared in the NEW column the first time this path was exercised.
|
|
97
|
+
|
|
98
|
+
A guard written in good faith that does not cover the path added beside it
|
|
99
|
+
is the same class as a guard that never fires."""
|
|
100
|
+
pid = tl.program_id(axis=0).to(tl.int64)
|
|
101
|
+
e = pid.to(tl.int64) * BLOCK + tl.arange(0, BLOCK) # 64-bit from the program id (register 58)
|
|
102
|
+
total = outer * index_len * inner
|
|
103
|
+
mask = e < total
|
|
104
|
+
per_outer = index_len * inner
|
|
105
|
+
o = e // per_outer
|
|
106
|
+
rem = e - o * per_outer
|
|
107
|
+
i = rem // inner
|
|
108
|
+
r = rem - i * inner
|
|
109
|
+
idx = tl.load(index + i, mask=mask, other=0)
|
|
110
|
+
idx = tl.where(idx < 0, idx + N, idx)
|
|
111
|
+
valid = (idx >= 0) & (idx < N)
|
|
112
|
+
tl.device_assert(valid | (~mask), "index_select: index out of range")
|
|
113
|
+
if FAULT_CODE != 0:
|
|
114
|
+
# Lanes past `total` loaded `other=0` and are in range by construction;
|
|
115
|
+
# they must not report. Reduced to one scalar so the store is a single
|
|
116
|
+
# conditional word rather than a vector.
|
|
117
|
+
if tl.max(tl.where(mask & (valid == 0), 1, 0)) != 0:
|
|
118
|
+
tl.store(fault_ptr, FAULT_CODE)
|
|
119
|
+
src = o * (N * inner) + idx * inner + r
|
|
120
|
+
v = tl.load(inp + src, mask=mask & valid, other=0.0)
|
|
121
|
+
tl.store(out + e, v, mask=mask & valid)
|