teeny_triton/triton/mod.rs
1/*
2 * Copyright (c) 2026 Teenygrad.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use core::ops::{Add, Div, Mul, Neg, Sub};
18pub use core::ops::{BitAnd, BitOr};
19
20use self::types::{self as ty};
21
22/// LLVM-backend-facing DSL types (the compiled counterpart of this module's `Tensor`/`Pointer`).
23pub mod llvm;
24/// Dtype/numeric-kind trait hierarchy (`Dtype`, `Num`, `Int`, `Float`) used to bound the `Triton`
25/// trait's generic methods.
26pub mod types;
27
28pub use types::*;
29
30/*------------------------------ Parameter Enums ------------------------------*/
31
32/// A grid/program-ID axis.
33#[repr(i32)]
34pub enum Axis {
35 /// The first (fastest-varying) grid axis.
36 X = 0,
37 /// The second grid axis.
38 Y = 1,
39 /// The third grid axis.
40 Z = 2,
41}
42
43/// Padding value applied to out-of-bounds lanes when using `boundary_check` in `load`.
44pub enum PaddingOption {
45 /// Pad with zero.
46 Zero,
47 /// Pad with NaN.
48 Nan,
49}
50
51/// L1/L2 cache behaviour for load and store instructions.
52pub enum CacheModifier {
53 /// Cache at all levels (L1 + L2).
54 Ca,
55 /// Cache at global level only (L2, bypass L1).
56 Cg,
57 /// Volatile — don't cache, always fetch from memory.
58 Cv,
59 /// Write-back at all coherent levels.
60 Wb,
61 /// Streaming — likely accessed once.
62 Cs,
63}
64
65/// Cache eviction priority hint for load and store instructions.
66pub enum EvictionPolicy {
67 /// Evict this data first (low reuse expected).
68 EvictFirst,
69 /// Evict this data last (high reuse expected).
70 EvictLast,
71 /// No eviction priority hint.
72 NoEvict,
73}
74
75/// Tensor-core precision mode for `dot` on `f32 × f32` inputs.
76pub enum InputPrecision {
77 /// TF32 precision (default on devices with Tensor Cores).
78 TF32,
79 /// Emulate higher precision using three TF32 dot products.
80 TF32x3,
81 /// Full IEEE-754 precision.
82 IEEE,
83}
84
85/// Rounding mode used when down-casting floating-point types in `cast`.
86pub enum FpDowncastRounding {
87 /// Round to nearest, ties to even.
88 Rtne,
89 /// Round towards zero (truncate).
90 Rtz,
91}
92
93/// Input format for scaled dot-product (`dot_scaled`).
94pub enum DotFormat {
95 /// 8-bit float, 4 exponent + 3 mantissa bits.
96 E4M3,
97 /// 8-bit float, 5 exponent + 2 mantissa bits.
98 E5M2,
99 /// 4-bit float (2 exponent + 1 mantissa bit), packed 2-per-byte.
100 E2M1x2,
101 /// 4-bit float (2 exponent + 1 mantissa bit), packed 4-per-byte.
102 E2M1x4,
103 /// `bfloat16`, packed 2-per-32-bits.
104 BF16x2,
105 /// Signed 8-bit integer.
106 Int8,
107 /// Unsigned 8-bit integer.
108 UInt8,
109}
110
111/// Memory ordering semantics for atomic operations.
112pub enum MemSem {
113 /// No ordering constraint beyond atomicity.
114 Relaxed,
115 /// Acquire ordering: subsequent operations can't be reordered before this one.
116 Acquire,
117 /// Release ordering: prior operations can't be reordered after this one.
118 Release,
119 /// Acquire + Release (default).
120 AcqRel,
121}
122
123/// Synchronization scope for atomic operations.
124pub enum MemScope {
125 /// Cooperative thread array (thread block).
126 Cta,
127 /// All threads on the GPU (default).
128 Gpu,
129 /// All threads in the system.
130 Sys,
131}
132
133/*------------------------------ Triton Trait ------------------------------*/
134
135/// The Triton-like kernel DSL: tensor/pointer types and the operations (creation, shape
136/// manipulation, linear algebra, memory, math, reduction, scan/sort, atomics, RNG) available
137/// inside a `#[kernel]`-annotated function. See the module docs for how this compiles.
138pub trait Triton
139where
140 Self::I32Tensor: Add<i32, Output = Self::I32Tensor>,
141 Self::I32Tensor: Sub<i32, Output = Self::I32Tensor>,
142 Self::I32Tensor: Mul<i32, Output = Self::I32Tensor>,
143 Self::I32Tensor: Div<i32, Output = Self::I32Tensor>,
144 Self::BoolTensor: BitAnd<Output = Self::BoolTensor>,
145 Self::BoolTensor: BitOr<Output = Self::BoolTensor>,
146{
147 /// A tensor of `bool`, produced by comparisons and used as a mask.
148 type BoolTensor: Copy + Clone;
149 /// A tensor of `i32`, e.g. produced by [`Triton::arange`].
150 type I32Tensor: Copy + Clone;
151 /// A tensor of dtype `D`.
152 type Tensor<D: ty::Dtype>: Copy
153 + Clone
154 + Add<Self::Tensor<D>, Output = Self::Tensor<D>>
155 + Sub<Self::Tensor<D>, Output = Self::Tensor<D>>
156 + Mul<Self::Tensor<D>, Output = Self::Tensor<D>>
157 + Div<Self::Tensor<D>, Output = Self::Tensor<D>>
158 + Neg<Output = Self::Tensor<D>>;
159 /// A device pointer to elements of dtype `D`.
160 type Pointer<D: ty::Dtype>: Copy
161 + Clone
162 + ty::Dtype
163 + Add<Self::Pointer<D>, Output = Self::Pointer<D>>;
164
165 /*------------------------------ Programming Model ------------------------------*/
166
167 /// The current program's index along `axis` within the launch grid.
168 fn program_id(axis: Axis) -> i32;
169
170 /// The total number of programs launched along `axis`.
171 fn num_programs(axis: Axis) -> i32;
172
173 /// Scalar gather: load the `f32` at `ptr + offset`, truncate to `i32`,
174 /// and return it as a plain Rust `i32` usable in scalar arithmetic
175 /// (e.g. as an addend to `arange` results via `I32Tensor + i32`).
176 ///
177 /// Used when integer indices are stored as f32 (the graph's default dtype).
178 fn load_scalar_f32_as_i32(ptr: Self::Pointer<f32>, offset: i32) -> i32;
179
180 /*------------------------------ Creation Ops ------------------------------*/
181
182 /// Create a 1-D `i32` tensor with values `[start, start+1, ..., end-1]`.
183 fn arange(start: impl Into<i32>, end: impl Into<i32>) -> Self::I32Tensor;
184
185 /// Create a 1-D `f32` tensor with values `[start as f32, start+1, ..., end-1]`.
186 ///
187 /// Equivalent to casting `arange(start, end)` to f32, but avoids the
188 /// intermediate I32Tensor copy that some backends cannot handle.
189 fn arange_f32(start: impl Into<i32>, end: impl Into<i32>) -> Self::Tensor<f32>;
190
191 /// Create a tensor of the given `shape` filled with zeros.
192 fn zeros<D: ty::Dtype>(shape: &[i32]) -> Self::Tensor<D>;
193
194 /// Create a zero-filled tensor with the same shape/dtype as `x`.
195 fn zeros_like<D: ty::Dtype>(x: Self::Tensor<D>) -> Self::Tensor<D>;
196
197 /// Create a tensor of the given `shape` filled with `value`.
198 fn full<D: ty::Dtype>(shape: &[i32], value: D) -> Self::Tensor<D>;
199
200 /// Cast a tensor to a different dtype.
201 ///
202 /// - `fp_downcast_rounding`: rounding mode when narrowing float types (default `None` = unspecified).
203 /// - `bitcast`: reinterpret bits without conversion (default `false`).
204 fn cast<Src: ty::Dtype, Dst: ty::Dtype>(
205 x: Self::Tensor<Src>,
206 fp_downcast_rounding: Option<FpDowncastRounding>,
207 bitcast: bool,
208 ) -> Self::Tensor<Dst>;
209
210 /// Concatenate two tensors.
211 ///
212 /// - `can_reorder`: allow the compiler to reorder elements (default `false`).
213 fn cat<D: ty::Dtype>(
214 a: Self::Tensor<D>,
215 b: Self::Tensor<D>,
216 can_reorder: bool,
217 ) -> Self::Tensor<D>;
218
219 /*------------------------------ Shape Manipulation Ops ------------------------------*/
220
221 /// Broadcast two tensors to a common compatible shape.
222 fn broadcast<D: ty::Dtype>(
223 a: Self::Tensor<D>,
224 b: Self::Tensor<D>,
225 ) -> (Self::Tensor<D>, Self::Tensor<D>);
226
227 /// Broadcast `x` to `shape`.
228 fn broadcast_to<D: ty::Dtype>(x: Self::Tensor<D>, shape: &[i32]) -> Self::Tensor<D>;
229
230 /// Insert a size-1 dimension at `axis`.
231 fn expand_dims<D: ty::Dtype>(x: Self::Tensor<D>, axis: i32) -> Self::Tensor<D>;
232
233 /// Permute `x`'s dimensions according to `dims`.
234 fn permute<D: ty::Dtype>(x: Self::Tensor<D>, dims: &[i32]) -> Self::Tensor<D>;
235
236 /// Reshape a tensor.
237 ///
238 /// - `can_reorder`: allow element reordering during reshape (default `false`).
239 fn reshape<D: ty::Dtype>(
240 x: Self::Tensor<D>,
241 shape: &[i32],
242 can_reorder: bool,
243 ) -> Self::Tensor<D>;
244
245 /// Permute dimensions. Alias for `permute`.
246 fn trans<D: ty::Dtype>(x: Self::Tensor<D>, dims: &[i32]) -> Self::Tensor<D>;
247
248 /// Flatten to 1-D.
249 ///
250 /// - `can_reorder`: allow element reordering (default `false`).
251 fn ravel<D: ty::Dtype>(x: Self::Tensor<D>, can_reorder: bool) -> Self::Tensor<D>;
252
253 /// View with a new shape (order not preserved).
254 fn view<D: ty::Dtype>(x: Self::Tensor<D>, shape: &[i32]) -> Self::Tensor<D>;
255
256 /// Join two tensors along a new minor dimension.
257 fn join<D: ty::Dtype>(a: Self::Tensor<D>, b: Self::Tensor<D>) -> Self::Tensor<D>;
258
259 /// Interleave two tensors along their last dimension.
260 fn interleave<D: ty::Dtype>(a: Self::Tensor<D>, b: Self::Tensor<D>) -> Self::Tensor<D>;
261
262 /// Split a tensor in two along its last dimension (which must have size 2).
263 fn split<D: ty::Dtype>(x: Self::Tensor<D>) -> (Self::Tensor<D>, Self::Tensor<D>);
264
265 /*------------------------------ Linear Algebra Ops ------------------------------*/
266
267 /// Matrix (or batched matrix) multiply.
268 ///
269 /// - `acc`: optional accumulator tensor added to the result.
270 /// - `input_precision`: Tensor Core precision for `f32 × f32` (default `None` = TF32 on capable hardware).
271 /// - `max_num_imprecise_acc`: limit on imprecise accumulations (default `None`).
272 fn dot<D: ty::Num, O: ty::Num>(
273 a: Self::Tensor<D>,
274 b: Self::Tensor<D>,
275 acc: Option<Self::Tensor<O>>,
276 input_precision: Option<InputPrecision>,
277 max_num_imprecise_acc: Option<i32>,
278 ) -> Self::Tensor<O>;
279
280 /// Scaled mixed-precision matrix multiply (FP8 / narrow formats).
281 ///
282 /// - `acc`: optional accumulator (default `None`).
283 /// - `fast_math`: allow reduced precision accumulation (default `false`).
284 fn dot_scaled<D: ty::Num, S: ty::Num, O: ty::Num>(
285 lhs: Self::Tensor<D>,
286 lhs_scale: Self::Tensor<S>,
287 lhs_format: DotFormat,
288 rhs: Self::Tensor<D>,
289 rhs_scale: Self::Tensor<S>,
290 rhs_format: DotFormat,
291 acc: Option<Self::Tensor<O>>,
292 fast_math: bool,
293 ) -> Self::Tensor<O>;
294
295 /*------------------------------ Memory / Pointer Ops ------------------------------*/
296
297 /// Create a block pointer encoding shape, strides, offsets, and tile shape.
298 fn make_block_ptr<D: ty::Dtype>(
299 base: Self::Pointer<D>,
300 shape: &[i32],
301 strides: &[i32],
302 offsets: &[i32],
303 block_shape: &[i32],
304 order: &[i32],
305 ) -> Self::Pointer<D>;
306
307 /// Advance a block pointer by the given per-dimension offsets.
308 fn advance<D: ty::Dtype>(ptr: Self::Pointer<D>, offsets: &[i32]) -> Self::Pointer<D>;
309
310 /// Create a tensor descriptor for TMA (Tensor Memory Accelerator) operations.
311 ///
312 /// - `padding_option`: out-of-bounds padding behaviour (default `PaddingOption::Zero`).
313 fn make_tensor_descriptor<D: ty::Dtype>(
314 base: Self::Pointer<D>,
315 shape: &[i32],
316 strides: &[i32],
317 block_shape: &[i32],
318 padding_option: Option<PaddingOption>,
319 ) -> Self::Pointer<D>;
320
321 /// Load a tile from memory using a tensor descriptor and per-dimension offsets.
322 fn load_tensor_descriptor<D: ty::Dtype>(
323 desc: Self::Pointer<D>,
324 offsets: &[i32],
325 ) -> Self::Tensor<D>;
326
327 /// Store a tile to memory using a tensor descriptor and per-dimension offsets.
328 fn store_tensor_descriptor<D: ty::Dtype>(
329 desc: Self::Pointer<D>,
330 offsets: &[i32],
331 value: Self::Tensor<D>,
332 );
333
334 /// Load a tensor from memory.
335 ///
336 /// - `mask`: when `Some`, lanes where mask is `false` are not loaded (default `None` = unconditional).
337 /// - `other`: fill value for masked-off lanes (default `None` = undefined).
338 /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
339 /// - `padding_option`: fill for out-of-bounds lanes in block-pointer mode (default `None`).
340 /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
341 /// - `eviction_policy`: eviction priority hint (default `None`).
342 /// - `volatile`: always fetch fresh from memory (default `false`).
343 fn load<D: ty::Dtype, const N: usize>(
344 ptr: Self::Tensor<Self::Pointer<D>>,
345 mask: Option<Self::BoolTensor>,
346 other: Option<Self::Tensor<D>>,
347 boundary_check: &[i32; N],
348 padding_option: Option<PaddingOption>,
349 cache_modifier: Option<CacheModifier>,
350 eviction_policy: Option<EvictionPolicy>,
351 volatile: bool,
352 ) -> Self::Tensor<D>;
353
354 /// Store a tensor to memory.
355 ///
356 /// - `mask`: when `Some`, lanes where mask is `false` are not stored (default `None` = unconditional).
357 /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
358 /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
359 /// - `eviction_policy`: eviction priority hint (default `None`).
360 fn store<D: ty::Dtype, const N: usize>(
361 dest: Self::Tensor<Self::Pointer<D>>,
362 src: Self::Tensor<D>,
363 mask: Option<Self::BoolTensor>,
364 boundary_check: &[i32; N],
365 cache_modifier: Option<CacheModifier>,
366 eviction_policy: Option<EvictionPolicy>,
367 );
368
369 /*------------------------------ Comparison Ops ------------------------------*/
370
371 /// Element-wise less-than between two tensors.
372 fn lt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
373 /// Element-wise less-than-or-equal between two tensors.
374 fn le<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
375 /// Element-wise greater-than between two tensors.
376 fn gt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
377 /// Element-wise greater-than-or-equal between two tensors.
378 fn ge<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
379 /// Element-wise equality between two tensors.
380 fn eq<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
381 /// Element-wise inequality between two tensors.
382 fn ne<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
383
384 /// Element-wise less-than against a scalar.
385 fn lt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
386 /// Element-wise less-than-or-equal against a scalar.
387 fn le_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
388 /// Element-wise greater-than against a scalar.
389 fn gt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
390 /// Element-wise greater-than-or-equal against a scalar.
391 fn ge_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
392 /// Element-wise equality against a scalar.
393 fn eq_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
394 /// Element-wise inequality against a scalar.
395 fn ne_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
396
397 /*------------------------------ Indexing Ops ------------------------------*/
398
399 /// Conditional element selection — corresponds to `tl.where`.
400 /// Named `where_` to avoid collision with the Rust keyword `where`.
401 fn where_<D: ty::Dtype>(
402 cond: Self::BoolTensor,
403 x: Self::Tensor<D>,
404 y: Self::Tensor<D>,
405 ) -> Self::Tensor<D>;
406
407 /// Reverse a tensor along `dim`. `None` reverses all dimensions.
408 fn flip<D: ty::Dtype>(x: Self::Tensor<D>, dim: Option<i32>) -> Self::Tensor<D>;
409
410 /// Gather elements from `src` along `axis` using `index`.
411 fn gather<D: ty::Dtype>(
412 src: Self::Tensor<D>,
413 index: Self::I32Tensor,
414 axis: i32,
415 ) -> Self::Tensor<D>;
416
417 /*------------------------------ Math Ops — Unary ------------------------------*/
418
419 /// Element-wise absolute value.
420 fn abs<D: ty::Dtype>(x: Self::Tensor<D>) -> Self::Tensor<D>;
421 /// Element-wise ceiling.
422 fn ceil<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
423 /// Element-wise floor.
424 fn floor<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
425 /// Element-wise cosine.
426 fn cos<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
427 /// Element-wise sine.
428 fn sin<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
429 /// Element-wise natural exponential (`e^x`).
430 fn exp<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
431 /// Element-wise base-2 exponential (`2^x`).
432 fn exp2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
433 /// Element-wise natural logarithm.
434 fn log<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
435 /// Element-wise base-2 logarithm.
436 fn log2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
437 /// Element-wise reciprocal square root (`1/sqrt(x)`).
438 fn rsqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
439 /// Element-wise sigmoid (`1/(1+e^-x)`).
440 fn sigmoid<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
441 /// Element-wise square root.
442 fn sqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
443 /// Element-wise square root, round-to-nearest.
444 fn sqrt_rn<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
445 /// Element-wise error function.
446 fn erf<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
447 /// Element-wise arctangent.
448 fn atan<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
449
450 /*------------------------------ Math Ops — Float (higher-level) ------------------------------*/
451
452 /// Numerically-stable softmax along `dim`. `dim = None` defaults to the last dimension.
453 ///
454 /// - `keep_dims`: retain the reduced dimension with length 1 (default `false`).
455 /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
456 fn softmax<D: ty::Float>(
457 x: Self::Tensor<D>,
458 dim: Option<i32>,
459 keep_dims: bool,
460 ieee_rounding: bool,
461 ) -> Self::Tensor<D>;
462
463 /*------------------------------ Math Ops — Binary ------------------------------*/
464
465 /// Element-wise maximum of two tensors.
466 fn maximum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
467 /// Element-wise minimum of two tensors.
468 fn minimum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
469
470 /// Element-wise clamp of `x` to `[lo, hi]`.
471 fn clamp<D: ty::Num>(
472 x: Self::Tensor<D>,
473 lo: Self::Tensor<D>,
474 hi: Self::Tensor<D>,
475 ) -> Self::Tensor<D>;
476
477 /// Element-wise fused multiply-add: `x * y + z`.
478 fn fma<D: ty::Float>(
479 x: Self::Tensor<D>,
480 y: Self::Tensor<D>,
481 z: Self::Tensor<D>,
482 ) -> Self::Tensor<D>;
483
484 /// Element-wise floating-point division.
485 ///
486 /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
487 fn fdiv<D: ty::Float>(
488 x: Self::Tensor<D>,
489 y: Self::Tensor<D>,
490 ieee_rounding: bool,
491 ) -> Self::Tensor<D>;
492
493 /// Element-wise division, round-to-nearest.
494 fn div_rn<D: ty::Float>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
495
496 /// Element-wise high 32 bits of an unsigned 32×32→64-bit multiply.
497 fn umulhi(x: Self::Tensor<u32>, y: Self::Tensor<u32>) -> Self::Tensor<u32>;
498
499 /// Ceiling integer division: `ceil(x / div)`.
500 fn cdiv(x: i32, div: i32) -> i32;
501
502 /// Swizzle 2-D indices for shared-memory bank-conflict avoidance.
503 /// Returns the remapped `(i, j)` indices.
504 fn swizzle2d(i: i32, j: i32, size_i: i32, size_j: i32, size_g: i32) -> (i32, i32);
505
506 /*------------------------------ Reduction Ops ------------------------------*/
507
508 /// Sum all elements along `axis`. `axis = None` reduces all dimensions.
509 fn sum<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
510
511 /// Maximum along `axis`. `axis = None` reduces all dimensions.
512 fn max<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
513
514 /// Maximum along `axis`, also returning the index of the maximum.
515 ///
516 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
517 fn max_with_indices<D: ty::Num>(
518 x: Self::Tensor<D>,
519 axis: i32,
520 tie_break_left: bool,
521 keep_dims: bool,
522 ) -> (Self::Tensor<D>, Self::I32Tensor);
523
524 /// Minimum along `axis`. `axis = None` reduces all dimensions.
525 fn min<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
526
527 /// Minimum along `axis`, also returning the index of the minimum.
528 ///
529 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
530 fn min_with_indices<D: ty::Num>(
531 x: Self::Tensor<D>,
532 axis: i32,
533 tie_break_left: bool,
534 keep_dims: bool,
535 ) -> (Self::Tensor<D>, Self::I32Tensor);
536
537 /// Index of the maximum along `axis`.
538 ///
539 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
540 fn argmax<D: ty::Num>(
541 x: Self::Tensor<D>,
542 axis: i32,
543 tie_break_left: bool,
544 keep_dims: bool,
545 ) -> Self::I32Tensor;
546
547 /// Index of the minimum along `axis`.
548 ///
549 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
550 fn argmin<D: ty::Num>(
551 x: Self::Tensor<D>,
552 axis: i32,
553 tie_break_left: bool,
554 keep_dims: bool,
555 ) -> Self::I32Tensor;
556
557 /// XOR-reduction along `axis`. `axis = None` reduces all dimensions.
558 fn xor_sum<D: ty::Int>(
559 x: Self::Tensor<D>,
560 axis: Option<i32>,
561 keep_dims: bool,
562 ) -> Self::Tensor<D>;
563
564 /*------------------------------ Scan / Sort Ops ------------------------------*/
565
566 /// Cumulative sum along `axis`.
567 fn cumsum<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
568
569 /// Cumulative product along `axis`.
570 fn cumprod<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
571
572 /// Sort along `dim`. `dim = None` sorts along the last dimension.
573 fn sort<D: ty::Num>(x: Self::Tensor<D>, dim: Option<i32>, descending: bool) -> Self::Tensor<D>;
574
575 /// Compute a histogram with `num_bins` bins (width 1, starting at 0).
576 ///
577 /// - `mask`: when `Some`, masked-off elements are excluded (default `None`).
578 fn histogram(
579 x: Self::I32Tensor,
580 num_bins: i32,
581 mask: Option<Self::BoolTensor>,
582 ) -> Self::I32Tensor;
583
584 /// Generic reduction along `axis` using a user-supplied combine function.
585 ///
586 /// `combine_fn` must be a statically-known function pointer (corresponds to a
587 /// `@triton.jit`-decorated helper in Python Triton).
588 fn reduce<D: ty::Dtype, O: ty::Dtype>(
589 x: Self::Tensor<D>,
590 axis: i32,
591 combine_fn: fn(Self::Tensor<O>, Self::Tensor<O>) -> Self::Tensor<O>,
592 keep_dims: bool,
593 ) -> Self::Tensor<O>;
594
595 /// Generic prefix-scan along `axis` using a user-supplied combine function.
596 ///
597 /// - `reverse`: scan in the reverse direction (default `false`).
598 fn associative_scan<D: ty::Dtype>(
599 x: Self::Tensor<D>,
600 axis: i32,
601 combine_fn: fn(Self::Tensor<D>, Self::Tensor<D>) -> Self::Tensor<D>,
602 reverse: bool,
603 ) -> Self::Tensor<D>;
604
605 /*------------------------------ Atomic Ops ------------------------------*/
606
607 /// Atomic add. Returns the previous value.
608 ///
609 /// - `mask`: when `Some`, only masked lanes perform the operation (default `None`).
610 /// - `sem`: memory ordering semantics (default `None` = AcqRel).
611 /// - `scope`: synchronization scope (default `None` = Gpu).
612 fn atomic_add<D: ty::Num>(
613 ptr: Self::Tensor<Self::Pointer<D>>,
614 val: Self::Tensor<D>,
615 mask: Option<Self::BoolTensor>,
616 sem: Option<MemSem>,
617 scope: Option<MemScope>,
618 ) -> Self::Tensor<D>;
619
620 /// Atomic bitwise AND. Returns the previous value. See [`Triton::atomic_add`] for parameters.
621 fn atomic_and<D: ty::Int>(
622 ptr: Self::Tensor<Self::Pointer<D>>,
623 val: Self::Tensor<D>,
624 mask: Option<Self::BoolTensor>,
625 sem: Option<MemSem>,
626 scope: Option<MemScope>,
627 ) -> Self::Tensor<D>;
628
629 /// Atomic bitwise OR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
630 fn atomic_or<D: ty::Int>(
631 ptr: Self::Tensor<Self::Pointer<D>>,
632 val: Self::Tensor<D>,
633 mask: Option<Self::BoolTensor>,
634 sem: Option<MemSem>,
635 scope: Option<MemScope>,
636 ) -> Self::Tensor<D>;
637
638 /// Atomic bitwise XOR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
639 fn atomic_xor<D: ty::Int>(
640 ptr: Self::Tensor<Self::Pointer<D>>,
641 val: Self::Tensor<D>,
642 mask: Option<Self::BoolTensor>,
643 sem: Option<MemSem>,
644 scope: Option<MemScope>,
645 ) -> Self::Tensor<D>;
646
647 /// Atomic maximum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
648 fn atomic_max<D: ty::Num>(
649 ptr: Self::Tensor<Self::Pointer<D>>,
650 val: Self::Tensor<D>,
651 mask: Option<Self::BoolTensor>,
652 sem: Option<MemSem>,
653 scope: Option<MemScope>,
654 ) -> Self::Tensor<D>;
655
656 /// Atomic minimum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
657 fn atomic_min<D: ty::Num>(
658 ptr: Self::Tensor<Self::Pointer<D>>,
659 val: Self::Tensor<D>,
660 mask: Option<Self::BoolTensor>,
661 sem: Option<MemSem>,
662 scope: Option<MemScope>,
663 ) -> Self::Tensor<D>;
664
665 /// Atomic exchange. Returns the previous value. See [`Triton::atomic_add`] for parameters.
666 fn atomic_xchg<D: ty::Dtype>(
667 ptr: Self::Tensor<Self::Pointer<D>>,
668 val: Self::Tensor<D>,
669 mask: Option<Self::BoolTensor>,
670 sem: Option<MemSem>,
671 scope: Option<MemScope>,
672 ) -> Self::Tensor<D>;
673
674 /// Atomic compare-and-swap. Returns the previous value.
675 fn atomic_cas<D: ty::Dtype>(
676 ptr: Self::Tensor<Self::Pointer<D>>,
677 cmp: Self::Tensor<D>,
678 val: Self::Tensor<D>,
679 sem: Option<MemSem>,
680 scope: Option<MemScope>,
681 ) -> Self::Tensor<D>;
682
683 /*------------------------------ Random Number Generation ------------------------------*/
684
685 /// Uniform random `f32` in `[0, 1)`.
686 ///
687 /// - `n_rounds`: number of Philox rounds (default `10`).
688 fn rand(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
689
690 /// Standard-normal random `f32`.
691 ///
692 /// - `n_rounds`: number of Philox rounds (default `10`).
693 fn randn(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
694
695 /// Random `i32`.
696 ///
697 /// - `n_rounds`: number of Philox rounds (default `10`).
698 fn randint(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::I32Tensor;
699
700 /// Four random `i32` streams (maximally efficient Philox entry point).
701 ///
702 /// - `n_rounds`: number of Philox rounds (default `10`).
703 fn randint4x(
704 seed: u32,
705 offsets: Self::I32Tensor,
706 n_rounds: i32,
707 ) -> (
708 Self::I32Tensor,
709 Self::I32Tensor,
710 Self::I32Tensor,
711 Self::I32Tensor,
712 );
713
714 /*------------------------------ Inline Assembly ------------------------------*/
715
716 /// Emit inline PTX/assembly applied element-wise across a tensor.
717 ///
718 /// - `asm`: the assembly template string.
719 /// - `constraints`: register constraint string.
720 /// - `is_pure`: whether the assembly has no side-effects (may be CSE'd).
721 /// - `pack`: number of elements packed into each register.
722 fn inline_asm_elementwise<D: ty::Dtype>(
723 asm: &str,
724 constraints: &str,
725 is_pure: bool,
726 pack: i32,
727 ) -> Self::Tensor<D>;
728
729 /*------------------------------ Compiler Hint Ops ------------------------------*/
730
731 /// Assert that `cond` is always true, allowing the compiler to assume so.
732 fn assume(cond: Self::BoolTensor);
733
734 /// Hint that values of `x` are always multiples of the given constants.
735 fn multiple_of<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
736
737 /// Hint that `x` has `values[i]` contiguous elements along dimension `i`.
738 fn max_contiguous<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
739
740 /// Hint that `x` has `values[i]` constant elements along dimension `i`.
741 fn max_constancy<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
742
743 /*------------------------------ Debug Ops ------------------------------*/
744
745 /// Insert a memory barrier for debugging purposes.
746 fn debug_barrier();
747
748 /// Emit a runtime assertion on the device. No-op when `cond` is `true`.
749 ///
750 /// - `msg`: message shown on assertion failure (default `""`).
751 /// - `mask`: when `Some`, only lanes where mask is `true` check the assertion.
752 fn device_assert(cond: Self::BoolTensor, msg: &str, mask: Option<Self::BoolTensor>);
753
754 /// Print a tensor value from device code for debugging.
755 ///
756 /// - `hex`: print values in hexadecimal (default `false`).
757 fn device_print<D: ty::Dtype>(prefix: &str, val: Self::Tensor<D>, hex: bool);
758
759 /// Compile-time assertion (evaluated before kernel launch).
760 fn static_assert(cond: bool, msg: &str);
761
762 /// Compile-time print (evaluated before kernel launch).
763 fn static_print(msg: &str);
764}