shared_bench/
shared_bench.rs1use hrx::{
4 Result,
5 benchmark::percentile,
6 execution::{Access, BindingContract, KernelContract, MemoryPlacement, Runtime},
7};
8use std::time::Instant;
9fn main() -> Result<()> {
10 let args: Vec<_> = std::env::args().collect();
11 if args.len() != 4 {
12 return Err(hrx::Error::Message(
13 "usage: shared_bench <passthrough.xclbin> <instructions.bin> <bytes>".into(),
14 ));
15 }
16 let bytes = args[3]
17 .parse::<usize>()
18 .map_err(|e| hrx::Error::Message(e.to_string()))?;
19 let runtime = Runtime::new()?;
20 let program = unsafe { runtime.npu(0)?.load_program(&args[1]) }?;
21 let binding = |bytes, access| BindingContract {
22 bytes,
23 access,
24 alignment: 4,
25 layout: "passthrough".into(),
26 };
27 let kernel = unsafe {
28 program.kernel(
29 &std::fs::read(&args[2])?,
30 KernelContract {
31 bindings: vec![
32 binding(bytes, Access::Read),
33 binding(4096, Access::Read),
34 binding(bytes, Access::Write),
35 ],
36 constants: vec![],
37 },
38 )
39 }?;
40 let a = runtime.allocate(bytes, MemoryPlacement::Shared(program.clone()))?;
41 let b = runtime.allocate(4096, MemoryPlacement::Shared(program.clone()))?;
42 let c = runtime.allocate(bytes, MemoryPlacement::Shared(program.clone()))?;
43 let mut graph = runtime.graph();
44 graph.fill(a.view(), 0x35)?;
45 graph.npu(&kernel, &[a.view(), b.view(), c.view()])?;
46 let graph = graph.prepare()?;
47 for _ in 0..5 {
48 graph.submit()?.wait()?;
49 }
50 let mut samples = Vec::new();
51 for _ in 0..100 {
52 let start = Instant::now();
53 graph.submit()?.wait()?;
54 samples.push(start.elapsed().as_secs_f64());
55 }
56 if c.map_read()?.iter().any(|&b| b != 0x35) {
57 return Err(hrx::Error::Message("incorrect benchmark output".into()));
58 }
59 samples.sort_by(f64::total_cmp);
60 println!(
61 "bytes={bytes} p50_us={:.2} p95_us={:.2}",
62 percentile(&samples, 50) * 1e6,
63 percentile(&samples, 95) * 1e6
64 );
65 Ok(())
66}