Skip to main content

rlevo_evolution/ops/kernels/
mod.rs

1//! Custom `CubeCL` kernels for hot-path operators.
2//!
3//! This module is a **design placeholder**. The current release ships
4//! only the pure-tensor operator baselines in [`crate::ops::selection`],
5//! [`crate::ops::crossover`], and [`crate::ops::mutation`]. Those
6//! compose from Burn tensor primitives and run on every backend Burn
7//! supports (flex, wgpu, …) with no extra work. The `custom-kernels`
8//! Cargo feature exists so downstream crates can pin the future ABI
9//! when kernels land.
10//!
11//! # Why kernels aren't in the current release
12//!
13//! Three operator paths were identified where a fused `CubeCL` kernel
14//! would eliminate multi-launch overhead. Landing real kernels requires
15//! non-trivial `CubeCL` integration (`cubecl 0.9` ships with Burn 0.20.1)
16//! and device-specific validation on wgpu. None of that work blocks the
17//! core strategy machinery, so it was deferred to keep the release
18//! shippable.
19//!
20//! The three designs below document the intended interfaces so a
21//! future contributor can write them without re-deriving the
22//! motivation.
23//!
24//! # Tournament selection
25//!
26//! Today the pure-tensor path
27//! ([`super::selection::tournament_select`]) samples tournament
28//! indices on the host, packs them into a 1-D `Int` tensor, and does a
29//! single `tensor.select(0, indices)` gather. Cost at `pop_size = N`:
30//! `N` host-side index draws and one device kernel launch.
31//!
32//! A fused kernel would take the form
33//!
34//! ```ignore
35//! fn tournament_select_cube<F: Float, I: Int>(
36//!     fitness: &Tensor<F>,          // (N,)
37//!     rng_state: &Tensor<I>,         // (N, k)  pre-sampled index pairs
38//!     winners: &mut Tensor<I>,       // (N,)    output
39//! )
40//! ```
41//!
42//! performing the index sampling and comparison in a single launch,
43//! eliminating the host trip entirely. Expected speedup at `N ≥ 256`
44//! on wgpu: order-of-magnitude.
45//!
46//! # DE trial-vector construction
47//!
48//! Classical DE computes `v_i = x_{r1} + F · (x_{r2} − x_{r3})` plus
49//! a binomial-crossover mask per gene. In
50//! [`crate::algorithms::de`] this is composed from three `select`s,
51//! one subtract, one `mul_scalar`, one mask-build, and one
52//! `mask_where` — seven kernel launches per generation.
53//!
54//! A fused kernel that takes the whole population plus pre-sampled
55//! indices and emits the trial vector in one pass:
56//!
57//! ```ignore
58//! fn de_trial_cube<F: Float, I: Int>(
59//!     pop: &Tensor<F>,               // (N, D)
60//!     indices: &Tensor<I>,           // (N, k)  sampled parent indices
61//!     f: F, cr: F,                   // scalars
62//!     rng_bits: &Tensor<I>,          // crossover mask seeds
63//!     variant: u32,                  // const-generic DeVariant discriminant
64//!     trial: &mut Tensor<F>,         // (N, D)  output
65//! )
66//! ```
67//!
68//! Expected impact: DE's inner loop is dominated by these 7 launches;
69//! collapsing to 1 would likely double throughput at `pop_size ≥ 256`.
70//!
71//! # Fitness-proportionate (roulette) selection
72//!
73//! Roulette selection is a prefix-sum + inverse-CDF lookup. Burn's
74//! `cumsum` + `searchsorted` would work but materializes two
75//! intermediate tensors. This kernel is lower priority than the two
76//! above — the pure-tensor path is fine for typical population sizes —
77//! but worth writing if profiling later shows roulette on a hot path.
78//!
79//! # Kernel infrastructure
80//!
81//! When implementing these:
82//!
83//! 1. Add `cubecl` to `rlevo-evolution`'s dependencies (gated on the
84//!    `custom-kernels` feature).
85//! 2. Use `#[cube(launch_unchecked)]` with Burn's `backend::custom` API
86//!    to plug into the `Backend` trait.
87//! 3. Provide a pure-tensor fallback (which is the current
88//!    implementation) for backends that don't support `CubeCL`.
89//! 4. Expose a toggle at the operator level so benchmarks can A/B
90//!    the two paths.
91
92#![allow(dead_code)]