#![allow(unsafe_op_in_unsafe_fn)]
use crate::thunk::*;
pub static FUSED_NOMIC_LAYER_COUNT: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LaneKind {
F32,
F16,
Bf16,
F64,
}
impl LaneKind {
pub fn resolve(dtype: rlx_ir::DType, elem_bytes: usize) -> Self {
match (dtype, elem_bytes) {
(rlx_ir::DType::F16, 2) => LaneKind::F16,
(rlx_ir::DType::BF16, 2) => LaneKind::Bf16,
(rlx_ir::DType::F64, 8) => LaneKind::F64,
_ => LaneKind::F32,
}
}
#[inline(always)]
pub unsafe fn load(self, base: *const u8, off: usize, idx: usize) -> f32 {
unsafe {
let p = base.add(off);
match self {
LaneKind::F32 => *(p as *const f32).add(idx),
LaneKind::F16 => half::f16::from_bits(*(p as *const u16).add(idx)).to_f32(),
LaneKind::Bf16 => half::bf16::from_bits(*(p as *const u16).add(idx)).to_f32(),
LaneKind::F64 => *(p as *const f64).add(idx) as f32,
}
}
}
#[inline(always)]
pub unsafe fn store(self, base: *mut u8, off: usize, idx: usize, v: f32) {
unsafe {
let p = base.add(off);
match self {
LaneKind::F32 => *(p as *mut f32).add(idx) = v,
LaneKind::F16 => *(p as *mut u16).add(idx) = half::f16::from_f32(v).to_bits(),
LaneKind::Bf16 => *(p as *mut u16).add(idx) = half::bf16::from_f32(v).to_bits(),
LaneKind::F64 => *(p as *mut f64).add(idx) = v as f64,
}
}
}
}
#[derive(Clone, strum_macros::IntoStaticStr)]
pub enum Thunk {
Nop,
ElementwiseRegion {
dst: usize,
len: u32,
input_offs: Vec<usize>,
chain: Vec<rlx_ir::op::ChainStep>,
scalar_input_mask: u32,
input_modulus: [u32; 16],
in_lanes: Vec<LaneKind>,
out_lane: LaneKind,
},
Sgemm {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
},
SgemmHalf {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
a_kind: HalfKind,
b_kind: HalfKind,
c_kind: HalfKind,
},
SgemmBf16 {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
},
SgemmF16 {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
},
SgemmT {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
ta: bool,
tb: bool,
},
SgdMomentum {
param: usize,
vel: usize,
grad: usize,
p_out: usize,
v_out: usize,
lr: f32,
mom: f32,
len: u32,
},
CgemmC64 {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
},
DenseSolveF64 {
a: usize,
b: usize,
x: usize,
n: u32,
nrhs: u32,
},
DenseSolveF32 {
a: usize,
b: usize,
x: usize,
n: u32,
nrhs: u32,
},
CholeskyF32 {
a: usize,
l: usize,
n: u32,
},
TriangularSolveF32 {
a: usize,
b: usize,
x: usize,
n: u32,
nrhs: u32,
lower: bool,
transpose: bool,
},
DetF32 {
a: usize,
out: usize,
n: u32,
log_abs: bool,
},
SortF32 {
src: usize,
dst: usize,
outer: u32,
axis_dim: u32,
inner: u32,
descending: bool,
arg: bool,
},
SvdF32 {
a: usize,
out: usize,
m: u32,
n: u32,
part: u8,
},
QrF32 {
a: usize,
out: usize,
m: u32,
n: u32,
part: u8,
},
BatchedDenseSolveF64 {
a: usize,
b: usize,
x: usize,
batch: u32,
n: u32,
nrhs: u32,
},
BatchedDenseSolveF32 {
a: usize,
b: usize,
x: usize,
batch: u32,
n: u32,
nrhs: u32,
},
BatchedDgemmF64 {
a: usize,
b: usize,
c: usize,
batch: u32,
m: u32,
k: u32,
n: u32,
a_bcast: bool,
b_bcast: bool,
},
BatchedSgemm {
a: usize,
b: usize,
c: usize,
batch: u32,
m: u32,
k: u32,
n: u32,
a_bcast: bool,
b_bcast: bool,
},
Dgemm {
a: usize,
b: usize,
c: usize,
m: u32,
k: u32,
n: u32,
},
TransposeF64 {
src: usize,
dst: usize,
in_total: u32,
out_dims: Vec<u32>,
in_strides: Vec<u32>,
},
ActivationF64 {
src: usize,
dst: usize,
len: u32,
kind: Activation,
},
ComplexNormSqF32 {
src: usize,
dst: usize,
len: u32,
},
ComplexNormSqBackwardF32 {
z: usize,
g: usize,
dz: usize,
len: u32,
},
ConjugateC64 {
src: usize,
dst: usize,
len: u32,
},
ActivationC64 {
src: usize,
dst: usize,
len: u32,
kind: Activation,
},
ReduceSumF64 {
src: usize,
dst: usize,
outer: u32,
reduced: u32,
inner: u32,
},
CopyF64 {
src: usize,
dst: usize,
len: u32,
},
CopyI64 {
src: usize,
dst: usize,
len: u32,
},
CastF32ToI64 {
src: usize,
dst: usize,
len: u32,
},
CastF32ToF64 {
src: usize,
dst: usize,
len: u32,
},
CastF64ToF32 {
src: usize,
dst: usize,
len: u32,
},
CastF64ToI64 {
src: usize,
dst: usize,
len: u32,
},
CastF64ToI32 {
src: usize,
dst: usize,
len: u32,
},
CastF64ToBool {
src: usize,
dst: usize,
len: u32,
},
CastI64ToI32 {
src: usize,
dst: usize,
len: u32,
},
CastI64ToF64 {
src: usize,
dst: usize,
len: u32,
},
CastI32ToF64 {
src: usize,
dst: usize,
len: u32,
},
CastF32ToF16 {
src: usize,
dst: usize,
len: u32,
},
CastF16ToF32 {
src: usize,
dst: usize,
len: u32,
},
CastF32ToBf16 {
src: usize,
dst: usize,
len: u32,
},
CastBf16ToF32 {
src: usize,
dst: usize,
len: u32,
},
CastF32ToI32 {
src: usize,
dst: usize,
len: u32,
},
CastI64ToF32 {
src: usize,
dst: usize,
len: u32,
},
CastBoolToI32 {
src: usize,
dst: usize,
len: u32,
},
CastBoolToF32 {
src: usize,
dst: usize,
len: u32,
},
CastF32ToBool {
src: usize,
dst: usize,
len: u32,
},
CastI32ToF32 {
src: usize,
dst: usize,
len: u32,
},
CastI32ToI64 {
src: usize,
dst: usize,
len: u32,
},
CastI32ToBool {
src: usize,
dst: usize,
len: u32,
},
CastI64ToBool {
src: usize,
dst: usize,
len: u32,
},
CastBoolToI64 {
src: usize,
dst: usize,
len: u32,
},
CastGeneric {
src: usize,
dst: usize,
len: u32,
src_dtype: rlx_ir::DType,
dst_dtype: rlx_ir::DType,
},
BinaryFullF64 {
lhs: usize,
rhs: usize,
dst: usize,
len: u32,
lhs_len: u32,
rhs_len: u32,
op: BinaryOp,
out_dims_bcast: Vec<u32>,
bcast_lhs_strides: Vec<u32>,
bcast_rhs_strides: Vec<u32>,
},
ConcatF64 {
dst: usize,
outer: u32,
inner: u32,
total_axis: u32,
inputs: Vec<(usize, u32, u32)>,
},
BinaryFullC64 {
lhs: usize,
rhs: usize,
dst: usize,
len: u32,
lhs_len: u32,
rhs_len: u32,
op: BinaryOp,
out_dims_bcast: Vec<u32>,
bcast_lhs_strides: Vec<u32>,
bcast_rhs_strides: Vec<u32>,
},
Scan {
body: Arc<ThunkSchedule>,
body_init: Arc<Vec<u8>>, body_input_off: usize, body_output_off: usize, outer_init_off: usize, outer_final_off: usize, length: u32,
carry_bytes: u32, save_trajectory: bool,
xs_inputs: Arc<Vec<(usize, usize, u32)>>,
bcast_inputs: Arc<Vec<(usize, usize, u32)>>,
num_checkpoints: u32,
},
ScanBackward {
body_vjp: Arc<ThunkSchedule>,
body_init: Arc<Vec<u8>>,
body_carry_in_off: usize, body_x_offs: Arc<Vec<usize>>, body_d_output_off: usize, body_dcarry_out_off: usize, outer_init_off: usize, outer_traj_off: usize, outer_upstream_off: usize, outer_xs_offs: Arc<Vec<(usize, u32)>>,
outer_dinit_off: usize, length: u32,
carry_bytes: u32,
carry_elem_size: u32,
save_trajectory: bool, num_checkpoints: u32,
forward_body: Option<Arc<ThunkSchedule>>,
forward_body_init: Option<Arc<Vec<u8>>>,
forward_body_carry_in_off: usize,
forward_body_output_off: usize,
forward_body_x_offs: Arc<Vec<usize>>,
},
ScanBackwardXs {
body_vjp: Arc<ThunkSchedule>,
body_init: Arc<Vec<u8>>,
body_carry_in_off: usize,
body_x_offs: Arc<Vec<usize>>,
body_d_output_off: usize,
body_dcarry_out_off: usize,
body_dxs_out_off: usize, outer_init_off: usize,
outer_traj_off: usize,
outer_upstream_off: usize,
outer_xs_offs: Arc<Vec<(usize, u32)>>,
outer_dxs_off: usize, length: u32,
carry_bytes: u32,
carry_elem_size: u32,
per_step_bytes: u32, save_trajectory: bool,
num_checkpoints: u32,
forward_body: Option<Arc<ThunkSchedule>>,
forward_body_init: Option<Arc<Vec<u8>>>,
forward_body_carry_in_off: usize,
forward_body_output_off: usize,
forward_body_x_offs: Arc<Vec<usize>>,
},
CustomFn {
body: Arc<ThunkSchedule>,
body_init: Arc<Vec<u8>>,
inputs: Arc<Vec<(usize, usize, u32)>>,
body_output_off: usize,
outer_output_off: usize,
out_bytes: u32,
},
FusedMmBiasAct {
a: usize,
w: usize,
bias: usize,
c: usize,
m: u32,
k: u32,
n: u32,
act: Option<Activation>,
},
FusedResidualLN {
x: usize,
res: usize,
bias: usize,
g: usize,
b: usize,
out: usize,
rows: u32,
h: u32,
eps: f32,
has_bias: bool,
},
FusedResidualRmsNorm {
x: usize,
res: usize,
bias: usize,
g: usize,
b: usize,
out: usize,
rows: u32,
h: u32,
eps: f32,
has_bias: bool,
},
BiasAdd {
src: usize,
bias: usize,
dst: usize,
m: u32,
n: u32,
},
BinaryFull {
lhs: usize,
rhs: usize,
dst: usize,
len: u32,
lhs_len: u32,
rhs_len: u32,
op: BinaryOp,
out_dims_bcast: Vec<u32>,
bcast_lhs_strides: Vec<u32>,
bcast_rhs_strides: Vec<u32>,
elem_bytes: u8,
},
ActivationInPlace {
data: usize,
len: u32,
act: Activation,
},
Gather {
table: usize,
table_len: u32,
idx: usize,
dst: usize,
num_idx: u32,
trailing: u32,
idx_i64: u8,
table_bytes: u8,
},
Narrow {
src: usize,
dst: usize,
outer: u32,
src_stride: u32,
dst_stride: u32,
inner: u32,
elem_bytes: u8,
},
Reverse {
src: usize,
dst: usize,
dims: Vec<u32>,
rev_mask: Vec<bool>,
elem_bytes: u8,
},
Copy {
src: usize,
dst: usize,
len: u32,
},
RoundHalf {
src: usize,
dst: usize,
len: u32,
bf16: bool,
},
LayerNorm {
src: usize,
g: usize,
b: usize,
dst: usize,
rows: u32,
h: u32,
eps: f32,
},
GroupNorm {
src: usize,
g: usize,
b: usize,
dst: usize,
n: u32,
c: u32,
h: u32,
w: u32,
num_groups: u32,
eps: f32,
},
BatchNormInference {
src: usize,
g: usize,
b: usize,
mean: usize,
var: usize,
dst: usize,
count: u32,
channels: u32,
eps: f32,
},
BatchNormInferenceBackwardInput {
x: usize,
gamma: usize,
mean: usize,
var: usize,
dy: usize,
dx: usize,
count: u32,
channels: u32,
eps: f32,
},
BatchNormInferenceBackwardGamma {
x: usize,
mean: usize,
var: usize,
dy: usize,
dgamma: usize,
count: u32,
channels: u32,
eps: f32,
},
BatchNormInferenceBackwardBeta {
dy: usize,
dbeta: usize,
count: u32,
channels: u32,
},
LayerNorm2d {
src: usize,
g: usize,
b: usize,
dst: usize,
n: u32,
c: u32,
h: u32,
w: u32,
eps: f32,
},
ConvTranspose2d {
src: usize,
weight: usize,
dst: usize,
n: u32,
c_in: u32,
h: u32,
w_in: u32,
c_out: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
dh: u32,
dw: u32,
groups: u32,
},
Conv3d {
src: usize,
weight: usize,
dst: usize,
n: u32,
c_in: u32,
d: u32,
h: u32,
w: u32,
c_out: u32,
d_out: u32,
h_out: u32,
w_out: u32,
kd: u32,
kh: u32,
kw: u32,
sd: u32,
sh: u32,
sw: u32,
pd: u32,
ph: u32,
pw: u32,
dd: u32,
dh: u32,
dw: u32,
groups: u32,
},
ConvTranspose3d {
src: usize,
weight: usize,
dst: usize,
n: u32,
c_in: u32,
d: u32,
h: u32,
w_in: u32,
c_out: u32,
d_out: u32,
h_out: u32,
w_out: u32,
kd: u32,
kh: u32,
kw: u32,
sd: u32,
sh: u32,
sw: u32,
pd: u32,
ph: u32,
pw: u32,
dd: u32,
dh: u32,
dw: u32,
groups: u32,
},
ResizeNearest2x {
src: usize,
dst: usize,
n: u32,
c: u32,
h: u32,
w: u32,
},
Interpolate3d {
src: usize,
dst: usize,
n: u32,
c: u32,
d_in: u32,
h_in: u32,
w_in: u32,
d_out: u32,
h_out: u32,
w_out: u32,
},
AxialRope2d {
src: usize,
dst: usize,
batch: u32,
seq: u32,
hidden: u32,
end_x: u32,
end_y: u32,
head_dim: u32,
num_heads: u32,
theta: f32,
repeat_factor: u32,
},
RmsNorm {
src: usize,
g: usize,
b: usize,
dst: usize,
rows: u32,
h: u32,
eps: f32,
},
AdaLayerNorm {
src: usize,
scale: usize,
shift: usize,
dst: usize,
rows: u32,
h: u32,
eps: f32,
layer_norm: bool,
mod_len: u32,
mod_off: Vec<u32>,
},
GatedResidual {
x: usize,
y: usize,
gate: usize,
dst: usize,
rows: u32,
h: u32,
gate_len: u32,
gate_off: Vec<u32>,
},
AdaLayerNormBackward {
x: usize,
scale: usize,
shift: usize,
dy: usize,
dst: usize,
rows: u32,
h: u32,
eps: f32,
layer_norm: bool,
mod_len: u32,
mod_off: Vec<u32>,
},
GatedResidualBackward {
x: usize,
y: usize,
gate: usize,
dy: usize,
dst: usize,
rows: u32,
h: u32,
gate_len: u32,
gate_off: Vec<u32>,
},
Softmax {
data: usize,
rows: u32,
cols: u32,
inner: u32,
},
Cumsum {
src: usize,
dst: usize,
rows: u32,
cols: u32,
exclusive: bool,
dtype: rlx_ir::DType,
},
CumScan {
src: usize,
dst: usize,
rows: u32,
cols: u32,
exclusive: bool,
is_max: bool,
},
SelectiveScan {
x: usize,
delta: usize,
a: usize,
b: usize,
c: usize,
dst: usize,
batch: u32,
seq: u32,
hidden: u32,
state_size: u32,
},
GatedDeltaNetBackward {
q: usize,
k: usize,
v: usize,
g: usize,
beta: usize,
state: usize,
dy: usize,
dst: usize,
batch: u32,
seq: u32,
heads: u32,
state_size: u32,
gate_per_channel: bool,
carry_state: bool,
},
GatedDeltaNet {
q: usize,
k: usize,
v: usize,
g: usize,
beta: usize,
state: usize,
dst: usize,
batch: u32,
seq: u32,
heads: u32,
state_size: u32,
gate_per_channel: bool,
carry_state: bool,
},
Lstm {
x: usize,
w_ih: usize,
w_hh: usize,
bias: usize,
h0: usize,
c0: usize,
dst: usize,
batch: u32,
seq: u32,
input_size: u32,
hidden: u32,
num_layers: u32,
bidirectional: bool,
carry: bool,
},
Gru {
x: usize,
w_ih: usize,
w_hh: usize,
b_ih: usize,
b_hh: usize,
h0: usize,
dst: usize,
batch: u32,
seq: u32,
input_size: u32,
hidden: u32,
num_layers: u32,
bidirectional: bool,
carry: bool,
},
Rnn {
x: usize,
w_ih: usize,
w_hh: usize,
bias: usize,
h0: usize,
dst: usize,
batch: u32,
seq: u32,
input_size: u32,
hidden: u32,
num_layers: u32,
bidirectional: bool,
carry: bool,
relu: bool,
},
Mamba2 {
x: usize,
dt: usize,
a: usize,
b: usize,
c: usize,
dst: usize,
batch: u32,
seq: u32,
heads: u32,
head_dim: u32,
state_size: u32,
},
Conv2D1x1 {
src: usize,
weight: usize,
dst: usize,
n: u32,
c_in: u32,
c_out: u32,
hw: u32,
},
DequantMatMul {
x: usize,
w_q: usize, scale: usize, zp: usize, dst: usize,
m: u32,
k: u32,
n: u32,
block_size: u32,
is_asymmetric: bool,
},
SynthMatMul {
x: usize, indices: usize, codebook: usize, dst: usize, m: u32,
k: u32,
n: u32,
entry_dim: u32,
num_entries: u32,
},
SplineActivation {
x: usize, coeff: usize, dst: usize, rows: u32,
channels: u32,
num_basis: u32,
grid_min: f32,
grid_max: f32,
},
DequantMatMulGguf {
x: usize, w_q: usize, dst: usize, m: u32,
k: u32,
n: u32,
scheme: rlx_ir::quant::QuantScheme,
},
DequantMatMulInt4 {
x: usize,
w_q: usize,
scale: usize,
zp: usize,
dst: usize,
m: u32,
k: u32,
n: u32,
block_size: u32,
is_asymmetric: bool,
},
DequantMatMulFp8 {
x: usize,
w_q: usize,
scale: usize,
dst: usize,
m: u32,
k: u32,
n: u32,
e5m2: bool,
},
DequantMatMulNvfp4 {
x: usize,
w_q: usize,
scale: usize,
global_scale: usize,
dst: usize,
m: u32,
k: u32,
n: u32,
},
DequantMatMulMxFp4x2 {
x: usize,
w_q: usize,
scale: usize,
dst: usize,
m: u32,
k: u32,
n: u32,
group: u32,
},
DequantMatMulMlx {
x: usize,
w_q: usize,
scale: usize,
zp: usize,
dst: usize,
m: u32,
k: u32,
n: u32,
scheme: rlx_ir::quant::QuantScheme,
},
ScaledMatMul {
lhs: usize,
rhs: usize,
lhs_scale: usize,
rhs_scale: usize,
bias: usize, dst: usize,
m: u32,
k: u32,
n: u32,
lhs_fmt: rlx_ir::ScaledFormat,
rhs_fmt: rlx_ir::ScaledFormat,
layout: rlx_ir::ScaleLayout,
has_bias: bool,
},
ScaledGroupedMatMul {
input: usize,
weight: usize,
input_scale: usize,
weight_scale: usize,
expert_idx: usize,
bias: usize, dst: usize,
m: u32,
k: u32,
n: u32,
num_experts: u32,
lhs_fmt: rlx_ir::ScaledFormat,
rhs_fmt: rlx_ir::ScaledFormat,
layout: rlx_ir::ScaleLayout,
has_bias: bool,
},
ScaledQuantize {
x: usize,
scale: usize,
dst: usize,
rows: u32,
cols: u32,
fmt: rlx_ir::ScaledFormat,
layout: rlx_ir::ScaleLayout,
},
ScaledQuantScale {
x: usize,
dst: usize,
rows: u32,
cols: u32,
fmt: rlx_ir::ScaledFormat,
layout: rlx_ir::ScaleLayout,
},
ScaledDequantize {
codes: usize,
scale: usize,
dst: usize,
rows: u32,
cols: u32,
fmt: rlx_ir::ScaledFormat,
layout: rlx_ir::ScaleLayout,
},
LoraMatMul {
x: usize,
w: usize,
a: usize,
b: usize,
dst: usize,
m: u32,
k: u32,
n: u32,
r: u32,
scale: f32,
},
Sample {
logits: usize,
dst: usize,
batch: u32,
vocab: u32,
top_k: u32, top_p: f32, temperature: f32, seed: u64,
},
RngNormal {
dst: usize,
len: u32,
mean: f32,
scale: f32,
key: u64,
op_seed: Option<f32>,
},
RngUniform {
dst: usize,
len: u32,
low: f32,
high: f32,
key: u64,
op_seed: Option<f32>,
},
Attention {
q: usize,
k: usize,
v: usize,
mask: usize,
out: usize,
batch: u32,
seq: u32,
kv_seq: u32,
heads: u32,
kv_heads: u32,
head_dim: u32,
v_head_dim: u32,
mask_kind: rlx_ir::op::MaskKind,
scale: f32,
softcap: f32,
q_row_stride: u32,
k_row_stride: u32,
v_row_stride: u32,
bhsd: bool,
},
AttentionBackward {
q: usize,
k: usize,
v: usize,
dy: usize,
mask: usize,
out: usize,
batch: u32,
seq: u32,
kv_seq: u32,
heads: u32,
head_dim: u32,
mask_kind: rlx_ir::op::MaskKind,
wrt: rlx_ir::op::AttentionBwdWrt,
bhsd: bool,
},
AttentionBackwardAll {
q: usize,
k: usize,
v: usize,
dy: usize,
mask: usize,
out_q: usize,
out_k: usize,
out_v: usize,
batch: u32,
seq: u32,
kv_seq: u32,
heads: u32,
head_dim: u32,
mask_kind: rlx_ir::op::MaskKind,
bhsd: bool,
},
Rope {
src: usize,
cos: usize,
sin: usize,
dst: usize,
batch: u32,
seq: u32,
hidden: u32,
head_dim: u32,
n_rot: u32,
cos_len: u32,
cos_row_stride: u32,
src_row_stride: u32,
interleaved: bool,
},
FusedAttnBlock {
hidden: usize,
qkv_w: usize,
out_w: usize,
mask: usize,
mask_kind: rlx_ir::op::MaskKind,
out: usize,
qkv_b: usize,
out_b: usize, cos: usize,
sin: usize,
cos_len: u32, batch: u32,
seq: u32,
hs: u32,
nh: u32,
dh: u32,
in_dim: u32,
out_dim: u32,
has_bias: bool,
has_rope: bool,
interleaved: bool,
},
FusedBertLayer {
hidden: usize,
qkv_w: usize,
qkv_b: usize,
out_w: usize,
out_b: usize,
mask: usize,
ln1_g: usize,
ln1_b: usize,
eps1: f32,
fc1_w: usize,
fc1_b: usize,
fc2_w: usize,
fc2_b: usize,
ln2_g: usize,
ln2_b: usize,
eps2: f32,
out: usize,
batch: u32,
seq: u32,
hs: u32,
nh: u32,
dh: u32,
int_dim: u32,
},
FusedNomicLayer {
hidden: usize,
qkv_w: usize,
out_w: usize,
mask: usize,
cos: usize,
sin: usize,
cos_len: u32,
ln1_g: usize,
ln1_b: usize,
eps1: f32,
fc11_w: usize,
fc12_w: usize,
fc2_w: usize,
ln2_g: usize,
ln2_b: usize,
eps2: f32,
out: usize,
batch: u32,
seq: u32,
hs: u32,
nh: u32,
dh: u32,
int_dim: u32,
interleaved: bool,
},
FusedSwiGLU {
src: usize,
dst: usize,
n_half: u32,
total: u32,
gate_first: bool,
},
KvAppend {
src: usize,
dst: usize,
outer: u32,
seq_cap: u32,
pos: u32,
inner_bytes: u32,
},
Concat {
dst: usize,
outer: u32,
inner: u32,
total_axis: u32,
inputs: Vec<(usize, u32, u32)>,
},
Compare {
lhs: usize,
rhs: usize,
dst: usize,
len: u32,
op: CmpOp,
inputs_i64: u8,
inputs_elem_bytes: u8,
dst_elem_bytes: u8,
lhs_scalar: bool,
rhs_scalar: bool,
lhs_len: u32,
rhs_len: u32,
out_dims_bcast: Vec<u32>,
bcast_lhs_strides: Vec<u32>,
bcast_rhs_strides: Vec<u32>,
},
Reduce {
src: usize,
dst: usize,
outer: u32,
reduced: u32,
inner: u32,
op: ReduceOp,
},
Histogram {
src: usize,
dst: usize,
n: u32,
bins: u32,
min: f32,
max: f32,
},
ArgReduce {
src: usize,
dst: usize,
outer: u32,
reduced: u32,
inner: u32,
is_max: bool,
},
TopK {
src: usize,
dst: usize,
outer: u32,
axis_dim: u32,
k: u32,
indices_i64: u8,
},
GroupedMatMul {
input: usize,
weight: usize,
expert_idx: usize,
dst: usize,
m: u32,
k_dim: u32,
n: u32,
num_experts: u32,
w_transposed: bool,
},
DequantGroupedMatMulGguf {
input: usize,
w_q: usize,
expert_idx: usize,
dst: usize,
m: u32,
k_dim: u32,
n: u32,
num_experts: u32,
scheme: rlx_ir::quant::QuantScheme,
},
DequantGroupedMatMulMlx {
input: usize,
w_q: usize,
scale: usize,
zp: usize,
expert_idx: usize,
dst: usize,
m: u32,
k_dim: u32,
n: u32,
num_experts: u32,
slab_bytes: u32,
scheme: rlx_ir::quant::QuantScheme,
scale_bf16: bool,
},
DequantMoEWeightsGguf {
w_q: usize,
dst: usize,
k_dim: u32,
n: u32,
num_experts: u32,
scheme: rlx_ir::quant::QuantScheme,
},
ScatterAdd {
updates: usize,
indices: usize,
dst: usize,
num_updates: u32,
out_dim: u32,
trailing: u32,
},
ScatterNd {
data: usize,
indices: usize,
updates: usize,
dst: usize,
data_shape: Vec<u32>,
indices_shape: Vec<u32>,
data_len: u32,
updates_len: u32,
indices_len: u32,
indices_i64: u8,
reduction: rlx_ir::ScatterNdReduction,
},
ScatterElements {
data: usize,
indices: usize,
updates: usize,
dst: usize,
data_shape: Vec<u32>,
indices_shape: Vec<u32>,
data_len: u32,
updates_len: u32,
indices_len: u32,
indices_i64: u8,
axis: i32,
reduction: rlx_ir::ScatterNdReduction,
},
GatherNd {
data: usize,
indices: usize,
dst: usize,
data_shape: Vec<u32>,
indices_shape: Vec<u32>,
data_len: u32,
indices_len: u32,
out_len: u32,
indices_i64: u8,
batch_dims: i32,
},
GatherElements {
data: usize,
indices: usize,
dst: usize,
data_shape: Vec<u32>,
indices_shape: Vec<u32>,
data_len: u32,
indices_len: u32,
out_len: u32,
indices_i64: u8,
data_elem_bytes: u8,
axis: i32,
},
Where {
cond: usize,
on_true: usize,
on_false: usize,
dst: usize,
len: u32,
elem_bytes: u8,
cond_elem_bytes: u8,
cond_scalar: bool,
true_scalar: bool,
false_scalar: bool,
},
Fma {
a: usize,
b: usize,
c: usize,
dst: usize,
len: u32,
elem_bytes: u8,
},
Transpose {
src: usize,
dst: usize,
in_total: u32,
out_dims: Vec<u32>,
in_strides: Vec<u32>,
elem_bytes: u8,
},
GatherAxis {
table: usize,
idx: usize,
dst: usize,
outer: u32,
axis_dim: u32,
num_idx: u32,
trailing: u32,
idx_i64: u8,
table_bytes: u8,
},
Pool2D {
src: usize,
dst: usize,
n: u32,
c: u32,
h: u32,
w: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
kind: ReduceOp,
},
Pool3D {
src: usize,
dst: usize,
n: u32,
c: u32,
d: u32,
h: u32,
w: u32,
d_out: u32,
h_out: u32,
w_out: u32,
kd: u32,
kh: u32,
kw: u32,
sd: u32,
sh: u32,
sw: u32,
pd: u32,
ph: u32,
pw: u32,
kind: ReduceOp,
},
Conv2D {
src: usize,
weight: usize,
dst: usize,
n: u32,
c_in: u32,
h: u32,
w: u32,
c_out: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
dh: u32,
dw: u32,
groups: u32,
},
QMatMul {
x: usize,
w: usize,
bias: usize,
out: usize,
m: u32,
k: u32,
n: u32,
x_zp: i32,
w_zp: i32,
out_zp: i32,
mult: f32,
},
QConv2d {
x: usize,
w: usize,
bias: usize,
out: usize,
n: u32,
c_in: u32,
h: u32,
w_in: u32,
c_out: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
dh: u32,
dw: u32,
groups: u32,
x_zp: i32,
w_zp: i32,
out_zp: i32,
mult: f32,
},
Quantize {
x: usize,
q: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
scales: Vec<f32>,
zero_points: Vec<i32>,
},
Dequantize {
q: usize,
x: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
scales: Vec<f32>,
zero_points: Vec<i32>,
},
FakeQuantize {
x: usize,
out: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
bits: u8,
ste: rlx_ir::op::SteKind,
scale_mode: rlx_ir::op::ScaleMode,
state_off: Option<usize>,
},
FakeQuantizeBackward {
x: usize,
dy: usize,
dx: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
bits: u8,
ste: rlx_ir::op::SteKind,
},
FakeQuantizeLSQ {
x: usize,
scale_off: usize,
out: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
bits: u8,
},
FakeQuantizeLSQBackwardX {
x: usize,
scale_off: usize,
dy: usize,
dx: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
bits: u8,
},
FakeQuantizeLSQBackwardScale {
x: usize,
scale_off: usize,
dy: usize,
dscale: usize,
len: u32,
chan_axis: u32,
chan_dim: u32,
inner: u32,
bits: u8,
},
ReluBackward {
x: usize,
dy: usize,
dx: usize,
len: u32,
},
ReluBackwardF64 {
x: usize,
dy: usize,
dx: usize,
len: u32,
},
ActivationBackward {
x: usize,
dy: usize,
dx: usize,
len: u32,
kind: Activation,
},
ActivationBackwardF64 {
x: usize,
dy: usize,
dx: usize,
len: u32,
kind: Activation,
},
LayerNormBackwardInput {
x: usize,
gamma: usize,
dy: usize,
dx: usize,
rows: u32,
h: u32,
eps: f32,
},
LayerNormBackwardGamma {
x: usize,
dy: usize,
dgamma: usize,
rows: u32,
h: u32,
eps: f32,
},
RmsNormBackwardInput {
x: usize,
gamma: usize,
beta: usize,
dy: usize,
dx: usize,
rows: u32,
h: u32,
eps: f32,
},
RmsNormBackwardGamma {
x: usize,
gamma: usize,
beta: usize,
dy: usize,
dgamma: usize,
rows: u32,
h: u32,
eps: f32,
},
RmsNormBackwardBeta {
x: usize,
gamma: usize,
beta: usize,
dy: usize,
dbeta: usize,
rows: u32,
h: u32,
eps: f32,
},
RopeBackward {
dy: usize,
cos: usize,
sin: usize,
dx: usize,
batch: u32,
seq: u32,
hidden: u32,
head_dim: u32,
n_rot: u32,
cos_len: u32,
cos_row_stride: u32,
interleaved: bool,
},
CumsumBackward {
dy: usize,
dx: usize,
rows: u32,
cols: u32,
exclusive: bool,
},
GatherBackward {
dy: usize,
indices: usize,
dst: usize,
outer: u32,
axis_dim: u32,
num_idx: u32,
trailing: u32,
},
GroupNormBackwardInput {
x: usize,
gamma: usize,
beta: usize,
dy: usize,
dx: usize,
n: u32,
c: u32,
h: u32,
w: u32,
num_groups: u32,
eps: f32,
},
GroupNormBackwardGamma {
x: usize,
dy: usize,
dgamma: usize,
n: u32,
c: u32,
h: u32,
w: u32,
num_groups: u32,
eps: f32,
},
GroupNormBackwardBeta {
dy: usize,
dbeta: usize,
n: u32,
c: u32,
h: u32,
w: u32,
},
MaxPool2dBackward {
x: usize,
dy: usize,
dx: usize,
n: u32,
c: u32,
h: u32,
w: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
},
Conv2dBackwardInput {
dy: usize,
w: usize,
dx: usize,
n: u32,
c_in: u32,
h: u32,
w_in: u32,
c_out: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
dh: u32,
dw: u32,
groups: u32,
},
Conv2dBackwardWeight {
x: usize,
dy: usize,
dw: usize,
n: u32,
c_in: u32,
h: u32,
w: u32,
c_out: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
dh: u32,
dw_dil: u32,
groups: u32,
},
MaxPool3dBackward {
x: usize,
dy: usize,
dx: usize,
n: u32,
c: u32,
d: u32,
h: u32,
w: u32,
d_out: u32,
h_out: u32,
w_out: u32,
kd: u32,
kh: u32,
kw: u32,
sd: u32,
sh: u32,
sw: u32,
pd: u32,
ph: u32,
pw: u32,
},
Conv3dBackwardInput {
dy: usize,
w: usize,
dx: usize,
n: u32,
c_in: u32,
d: u32,
h: u32,
w_in: u32,
c_out: u32,
d_out: u32,
h_out: u32,
w_out: u32,
kd: u32,
kh: u32,
kw: u32,
sd: u32,
sh: u32,
sw: u32,
pd: u32,
ph: u32,
pw: u32,
dd: u32,
dh: u32,
dw: u32,
groups: u32,
},
Conv3dBackwardWeight {
x: usize,
dy: usize,
dw: usize,
n: u32,
c_in: u32,
d: u32,
h: u32,
w: u32,
c_out: u32,
d_out: u32,
h_out: u32,
w_out: u32,
kd: u32,
kh: u32,
kw: u32,
sd: u32,
sh: u32,
sw: u32,
pd: u32,
ph: u32,
pw: u32,
dd: u32,
dh: u32,
dw_dil: u32,
groups: u32,
},
Im2Col {
x: usize,
col: usize,
n: u32,
c_in: u32,
h: u32,
w: u32,
h_out: u32,
w_out: u32,
kh: u32,
kw: u32,
sh: u32,
sw: u32,
ph: u32,
pw: u32,
dh: u32,
dw_dil: u32,
},
SoftmaxCrossEntropyDense {
logits: usize,
targets: usize,
dst: usize,
n: u32,
c: u32,
},
SoftmaxCrossEntropy {
logits: usize,
labels: usize,
dst: usize,
n: u32,
c: u32,
},
SoftmaxCrossEntropyBackward {
logits: usize,
labels: usize,
d_loss: usize,
dlogits: usize,
n: u32,
c: u32,
},
CustomOp {
kernel: Arc<dyn CpuKernel>,
inputs: Vec<(usize, u32, Shape)>, output: (usize, u32, Shape), attrs: Vec<u8>,
},
GaussianSplatRender {
positions_off: usize,
positions_len: usize,
scales_off: usize,
scales_len: usize,
rotations_off: usize,
rotations_len: usize,
opacities_off: usize,
opacities_len: usize,
colors_off: usize,
colors_len: usize,
sh_coeffs_off: usize,
sh_coeffs_len: usize,
meta_off: usize,
dst_off: usize,
dst_len: usize,
width: u32,
height: u32,
tile_size: u32,
radius_scale: f32,
alpha_cutoff: f32,
max_splat_steps: u32,
transmittance_threshold: f32,
max_list_entries: u32,
},
GaussianSplatRenderBackward {
positions_off: usize,
positions_len: usize,
scales_off: usize,
scales_len: usize,
rotations_off: usize,
rotations_len: usize,
opacities_off: usize,
opacities_len: usize,
colors_off: usize,
colors_len: usize,
sh_coeffs_off: usize,
sh_coeffs_len: usize,
meta_off: usize,
d_loss_off: usize,
d_loss_len: usize,
packed_off: usize,
packed_len: usize,
width: u32,
height: u32,
tile_size: u32,
radius_scale: f32,
alpha_cutoff: f32,
max_splat_steps: u32,
transmittance_threshold: f32,
max_list_entries: u32,
loss_grad_clip: f32,
sh_band: u32,
max_anisotropy: f32,
},
GaussianSplatPrepare {
positions_off: usize,
positions_len: usize,
scales_off: usize,
scales_len: usize,
rotations_off: usize,
rotations_len: usize,
opacities_off: usize,
opacities_len: usize,
colors_off: usize,
colors_len: usize,
sh_coeffs_off: usize,
sh_coeffs_len: usize,
meta_off: usize,
meta_len: usize,
prep_off: usize,
prep_len: usize,
width: u32,
height: u32,
tile_size: u32,
radius_scale: f32,
alpha_cutoff: f32,
max_splat_steps: u32,
transmittance_threshold: f32,
max_list_entries: u32,
},
GaussianSplatRasterize {
prep_off: usize,
prep_len: usize,
meta_off: usize,
meta_len: usize,
dst_off: usize,
dst_len: usize,
count: usize,
width: u32,
height: u32,
tile_size: u32,
alpha_cutoff: f32,
max_splat_steps: u32,
transmittance_threshold: f32,
max_list_entries: u32,
},
Fft1d {
src: usize,
dst: usize,
outer: u32,
n_complex: u32,
inverse: bool,
norm_tag: u32,
dtype: rlx_ir::DType,
},
Fft1dQ {
src: usize,
dst: usize,
outer: u32,
n_complex: u32,
inverse: bool,
norm_tag: u32,
scale_tag: u32,
},
FftButterflyStage {
state_src: usize,
state_dst: usize,
gate_src: usize,
rev_src: usize,
tw_re_src: usize,
tw_im_src: usize,
batch: u32,
n_fft: u32,
stage: u32,
},
LogMel {
spec: usize,
filters: usize,
dst: usize,
outer: u32,
n_fft: u32,
n_bins: u32,
n_mels: u32,
},
LogMelBackward {
spec: usize,
filters: usize,
dy: usize,
dst: usize,
outer: u32,
n_fft: u32,
n_bins: u32,
n_mels: u32,
},
WelchPeaks {
spec: usize,
dst: usize,
welch_batch: u32,
n_fft: u32,
n_segments: u32,
k: u32,
},
}
#[derive(Clone)]
pub struct ThunkSchedule {
pub thunks: Vec<Thunk>,
pub moe_resident: Option<std::sync::Arc<[bool]>>,
pub moe_resident_layers: Option<std::sync::Arc<Vec<std::sync::Arc<[bool]>>>>,
pub moe_topk_capture: Option<std::sync::Arc<crate::moe_topk_capture::MoeTopkCapture>>,
pub mask_threshold: f32,
pub mask_neg_inf: f32,
pub score_skip: f32,
pub compiled_fns: Vec<Arc<dyn Fn(*mut u8) + Send + Sync>>,
pub rng: Arc<std::sync::RwLock<rlx_ir::RngOptions>>,
}
impl ThunkSchedule {
pub fn strip_nops(&mut self) {
self.thunks.retain(|t| !matches!(t, Thunk::Nop));
self.compiled_fns.clear();
}
}
pub(crate) fn node_offset(arena: &Arena, id: NodeId) -> usize {
if arena.has_buffer(id) {
arena.byte_offset(id)
} else {
usize::MAX
}
}
pub(crate) fn thunk_read_offsets(t: &Thunk) -> Vec<usize> {
match t {
Thunk::Sgemm { a, b, .. } => vec![*a, *b],
Thunk::SgemmBf16 { a, b, .. } => vec![*a, *b],
Thunk::SgemmF16 { a, b, .. } => vec![*a, *b],
Thunk::SgemmT { a, b, .. } => vec![*a, *b],
Thunk::SgdMomentum {
param, vel, grad, ..
} => vec![*param, *vel, *grad],
Thunk::DenseSolveF64 { a, b, .. } => vec![*a, *b],
Thunk::DenseSolveF32 { a, b, .. } => vec![*a, *b],
Thunk::BatchedDenseSolveF64 { a, b, .. } => vec![*a, *b],
Thunk::BatchedDgemmF64 { a, b, .. } => vec![*a, *b],
Thunk::BatchedSgemm { a, b, .. } => vec![*a, *b],
Thunk::FusedMmBiasAct { a, w, bias, .. } => vec![*a, *w, *bias],
Thunk::ElementwiseRegion { input_offs, .. } => input_offs.clone(),
Thunk::BiasAdd { src, bias, .. } => vec![*src, *bias],
Thunk::BinaryFull { lhs, rhs, .. } => vec![*lhs, *rhs],
Thunk::BinaryFullF64 { lhs, rhs, .. } => vec![*lhs, *rhs],
Thunk::BinaryFullC64 { lhs, rhs, .. } => vec![*lhs, *rhs],
Thunk::ComplexNormSqF32 { src, .. } => vec![*src],
Thunk::ComplexNormSqBackwardF32 { z, g, .. } => vec![*z, *g],
Thunk::ConjugateC64 { src, .. } => vec![*src],
Thunk::Scan {
outer_init_off,
xs_inputs,
..
} => {
let mut v = vec![*outer_init_off];
for (_, outer_xs_off, _) in xs_inputs.iter() {
v.push(*outer_xs_off);
}
v
}
Thunk::ScanBackward {
outer_init_off,
outer_traj_off,
outer_upstream_off,
outer_xs_offs,
..
} => {
let mut v = vec![*outer_init_off, *outer_traj_off, *outer_upstream_off];
for (off, _) in outer_xs_offs.iter() {
v.push(*off);
}
v
}
Thunk::ScanBackwardXs {
outer_init_off,
outer_traj_off,
outer_upstream_off,
outer_xs_offs,
..
} => {
let mut v = vec![*outer_init_off, *outer_traj_off, *outer_upstream_off];
for (off, _) in outer_xs_offs.iter() {
v.push(*off);
}
v
}
Thunk::CustomFn { inputs, .. } => {
inputs.iter().map(|(_, outer_off, _)| *outer_off).collect()
}
Thunk::ActivationInPlace { data, .. } => vec![*data],
Thunk::LayerNorm { src, g, b, .. } | Thunk::GroupNorm { src, g, b, .. } => {
vec![*src, *g, *b]
}
Thunk::BatchNormInference {
src,
g,
b,
mean,
var,
..
} => vec![*src, *g, *b, *mean, *var],
Thunk::ResizeNearest2x { src, .. } => vec![*src],
Thunk::Interpolate3d { src, .. } => vec![*src],
Thunk::AxialRope2d { src, .. } => vec![*src],
Thunk::FusedResidualLN {
x, res, bias, g, b, ..
} => vec![*x, *res, *bias, *g, *b],
Thunk::FusedResidualRmsNorm {
x, res, bias, g, b, ..
} => vec![*x, *res, *bias, *g, *b],
Thunk::RmsNorm { src, g, b, .. } => vec![*src, *g, *b],
Thunk::AdaLayerNorm {
src, scale, shift, ..
} => vec![*src, *scale, *shift],
Thunk::GatedResidual { x, y, gate, .. } => vec![*x, *y, *gate],
Thunk::AdaLayerNormBackward {
x,
scale,
shift,
dy,
..
} => vec![*x, *scale, *shift, *dy],
Thunk::GatedResidualBackward { x, y, gate, dy, .. } => vec![*x, *y, *gate, *dy],
Thunk::Softmax { data, .. } => vec![*data],
Thunk::Cumsum { src, .. } => vec![*src],
Thunk::CumScan { src, .. } => vec![*src],
Thunk::Sample { logits, .. } => vec![*logits],
Thunk::RngNormal { .. } | Thunk::RngUniform { .. } => vec![],
Thunk::LoraMatMul { x, w, a, b, .. } => vec![*x, *w, *a, *b],
Thunk::DequantMatMul {
x, w_q, scale, zp, ..
} => vec![*x, *w_q, *scale, *zp],
Thunk::SynthMatMul {
x,
indices,
codebook,
..
} => vec![*x, *indices, *codebook],
Thunk::SplineActivation { x, coeff, .. } => vec![*x, *coeff],
Thunk::DequantMatMulGguf { x, w_q, .. } => vec![*x, *w_q],
Thunk::DequantMatMulInt4 {
x, w_q, scale, zp, ..
} => vec![*x, *w_q, *scale, *zp],
Thunk::DequantMatMulFp8 { x, w_q, scale, .. } => vec![*x, *w_q, *scale],
Thunk::DequantMatMulNvfp4 {
x,
w_q,
scale,
global_scale,
..
} => vec![*x, *w_q, *scale, *global_scale],
Thunk::DequantMatMulMxFp4x2 { x, w_q, scale, .. } => vec![*x, *w_q, *scale],
Thunk::DequantMatMulMlx {
x, w_q, scale, zp, ..
} => vec![*x, *w_q, *scale, *zp],
Thunk::ScaledMatMul {
lhs,
rhs,
lhs_scale,
rhs_scale,
bias,
has_bias,
..
} => {
let mut v = vec![*lhs, *rhs, *lhs_scale, *rhs_scale];
if *has_bias {
v.push(*bias);
}
v
}
Thunk::ScaledQuantize { x, scale, .. } => vec![*x, *scale],
Thunk::ScaledQuantScale { x, .. } => vec![*x],
Thunk::ScaledDequantize { codes, scale, .. } => vec![*codes, *scale],
Thunk::Conv2D1x1 { src, weight, .. } => vec![*src, *weight],
Thunk::SelectiveScan {
x, delta, a, b, c, ..
} => vec![*x, *delta, *a, *b, *c],
Thunk::GatedDeltaNet {
q,
k,
v,
g,
beta,
state,
carry_state,
..
} => {
let mut v = vec![*q, *k, *v, *g, *beta];
if *carry_state {
v.push(*state);
}
v
}
Thunk::Attention { q, k, v, mask, .. } => vec![*q, *k, *v, *mask],
Thunk::AttentionBackward {
q, k, v, dy, mask, ..
} => {
let mut v = vec![*q, *k, *v, *dy];
if *mask != 0 {
v.push(*mask);
}
v
}
Thunk::Fft1dQ { src, .. } => vec![*src],
Thunk::Rope { src, cos, sin, .. } => vec![*src, *cos, *sin],
Thunk::FusedAttnBlock {
hidden,
qkv_w,
out_w,
mask,
qkv_b,
out_b,
cos,
sin,
..
} => vec![*hidden, *qkv_w, *out_w, *mask, *qkv_b, *out_b, *cos, *sin],
Thunk::FusedSwiGLU { src, .. } => vec![*src],
Thunk::Concat { inputs, .. } => inputs.iter().map(|(off, _, _)| *off).collect(),
Thunk::ConcatF64 { inputs, .. } => inputs.iter().map(|(off, _, _)| *off).collect(),
Thunk::Narrow { src, .. } => vec![*src],
Thunk::Copy { src, .. } => vec![*src],
Thunk::RoundHalf { src, .. } => vec![*src],
Thunk::Gather { table, idx, .. } => vec![*table, *idx],
Thunk::Histogram { src, .. } => vec![*src],
_ => vec![],
}
}
pub struct ScanBodyPlan {
pub body: ThunkSchedule,
pub body_init: Vec<u8>,
pub body_input_off: usize,
pub body_output_off: usize,
pub carry_bytes: usize,
pub bcast_body_offs: Vec<usize>,
pub xs_body_offs: Vec<usize>,
}
impl std::fmt::Debug for ScanBodyPlan {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ScanBodyPlan")
.field("carry_bytes", &self.carry_bytes)
.field("body_input_off", &self.body_input_off)
.field("body_output_off", &self.body_output_off)
.field("num_bcast", &self.bcast_body_offs.len())
.field("num_xs", &self.xs_body_offs.len())
.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HalfKind {
F32,
Bf16,
F16,
}
impl HalfKind {
pub fn packed(self) -> bool {
!matches!(self, HalfKind::F32)
}
}