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`. No default — every call site must
271 /// pick one explicitly. `IEEE` matches `tt.dot`'s own default (full-precision, no tensor cores);
272 /// `TF32` routes through tensor cores at reduced mantissa precision. A silent default here is
273 /// exactly what caused kernels to unknowingly run at `IEEE` instead of the intended `TF32`.
274 /// - `max_num_imprecise_acc`: limit on imprecise accumulations (default `None`).
275 fn dot<D: ty::Num, O: ty::Num>(
276 a: Self::Tensor<D>,
277 b: Self::Tensor<D>,
278 acc: Option<Self::Tensor<O>>,
279 input_precision: InputPrecision,
280 max_num_imprecise_acc: Option<i32>,
281 ) -> Self::Tensor<O>;
282
283 /// Scaled mixed-precision matrix multiply (FP8 / narrow formats).
284 ///
285 /// - `acc`: optional accumulator (default `None`).
286 /// - `fast_math`: allow reduced precision accumulation (default `false`).
287 fn dot_scaled<D: ty::Num, S: ty::Num, O: ty::Num>(
288 lhs: Self::Tensor<D>,
289 lhs_scale: Self::Tensor<S>,
290 lhs_format: DotFormat,
291 rhs: Self::Tensor<D>,
292 rhs_scale: Self::Tensor<S>,
293 rhs_format: DotFormat,
294 acc: Option<Self::Tensor<O>>,
295 fast_math: bool,
296 ) -> Self::Tensor<O>;
297
298 /*------------------------------ Memory / Pointer Ops ------------------------------*/
299
300 /// Create a block pointer encoding shape, strides, offsets, and tile shape.
301 fn make_block_ptr<D: ty::Dtype>(
302 base: Self::Pointer<D>,
303 shape: &[i32],
304 strides: &[i32],
305 offsets: &[i32],
306 block_shape: &[i32],
307 order: &[i32],
308 ) -> Self::Pointer<D>;
309
310 /// Advance a block pointer by the given per-dimension offsets.
311 fn advance<D: ty::Dtype>(ptr: Self::Pointer<D>, offsets: &[i32]) -> Self::Pointer<D>;
312
313 /// Create a tensor descriptor for TMA (Tensor Memory Accelerator) operations.
314 ///
315 /// - `padding_option`: out-of-bounds padding behaviour (default `PaddingOption::Zero`).
316 fn make_tensor_descriptor<D: ty::Dtype>(
317 base: Self::Pointer<D>,
318 shape: &[i32],
319 strides: &[i32],
320 block_shape: &[i32],
321 padding_option: Option<PaddingOption>,
322 ) -> Self::Pointer<D>;
323
324 /// Load a tile from memory using a tensor descriptor and per-dimension offsets.
325 fn load_tensor_descriptor<D: ty::Dtype>(
326 desc: Self::Pointer<D>,
327 offsets: &[i32],
328 ) -> Self::Tensor<D>;
329
330 /// Store a tile to memory using a tensor descriptor and per-dimension offsets.
331 fn store_tensor_descriptor<D: ty::Dtype>(
332 desc: Self::Pointer<D>,
333 offsets: &[i32],
334 value: Self::Tensor<D>,
335 );
336
337 /// Load a tensor from memory.
338 ///
339 /// - `mask`: when `Some`, lanes where mask is `false` are not loaded (default `None` = unconditional).
340 /// - `other`: fill value for masked-off lanes (default `None` = undefined).
341 /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
342 /// - `padding_option`: fill for out-of-bounds lanes in block-pointer mode (default `None`).
343 /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
344 /// - `eviction_policy`: eviction priority hint (default `None`).
345 /// - `volatile`: always fetch fresh from memory (default `false`).
346 fn load<D: ty::Dtype, const N: usize>(
347 ptr: Self::Tensor<Self::Pointer<D>>,
348 mask: Option<Self::BoolTensor>,
349 other: Option<Self::Tensor<D>>,
350 boundary_check: &[i32; N],
351 padding_option: Option<PaddingOption>,
352 cache_modifier: Option<CacheModifier>,
353 eviction_policy: Option<EvictionPolicy>,
354 volatile: bool,
355 ) -> Self::Tensor<D>;
356
357 /// Store a tensor to memory.
358 ///
359 /// - `mask`: when `Some`, lanes where mask is `false` are not stored (default `None` = unconditional).
360 /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
361 /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
362 /// - `eviction_policy`: eviction priority hint (default `None`).
363 fn store<D: ty::Dtype, const N: usize>(
364 dest: Self::Tensor<Self::Pointer<D>>,
365 src: Self::Tensor<D>,
366 mask: Option<Self::BoolTensor>,
367 boundary_check: &[i32; N],
368 cache_modifier: Option<CacheModifier>,
369 eviction_policy: Option<EvictionPolicy>,
370 );
371
372 /*------------------------------ Comparison Ops ------------------------------*/
373
374 /// Element-wise less-than between two tensors.
375 fn lt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
376 /// Element-wise less-than-or-equal between two tensors.
377 fn le<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
378 /// Element-wise greater-than between two tensors.
379 fn gt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
380 /// Element-wise greater-than-or-equal between two tensors.
381 fn ge<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
382 /// Element-wise equality between two tensors.
383 fn eq<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
384 /// Element-wise inequality between two tensors.
385 fn ne<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
386
387 /// Element-wise less-than against a scalar.
388 fn lt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
389 /// Element-wise less-than-or-equal against a scalar.
390 fn le_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
391 /// Element-wise greater-than against a scalar.
392 fn gt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
393 /// Element-wise greater-than-or-equal against a scalar.
394 fn ge_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
395 /// Element-wise equality against a scalar.
396 fn eq_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
397 /// Element-wise inequality against a scalar.
398 fn ne_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
399
400 /*------------------------------ Indexing Ops ------------------------------*/
401
402 /// Conditional element selection — corresponds to `tl.where`.
403 /// Named `where_` to avoid collision with the Rust keyword `where`.
404 fn where_<D: ty::Dtype>(
405 cond: Self::BoolTensor,
406 x: Self::Tensor<D>,
407 y: Self::Tensor<D>,
408 ) -> Self::Tensor<D>;
409
410 /// Reverse a tensor along `dim`. `None` reverses all dimensions.
411 fn flip<D: ty::Dtype>(x: Self::Tensor<D>, dim: Option<i32>) -> Self::Tensor<D>;
412
413 /// Gather elements from `src` along `axis` using `index`.
414 fn gather<D: ty::Dtype>(
415 src: Self::Tensor<D>,
416 index: Self::I32Tensor,
417 axis: i32,
418 ) -> Self::Tensor<D>;
419
420 /*------------------------------ Math Ops — Unary ------------------------------*/
421
422 /// Element-wise absolute value.
423 fn abs<D: ty::Dtype>(x: Self::Tensor<D>) -> Self::Tensor<D>;
424 /// Element-wise ceiling.
425 fn ceil<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
426 /// Element-wise floor.
427 fn floor<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
428 /// Element-wise cosine.
429 fn cos<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
430 /// Element-wise sine.
431 fn sin<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
432 /// Element-wise natural exponential (`e^x`).
433 fn exp<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
434 /// Element-wise base-2 exponential (`2^x`).
435 fn exp2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
436 /// Element-wise natural logarithm.
437 fn log<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
438 /// Element-wise base-2 logarithm.
439 fn log2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
440 /// Element-wise reciprocal square root (`1/sqrt(x)`).
441 fn rsqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
442 /// Element-wise sigmoid (`1/(1+e^-x)`).
443 fn sigmoid<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
444 /// Element-wise square root.
445 fn sqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
446 /// Element-wise square root, round-to-nearest.
447 fn sqrt_rn<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
448 /// Element-wise error function.
449 fn erf<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
450 /// Element-wise arctangent.
451 fn atan<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
452
453 /*------------------------------ Math Ops — Float (higher-level) ------------------------------*/
454
455 /// Numerically-stable softmax along `dim`. `dim = None` defaults to the last dimension.
456 ///
457 /// - `keep_dims`: retain the reduced dimension with length 1 (default `false`).
458 /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
459 fn softmax<D: ty::Float>(
460 x: Self::Tensor<D>,
461 dim: Option<i32>,
462 keep_dims: bool,
463 ieee_rounding: bool,
464 ) -> Self::Tensor<D>;
465
466 /*------------------------------ Math Ops — Binary ------------------------------*/
467
468 /// Element-wise maximum of two tensors.
469 fn maximum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
470 /// Element-wise minimum of two tensors.
471 fn minimum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
472
473 /// Element-wise clamp of `x` to `[lo, hi]`.
474 fn clamp<D: ty::Num>(
475 x: Self::Tensor<D>,
476 lo: Self::Tensor<D>,
477 hi: Self::Tensor<D>,
478 ) -> Self::Tensor<D>;
479
480 /// Element-wise fused multiply-add: `x * y + z`.
481 fn fma<D: ty::Float>(
482 x: Self::Tensor<D>,
483 y: Self::Tensor<D>,
484 z: Self::Tensor<D>,
485 ) -> Self::Tensor<D>;
486
487 /// Element-wise floating-point division.
488 ///
489 /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
490 fn fdiv<D: ty::Float>(
491 x: Self::Tensor<D>,
492 y: Self::Tensor<D>,
493 ieee_rounding: bool,
494 ) -> Self::Tensor<D>;
495
496 /// Element-wise division, round-to-nearest.
497 fn div_rn<D: ty::Float>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
498
499 /// Element-wise high 32 bits of an unsigned 32×32→64-bit multiply.
500 fn umulhi(x: Self::Tensor<u32>, y: Self::Tensor<u32>) -> Self::Tensor<u32>;
501
502 /// Ceiling integer division: `ceil(x / div)`.
503 fn cdiv(x: i32, div: i32) -> i32;
504
505 /// Swizzle 2-D indices for shared-memory bank-conflict avoidance.
506 /// Returns the remapped `(i, j)` indices.
507 fn swizzle2d(i: i32, j: i32, size_i: i32, size_j: i32, size_g: i32) -> (i32, i32);
508
509 /*------------------------------ Reduction Ops ------------------------------*/
510
511 /// Sum all elements along `axis`. `axis = None` reduces all dimensions.
512 fn sum<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
513
514 /// Maximum along `axis`. `axis = None` reduces all dimensions.
515 fn max<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
516
517 /// Maximum along `axis`, also returning the index of the maximum.
518 ///
519 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
520 fn max_with_indices<D: ty::Num>(
521 x: Self::Tensor<D>,
522 axis: i32,
523 tie_break_left: bool,
524 keep_dims: bool,
525 ) -> (Self::Tensor<D>, Self::I32Tensor);
526
527 /// Minimum along `axis`. `axis = None` reduces all dimensions.
528 fn min<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
529
530 /// Minimum along `axis`, also returning the index of the minimum.
531 ///
532 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
533 fn min_with_indices<D: ty::Num>(
534 x: Self::Tensor<D>,
535 axis: i32,
536 tie_break_left: bool,
537 keep_dims: bool,
538 ) -> (Self::Tensor<D>, Self::I32Tensor);
539
540 /// Index of the maximum along `axis`.
541 ///
542 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
543 fn argmax<D: ty::Num>(
544 x: Self::Tensor<D>,
545 axis: i32,
546 tie_break_left: bool,
547 keep_dims: bool,
548 ) -> Self::I32Tensor;
549
550 /// Index of the minimum along `axis`.
551 ///
552 /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
553 fn argmin<D: ty::Num>(
554 x: Self::Tensor<D>,
555 axis: i32,
556 tie_break_left: bool,
557 keep_dims: bool,
558 ) -> Self::I32Tensor;
559
560 /// XOR-reduction along `axis`. `axis = None` reduces all dimensions.
561 fn xor_sum<D: ty::Int>(
562 x: Self::Tensor<D>,
563 axis: Option<i32>,
564 keep_dims: bool,
565 ) -> Self::Tensor<D>;
566
567 /*------------------------------ Scan / Sort Ops ------------------------------*/
568
569 /// Cumulative sum along `axis`.
570 fn cumsum<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
571
572 /// Cumulative product along `axis`.
573 fn cumprod<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
574
575 /// Sort along `dim`. `dim = None` sorts along the last dimension.
576 fn sort<D: ty::Num>(x: Self::Tensor<D>, dim: Option<i32>, descending: bool) -> Self::Tensor<D>;
577
578 /// Compute a histogram with `num_bins` bins (width 1, starting at 0).
579 ///
580 /// - `mask`: when `Some`, masked-off elements are excluded (default `None`).
581 fn histogram(
582 x: Self::I32Tensor,
583 num_bins: i32,
584 mask: Option<Self::BoolTensor>,
585 ) -> Self::I32Tensor;
586
587 /// Generic reduction along `axis` using a user-supplied combine function.
588 ///
589 /// `combine_fn` must be a statically-known function pointer (corresponds to a
590 /// `@triton.jit`-decorated helper in Python Triton).
591 fn reduce<D: ty::Dtype, O: ty::Dtype>(
592 x: Self::Tensor<D>,
593 axis: i32,
594 combine_fn: fn(Self::Tensor<O>, Self::Tensor<O>) -> Self::Tensor<O>,
595 keep_dims: bool,
596 ) -> Self::Tensor<O>;
597
598 /// Generic prefix-scan along `axis` using a user-supplied combine function.
599 ///
600 /// - `reverse`: scan in the reverse direction (default `false`).
601 fn associative_scan<D: ty::Dtype>(
602 x: Self::Tensor<D>,
603 axis: i32,
604 combine_fn: fn(Self::Tensor<D>, Self::Tensor<D>) -> Self::Tensor<D>,
605 reverse: bool,
606 ) -> Self::Tensor<D>;
607
608 /*------------------------------ Atomic Ops ------------------------------*/
609
610 /// Atomic add. Returns the previous value.
611 ///
612 /// - `mask`: when `Some`, only masked lanes perform the operation (default `None`).
613 /// - `sem`: memory ordering semantics (default `None` = AcqRel).
614 /// - `scope`: synchronization scope (default `None` = Gpu).
615 fn atomic_add<D: ty::Num>(
616 ptr: Self::Tensor<Self::Pointer<D>>,
617 val: Self::Tensor<D>,
618 mask: Option<Self::BoolTensor>,
619 sem: Option<MemSem>,
620 scope: Option<MemScope>,
621 ) -> Self::Tensor<D>;
622
623 /// Atomic bitwise AND. Returns the previous value. See [`Triton::atomic_add`] for parameters.
624 fn atomic_and<D: ty::Int>(
625 ptr: Self::Tensor<Self::Pointer<D>>,
626 val: Self::Tensor<D>,
627 mask: Option<Self::BoolTensor>,
628 sem: Option<MemSem>,
629 scope: Option<MemScope>,
630 ) -> Self::Tensor<D>;
631
632 /// Atomic bitwise OR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
633 fn atomic_or<D: ty::Int>(
634 ptr: Self::Tensor<Self::Pointer<D>>,
635 val: Self::Tensor<D>,
636 mask: Option<Self::BoolTensor>,
637 sem: Option<MemSem>,
638 scope: Option<MemScope>,
639 ) -> Self::Tensor<D>;
640
641 /// Atomic bitwise XOR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
642 fn atomic_xor<D: ty::Int>(
643 ptr: Self::Tensor<Self::Pointer<D>>,
644 val: Self::Tensor<D>,
645 mask: Option<Self::BoolTensor>,
646 sem: Option<MemSem>,
647 scope: Option<MemScope>,
648 ) -> Self::Tensor<D>;
649
650 /// Atomic maximum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
651 fn atomic_max<D: ty::Num>(
652 ptr: Self::Tensor<Self::Pointer<D>>,
653 val: Self::Tensor<D>,
654 mask: Option<Self::BoolTensor>,
655 sem: Option<MemSem>,
656 scope: Option<MemScope>,
657 ) -> Self::Tensor<D>;
658
659 /// Atomic minimum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
660 fn atomic_min<D: ty::Num>(
661 ptr: Self::Tensor<Self::Pointer<D>>,
662 val: Self::Tensor<D>,
663 mask: Option<Self::BoolTensor>,
664 sem: Option<MemSem>,
665 scope: Option<MemScope>,
666 ) -> Self::Tensor<D>;
667
668 /// Atomic exchange. Returns the previous value. See [`Triton::atomic_add`] for parameters.
669 fn atomic_xchg<D: ty::Dtype>(
670 ptr: Self::Tensor<Self::Pointer<D>>,
671 val: Self::Tensor<D>,
672 mask: Option<Self::BoolTensor>,
673 sem: Option<MemSem>,
674 scope: Option<MemScope>,
675 ) -> Self::Tensor<D>;
676
677 /// Atomic compare-and-swap. Returns the previous value.
678 fn atomic_cas<D: ty::Dtype>(
679 ptr: Self::Tensor<Self::Pointer<D>>,
680 cmp: Self::Tensor<D>,
681 val: Self::Tensor<D>,
682 sem: Option<MemSem>,
683 scope: Option<MemScope>,
684 ) -> Self::Tensor<D>;
685
686 /*------------------------------ Random Number Generation ------------------------------*/
687
688 /// Uniform random `f32` in `[0, 1)`.
689 ///
690 /// - `n_rounds`: number of Philox rounds (default `10`).
691 fn rand(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
692
693 /// Standard-normal random `f32`.
694 ///
695 /// - `n_rounds`: number of Philox rounds (default `10`).
696 fn randn(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
697
698 /// Random `i32`.
699 ///
700 /// - `n_rounds`: number of Philox rounds (default `10`).
701 fn randint(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::I32Tensor;
702
703 /// Four random `i32` streams (maximally efficient Philox entry point).
704 ///
705 /// - `n_rounds`: number of Philox rounds (default `10`).
706 fn randint4x(
707 seed: u32,
708 offsets: Self::I32Tensor,
709 n_rounds: i32,
710 ) -> (
711 Self::I32Tensor,
712 Self::I32Tensor,
713 Self::I32Tensor,
714 Self::I32Tensor,
715 );
716
717 /*------------------------------ Inline Assembly ------------------------------*/
718
719 /// Emit inline PTX/assembly applied element-wise across a tensor.
720 ///
721 /// - `asm`: the assembly template string.
722 /// - `constraints`: register constraint string.
723 /// - `is_pure`: whether the assembly has no side-effects (may be CSE'd).
724 /// - `pack`: number of elements packed into each register.
725 fn inline_asm_elementwise<D: ty::Dtype>(
726 asm: &str,
727 constraints: &str,
728 is_pure: bool,
729 pack: i32,
730 ) -> Self::Tensor<D>;
731
732 /*------------------------------ Compiler Hint Ops ------------------------------*/
733
734 /// Assert that `cond` is always true, allowing the compiler to assume so.
735 fn assume(cond: Self::BoolTensor);
736
737 /// Hint that values of `x` are always multiples of the given constants.
738 fn multiple_of<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
739
740 /// Hint that `x` has `values[i]` contiguous elements along dimension `i`.
741 fn max_contiguous<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
742
743 /// Hint that `x` has `values[i]` constant elements along dimension `i`.
744 fn max_constancy<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
745
746 /*------------------------------ Debug Ops ------------------------------*/
747
748 /// Insert a memory barrier for debugging purposes.
749 fn debug_barrier();
750
751 /// Emit a runtime assertion on the device. No-op when `cond` is `true`.
752 ///
753 /// - `msg`: message shown on assertion failure (default `""`).
754 /// - `mask`: when `Some`, only lanes where mask is `true` check the assertion.
755 fn device_assert(cond: Self::BoolTensor, msg: &str, mask: Option<Self::BoolTensor>);
756
757 /// Print a tensor value from device code for debugging.
758 ///
759 /// - `hex`: print values in hexadecimal (default `false`).
760 fn device_print<D: ty::Dtype>(prefix: &str, val: Self::Tensor<D>, hex: bool);
761
762 /// Compile-time assertion (evaluated before kernel launch).
763 fn static_assert(cond: bool, msg: &str);
764
765 /// Compile-time print (evaluated before kernel launch).
766 fn static_print(msg: &str);
767}