//! The engine's energy-landscape GPU members metered by this machine's own on-chip //! counter (`sink_meter::RunCounter`): the GPU rail through IOReport on macOS, the board //! through NVML on Linux. Hardware only, run by hand with `--ignored --nocapture`. //! //! The operator's term these tests declare for the counter, 100,000 ppm, is a coarse choice //! for a hand run, not an evaluation of the counter's own error; the meter adds its own terms //! beside it, and nothing here seals a figure. The figure is the whole rail or board over the //! call's window, idle draw and any other work on the device included, as the answer says. #![allow(dead_code, unused_imports)] use std::time::Instant; use wai::sink_meter::RunCounter; use wai_quantum::quantum_landscape::energy::Landscape; use wai_quantum::quantum_landscape::member::{Chain, CpuReference, Member}; use wai_quantum::quantum_landscape::sample::{chain_seed, out, schedule, start}; use wai_quantum::quantum_landscape::settle::Workload; const DECLARED_PPM: u32 = 100_000; fn work(n: usize, chains: u64, sweeps: u32) -> (Workload, Vec, Vec) { let mut l = Landscape::new(n); let mut k = 0u64; for i in 0..n { for _ in 0..4 { k += 1; let j = (out(0x7177, k) % n as u64) as usize; if j != i { l.couple(i, j, if k % 3 == 0 { -1 } else { 1 }); } } } l.set_cost(1); let cs = (0..chains) .map(|r| { let c = chain_seed(9, r); Chain { start: start(c, n), seed: c } }) .collect(); (l.lower(), cs, schedule(l.default_temperature(), sweeps)) } fn metered(m: &dyn Member, w: &Workload, cs: &[Chain], temperatures: &[f64]) { let t = Instant::now(); let got = m.chains(w, cs, temperatures).unwrap(); let wall = t.elapsed().as_secs_f64(); let reading = m.meter(); println!("{}: {} chains, {} cells, {} sweeps in {wall:.2} s wall-clock", m.id(), cs.len(), w.n(), temperatures.len()); match &reading { Some(r) => println!(" read: {} µJ over {} µs, class {}\n covering {}", r.joules_micro, r.window_us, r.class, r.scope.as_deref().unwrap_or("this run alone")), None => println!(" no reading"), } let r = reading.expect("a call longer than the profile's minimum window, on a live counter, gives a reading"); assert_eq!(r.class["energy_provenance"], "OnChipCounter", "{}", r.class); assert!(r.scope.as_deref().is_some_and(|s| s.contains("idle draw")), "{:?}", r.scope); // The same bits as the reference, on a slice of the chains. assert_eq!(got[..4], CpuReference.chains(w, &cs[..4], temperatures).unwrap()[..]); } #[cfg(all(target_os = "macos", feature = "quantum_landscape_metal"))] #[test] #[ignore] fn a_metal_member_reads_the_gpu_rail() { let counter = wai::sink_meter::IoReportGpu::open().expect("IOReport's GPU Energy channel"); let m = wai_quantum::quantum_landscape::metal::discover().into_iter().find_map(Result::ok).expect("a Metal device"); let m = m.with_meter(Box::new(RunCounter::new(Box::new(counter), DECLARED_PPM).unwrap())); let (w, cs, t) = work(4096, 1024, 400); metered(&m, &w, &cs, &t); } #[cfg(all(target_os = "linux", feature = "quantum_landscape_cuda"))] #[test] #[ignore] fn a_cuda_member_reads_the_board() { let counter = wai::sink_meter::Nvml::open().expect("NVML"); // energy-measurement §9.3: the bridge itself refuses an implausible counter, so no figure // can come from one. This hand run then has nothing to read, and says so. let meter = match RunCounter::nvml(counter, DECLARED_PPM) { Ok(m) => m, Err(why) => { println!("no meter: {why}"); return; } }; let m = wai_quantum::quantum_landscape::cuda::discover().into_iter().find_map(Result::ok).expect("a CUDA device"); let m = m.with_meter(Box::new(meter)); let (w, cs, t) = work(4096, 1024, 1200); metered(&m, &w, &cs, &t); }