use rlx_ir::{DType, Graph, ScaleLayout, ScaledFormat, Shape, SynthKind};
use rlx_runtime::{Device, Session};
const M: usize = 4;
const K: usize = 32;
const N: usize = 6;
const D: usize = 2;
const NE: usize = 8;
fn kb() -> usize {
K / D
}
fn x_data() -> Vec<f32> {
(0..M * K).map(|i| (i as f32 * 0.1).sin()).collect()
}
fn cb_data() -> Vec<f32> {
(0..NE * D).map(|i| (i as f32 * 0.3).cos() * 0.8).collect()
}
fn idx_data() -> Vec<u8> {
(0..N * kb()).map(|i| (i % NE) as u8).collect()
}
fn kind() -> SynthKind {
SynthKind::Codebook {
entry_dim: D as u32,
num_entries: NE as u32,
}
}
fn cosine(a: &[f32], b: &[f32]) -> f32 {
let d: f32 = a.iter().zip(b).map(|(x, y)| x * y).sum();
let na = a.iter().map(|x| x * x).sum::<f32>().sqrt();
let nb = b.iter().map(|x| x * x).sum::<f32>().sqrt();
d / (na * nb + 1e-12)
}
fn run(fmt: Option<ScaledFormat>) -> Vec<f32> {
let mut g = Graph::new("qcb");
let x = g.input("x", Shape::new(&[M, K], DType::F32));
let cb = g.input("cb", Shape::new(&[NE, D], DType::F32));
let idx = g.param("idx", Shape::new(&[N, kb()], DType::U8));
let out_shape = Shape::new(&[M, N], DType::F32);
let y = match fmt {
None => g.synth_matmul(x, idx, cb, kind(), out_shape),
Some(f) => {
let (codes, scale) = g.scaled_quantize(cb, f, ScaleLayout::PerTensor);
g.synth_matmul_qcodebook(
x,
idx,
codes,
scale,
kind(),
f,
ScaleLayout::PerTensor,
out_shape,
)
}
};
g.set_outputs(vec![y]);
let mut c = Session::new(Device::Cpu).compile(g);
c.set_param_typed("idx", &idx_data(), DType::U8);
c.run(&[("x", &x_data()), ("cb", &cb_data())])
.pop()
.unwrap()
}
#[test]
fn qcodebook_formats_track_f32() {
let reference = run(None);
let cases = [
(ScaledFormat::F8E4M3, 0.97f32),
(ScaledFormat::F8E5M2, 0.95),
(ScaledFormat::F4E2M1, 0.80),
(ScaledFormat::custom(3, 0), 0.50), ];
for (fmt, tol) in cases {
let out = run(Some(fmt));
assert_eq!(out.len(), M * N);
assert!(out.iter().all(|v| v.is_finite()), "{fmt:?}: non-finite");
let cos = cosine(&reference, &out);
eprintln!("qcodebook {fmt:?}: cos_vs_f32={cos:.4}");
assert!(cos >= tol, "{fmt:?}: cosine {cos} < {tol}");
}
}