use std::time::Instant;
use rlx_optim::{Adam, AdamW, Lion, Optimizer, Sgd};
fn fill(n: usize, seed: u32) -> Vec<f32> {
let mut s = seed;
(0..n)
.map(|_| {
s = s.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
((s >> 8) as f32 / 8_388_608.0 - 1.0) * 0.1
})
.collect()
}
fn bench(label: &str, n: usize, mut opt: Box<dyn Optimizer>) -> f64 {
let shape = [n];
let mut param = fill(n, 7);
let grad = fill(n, 11);
for _ in 0..5 {
opt.step("w", &shape, &mut param, &grad);
opt.end_iteration();
}
let iters = (200_000_000 / n).clamp(20, 2000);
let start = Instant::now();
for _ in 0..iters {
opt.step("w", &shape, &mut param, &grad);
opt.end_iteration();
}
let per_step = start.elapsed().as_secs_f64() / iters as f64;
let per_elem_ns = per_step * 1e9 / n as f64;
println!(
" {label:22} {:>9.1} µs/step {per_elem_ns:>6.2} ns/element {:>6.2} GB/s",
per_step * 1e6,
(n as f64 * 7.0 * 4.0) / per_step / 1e9
);
per_elem_ns
}
fn main() {
for n in [64 * 1024usize, 1024 * 1024, 8 * 1024 * 1024] {
println!(
"\n{} elements ({:.1} MiB per buffer)",
n,
(n * 4) as f64 / 1048576.0
);
bench("adamw (f64 default)", n, Box::new(AdamW::new(1e-3)));
bench(
"adamw f32Math",
n,
Box::new(AdamW::new(1e-3).with_f32_math(true)),
);
bench("adam (f64 default)", n, Box::new(Adam::new(1e-3)));
bench(
"adam f32Math",
n,
Box::new(Adam::new(1e-3).with_f32_math(true)),
);
bench("sgd+momentum", n, {
let mut o = Sgd::new(1e-3);
o.momentum = 0.9;
Box::new(o)
});
bench("lion", n, Box::new(Lion::new(1e-3)));
}
}