open-standards/wai/wai-ops-npu/tests/width.rs
Transaction Science e1da73a18c wai-ops-npu: wai-ops/1-npu on a neural processor's compute core, exact on every subset vector
A new crate, wai/wai-ops-npu, with no dependency but wai-ops. Its kernel runs
on one compute core of a tile array, built at run time with the array's open
toolchain; its host side is compiled against the device runtime and loaded.
The interpreter runs each graph through wai_ops::run_with and asks the core for
every arithmetic operator's outputs: conv and conv_transpose as multiply-
accumulate lines (8- and 16-bit operands into 32-bit accumulator lanes, 32-bit
operands into 64-bit lanes, the width the certificate's mac record allows),
rescale, chscale and mul through the unit's shift-round step under the mode
that is the operator's rounding, the elementwise operators, and lut16 a table
block at a time. Movement, policies, checks and state stay the interpreter's.

The unit's shift-round step is exact for shifts 0..59 only: it takes 60..63 as
a left shift by 64 - s (measured), so those shifts go through the core's scalar
unit in 64-bit arithmetic.

Tests: the corpus (every graph vector in the subset, against the committed
results and the interpreter), the rounding, saturation, lane and
requantisation probes, twelve kernel edits the corpus must catch, and the
graphs outside the subset by acc32 alone, which are not exact here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-22 07:04:13 -04:00

38 lines
1.8 KiB
Rust

//! Why the certificate decides which graphs run here: the graphs of the corpus that use
//! only the subset's operators but whose verdict does not meet `acc32` (§9.2 item 1),
//! run with their arithmetic on the device anyway, give results that differ from the
//! interpreter's, or carry values past the words a line holds. On every graph the
//! subset admits, the device agrees (`tests/corpus.rs`).
//!
//! With no device the test prints `ops-npu width: SKIPPED`, and fails under
//! `WAI_OPS_NPU_REQUIRE`.
#[path = "support/corpus.rs"]
mod corpus;
use corpus::report;
#[test]
fn graphs_the_certificate_keeps_out_are_not_exact_here() {
let vs = corpus::vectors();
let (rs, _) = corpus::ready(&vs);
let only_acc32: Vec<&corpus::Ready<'_>> = rs.iter().filter(|r| r.plan.reasons == ["acc32"]).collect();
assert!(only_acc32.len() > 100, "too few graphs outside the subset by acc32 alone: {}", only_acc32.len());
let Some(npu) = corpus::device("width") else { return };
let t = corpus::run_all(&npu, &only_acc32, 3);
// A graph whose values leave the words a line carries is declined operator by
// operator; those ran on the CPU and say nothing about the device.
report(&format!(
"ops-npu width: key={} graphs outside the subset by acc32 alone={}: on the device {} differ from the interpreter; operators declined (values past 32 bits)={}; errors={}",
npu.key(),
only_acc32.len(),
t.mismatched,
t.stats.declined.len(),
t.stats.errors.len()
));
for m in &t.mismatches {
println!("DIFFERS {m}");
}
assert!(t.stats.errors.is_empty(), "device errors: {:?}", t.stats.errors.first());
assert!(t.mismatched > 0, "every graph the certificate keeps from the subset agreed on the device");
}