use ffai_core::engine::{VlmEngine, VlmOptions};
use ffai_core::types::{ImageBuffer, PixelFormat};
use std::path::Path;
use std::time::Instant;
const IMG: usize = 384;
const ROUNDS: usize = 3;
fn reference_image() -> ImageBuffer {
let mut data = vec![0u8; IMG * IMG * 3];
let mut i = 0;
for y in 0..IMG {
let fy = y as f64 / IMG as f64;
for x in 0..IMG {
let fx = x as f64 / IMG as f64;
let r = 0.5 + 0.5 * (6.0 * std::f64::consts::PI * fx).sin();
let g = 0.5 + 0.5 * (6.0 * std::f64::consts::PI * fy + 1.0).sin();
let b = 0.5 + 0.5 * (6.0 * std::f64::consts::PI * (fx + fy) + 2.0).sin();
data[i] = (r.clamp(0.0, 1.0) * 255.0 + 0.5) as u8;
data[i + 1] = (g.clamp(0.0, 1.0) * 255.0 + 0.5) as u8;
data[i + 2] = (b.clamp(0.0, 1.0) * 255.0 + 0.5) as u8;
i += 3;
}
}
ImageBuffer { width: IMG as u32, height: IMG as u32, format: PixelFormat::Rgb8, data }
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let arm = std::env::args().nth(1).unwrap_or_else(|| "fuse_bias".into());
fn set_env(key: &'static str, on: &'static str, off: &'static str) -> impl Fn(bool) -> bool {
move |v| {
let prev = std::env::var(key).ok();
#[allow(unsafe_code)]
unsafe {
std::env::set_var(key, if v { on } else { off });
}
prev.as_deref() == Some(on)
}
}
let toggle: Box<dyn Fn(bool) -> bool> = match arm.as_str() {
"fuse_bias" => Box::new(ffai_argus::siglip::set_fuse_bias),
"late_norm" => Box::new(ffai_argus::siglip::set_late_normalize),
"fused_ln" => Box::new(ffai_argus::siglip::set_fused_ln),
"head_attn" => Box::new(ffai_argus::siglip::set_head_attn),
"kernels_parallel" => Box::new(set_env("FFAI_ARGUS_KERNELS_PARALLEL", "1", "0")),
"workers4" => Box::new(set_env("FFAI_ARGUS_TILE_WORKERS", "4", "6")),
"workers8" => Box::new(set_env("FFAI_ARGUS_TILE_WORKERS", "8", "6")),
other => return Err(format!("unknown arm {other}").into()),
};
let manifests = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../models");
let engine = ffai_argus::SmolVlm::with_manifest_dir(manifests);
let img = reference_image();
let opts = VlmOptions { max_new_tokens: Some(32), ..VlmOptions::default() };
let mut run = |on: bool| -> Result<(f64, String), Box<dyn std::error::Error>> {
let prev = toggle(on);
let t = Instant::now();
let text = engine.describe_image(&img, &opts)?;
let ms = t.elapsed().as_secs_f64() * 1e3;
toggle(prev);
Ok((ms, text))
};
let (_, on_text) = run(true)?;
let (_, off_text) = run(false)?;
println!(" arm `{arm}` ON : {on_text:?}");
println!(" arm `{arm}` OFF: {off_text:?}");
if on_text != off_text {
return Err("arms produce different captions — not a like-for-like A/B".into());
}
println!(" captions AGREE\n");
let (mut a, mut b) = (Vec::new(), Vec::new());
for r in 0..ROUNDS {
for on in if r % 2 == 0 { [true, false] } else { [false, true] } {
let (ms, _) = run(on)?;
if on {
a.push(ms);
} else {
b.push(ms);
}
}
for on in if r % 2 == 0 { [false, true] } else { [true, false] } {
let (ms, _) = run(on)?;
if on {
a.push(ms);
} else {
b.push(ms);
}
}
println!(" round {}/{ROUNDS}", r + 1);
}
let stat = |v: &mut Vec<f64>| {
v.sort_by(f64::total_cmp);
(v[0], v[v.len() / 2])
};
let (amin, amed) = stat(&mut a);
let (bmin, bmed) = stat(&mut b);
println!("\n WHOLE CAPTION — real engine, real workers — {} samples/arm\n", a.len());
println!(" {:<18} {:>10} {:>10}", "arm", "min ms", "median ms");
println!(" {:-<18} {:->10} {:->10}", "", "", "");
println!(" {:<18} {bmin:>10.0} {bmed:>10.0}", format!("{arm} OFF"));
println!(" {:<18} {amin:>10.0} {amed:>10.0}", format!("{arm} ON"));
println!(" {:-<18} {:->10} {:->10}", "", "", "");
println!(" {:<18} {:>9.3}x {:>9.3}x", "speedup", bmin / amin, bmed / amed);
Ok(())
}