From af7aae757b20f1191d0243ffb3f66f427e5bd991 Mon Sep 17 00:00:00 2001 From: human9000 Date: Tue, 14 Jul 2026 18:40:53 +0300 Subject: [PATCH 1/2] Add onnx model criterion benches --- .../perf-runners/onnx-pr-bench/Cargo.lock | 227 +++++++++++++++- .../perf-runners/onnx-pr-bench/Cargo.toml | 7 + .../onnx-pr-bench/benches/onnx_models.rs | 246 ++++++++++++++++++ 3 files changed, 478 insertions(+), 2 deletions(-) create mode 100644 benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs diff --git a/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock b/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock index 929cd04..8a77ab3 100644 --- a/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock +++ b/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock @@ -17,6 +17,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + [[package]] name = "anyhow" version = "1.0.103" @@ -62,6 +74,21 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cblas-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6feecd82cce51b0204cf063f0041d69f24ce83f680d87514b004248e7b0fa65" +dependencies = [ + "libc", +] + [[package]] name = "cc" version = "1.2.65" @@ -78,6 +105,58 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + [[package]] name = "crc32fast" version = "1.5.0" @@ -87,6 +166,40 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -112,6 +225,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "either" version = "1.16.0" @@ -182,6 +301,17 @@ dependencies = [ "r-efi", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -194,6 +324,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "image" version = "0.25.10" @@ -219,6 +355,26 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -317,6 +473,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "petgraph" version = "0.7.1" @@ -376,7 +538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ "heck", - "itertools", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -396,7 +558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", "syn", @@ -506,6 +668,15 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.228" @@ -513,6 +684,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -604,12 +776,41 @@ dependencies = [ "syn", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + [[package]] name = "windows-link" version = "0.2.1" @@ -643,6 +844,7 @@ dependencies = [ name = "yscv-kernels" version = "0.1.10" dependencies = [ + "cblas-sys", "cc", "rayon", "rustc-hash", @@ -671,6 +873,7 @@ dependencies = [ name = "yscv-onnx-pr-bench" version = "0.1.0" dependencies = [ + "criterion", "image", "mimalloc", "rustc-hash", @@ -712,6 +915,26 @@ dependencies = [ "yscv-tensor", ] +[[package]] +name = "zerocopy" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/benchmarks/perf-runners/onnx-pr-bench/Cargo.toml b/benchmarks/perf-runners/onnx-pr-bench/Cargo.toml index 2a920da..d9736bc 100644 --- a/benchmarks/perf-runners/onnx-pr-bench/Cargo.toml +++ b/benchmarks/perf-runners/onnx-pr-bench/Cargo.toml @@ -16,6 +16,13 @@ yscv-kernels = { path = "../../../crates/yscv-kernels", default-features = false yscv-onnx = { path = "../../../crates/yscv-onnx", default-features = false } yscv-tensor = { path = "../../../crates/yscv-tensor" } +[dev-dependencies] +criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] } + +[[bench]] +name = "onnx_models" +harness = false + [profile.release] lto = "fat" codegen-units = 1 diff --git a/benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs b/benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs new file mode 100644 index 0000000..6890edc --- /dev/null +++ b/benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs @@ -0,0 +1,246 @@ +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main}; + +use serde_json::Value; +use yscv_onnx::{OnnxModel, OnnxRunner, load_onnx_model_from_file, optimize_onnx_graph}; +use yscv_tensor::Tensor; + +struct CaseSpec { + name: String, + model: String, + inputs: Vec<(String, Vec)>, + fill_random: bool, + image: Option, + image_input: Option, + image_size: usize, +} + +struct PreparedCase { + name: String, + model: OnnxModel, + inputs: Vec<(String, Tensor)>, +} + +struct XorShift(u32); + +impl XorShift { + fn new(seed: u32) -> Self { + Self(seed.max(1)) + } + + fn next_f32(&mut self) -> f32 { + self.0 ^= self.0 << 13; + self.0 ^= self.0 >> 17; + self.0 ^= self.0 << 5; + self.0 as f32 / u32::MAX as f32 + } +} + +fn asset_dir() -> PathBuf { + env::var_os("YSCV_ONNX_PR_BENCH_ASSET_DIR") + .map(PathBuf::from) + .unwrap_or_else(|| { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/criterion-assets") + }) +} + +fn run_command(command: &mut Command, description: &str) { + let status = command + .status() + .unwrap_or_else(|error| panic!("{description}: {error}")); + assert!(status.success(), "{description} exited with {status}"); +} + +fn prepare_assets(asset_dir: &Path) { + fs::create_dir_all(asset_dir).expect("create Criterion asset directory"); + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + run_command( + Command::new("bash") + .arg(manifest_dir.join("download-assets.sh")) + .arg(asset_dir), + "download Criterion benchmark assets", + ); +} + +fn required_str<'a>(value: &'a Value, field: &str, case: &str) -> &'a str { + value[field] + .as_str() + .unwrap_or_else(|| panic!("case '{case}' has no string '{field}'")) +} + +fn suite_cases() -> Vec { + let suite: Value = + serde_json::from_str(include_str!("../suite.json")).expect("parse suite.json"); + let model_assets: Vec<_> = suite["assets"] + .as_array() + .expect("suite.json assets array") + .iter() + .filter_map(|asset| asset["path"].as_str()) + .filter(|path| path.ends_with(".onnx")) + .collect(); + suite["cases"] + .as_array() + .expect("suite.json cases array") + .iter() + .filter(|case| { + let case_name = case["name"].as_str().unwrap_or("unknown"); + let model = required_str(case, "model", case_name); + model_assets.contains(&model) + }) + .map(|case| { + let name = required_str(case, "name", "unknown").to_string(); + let inputs = case["inputs"] + .as_array() + .unwrap_or_else(|| panic!("case '{name}' has no inputs")) + .iter() + .map(|input| { + let input_name = required_str(input, "name", &name).to_string(); + let shape = input["shape"] + .as_array() + .unwrap_or_else(|| { + panic!("case '{name}' input '{input_name}' has no shape") + }) + .iter() + .map(|dimension| { + dimension.as_u64().unwrap_or_else(|| { + panic!("case '{name}' input '{input_name}' has a non-integer shape") + }) as usize + }) + .collect(); + (input_name, shape) + }) + .collect(); + let has_random_input = case["inputs"] + .as_array() + .is_some_and(|inputs| inputs.iter().any(|input| input["source"] == "random")); + CaseSpec { + name: name.clone(), + model: required_str(case, "model", &name).to_string(), + inputs, + fill_random: case["fill"] == "random" || has_random_input, + image: case["image"].as_str().map(ToOwned::to_owned), + image_input: case["image_input"].as_str().map(ToOwned::to_owned), + image_size: case["image_size"].as_u64().unwrap_or(640) as usize, + } + }) + .collect() +} + +fn random_tensor(shape: &[usize], seed: u32) -> Tensor { + let mut rng = XorShift::new(seed); + let data = (0..shape.iter().product()) + .map(|_| rng.next_f32()) + .collect(); + Tensor::from_vec(shape.to_vec(), data).expect("build random benchmark input") +} + +fn image_tensor(path: &Path, target_size: usize) -> Tensor { + let image = image::ImageReader::open(path) + .expect("open benchmark image") + .decode() + .expect("decode benchmark image") + .to_rgb8(); + let (width, height) = image.dimensions(); + let rgb = image + .as_raw() + .iter() + .map(|&value| value as f32 / 255.0) + .collect(); + let hwc = Tensor::from_vec(vec![height as usize, width as usize, 3], rgb) + .expect("build benchmark image tensor"); + let (letterboxed, _, _, _) = yscv_detect::letterbox_preprocess(&hwc, target_size); + let src = letterboxed.data(); + let hw = target_size * target_size; + let mut nchw = vec![0.0; 3 * hw]; + for y in 0..target_size { + for x in 0..target_size { + let source = (y * target_size + x) * 3; + let destination = y * target_size + x; + nchw[destination] = src[source]; + nchw[hw + destination] = src[source + 1]; + nchw[2 * hw + destination] = src[source + 2]; + } + } + Tensor::from_vec(vec![1, 3, target_size, target_size], nchw) + .expect("build NCHW benchmark image tensor") +} + +fn prepare_case(spec: CaseSpec, asset_dir: &Path) -> PreparedCase { + let mut model = load_onnx_model_from_file(asset_dir.join(&spec.model)) + .unwrap_or_else(|error| panic!("load {}: {error}", spec.model)); + optimize_onnx_graph(&mut model); + let image_name = spec.image.as_ref().map(|_| { + spec.image_input.clone().unwrap_or_else(|| { + if spec.inputs.len() == 1 { + spec.inputs[0].0.clone() + } else { + "images".to_string() + } + }) + }); + let image = spec + .image + .as_ref() + .map(|path| image_tensor(&asset_dir.join(path), spec.image_size)); + let inputs = spec + .inputs + .iter() + .enumerate() + .map(|(index, (name, shape))| { + let tensor = if image_name.as_deref() == Some(name) { + let tensor = image.as_ref().expect("image input requires an image asset"); + assert_eq!( + tensor.shape(), + shape, + "image shape for case '{}'", + spec.name + ); + tensor.clone() + } else if spec.fill_random { + random_tensor(shape, 0xC0FFEE ^ index as u32) + } else { + Tensor::zeros(shape.clone()).expect("build zero benchmark input") + }; + (name.clone(), tensor) + }) + .collect(); + + PreparedCase { + name: spec.name, + model, + inputs, + } +} + +fn bench_onnx_models(criterion: &mut Criterion) { + let asset_dir = asset_dir(); + prepare_assets(&asset_dir); + let cases: Vec<_> = suite_cases() + .into_iter() + .map(|case| prepare_case(case, &asset_dir)) + .collect(); + let mut group = criterion.benchmark_group("onnx_models"); + + for case in &cases { + let runner = OnnxRunner::new(&case.model).expect("initialize ONNX runner"); + let feed: Vec<_> = case + .inputs + .iter() + .map(|(name, tensor)| (name.as_str(), tensor)) + .collect(); + runner.run(&feed).expect("warm up ONNX model"); + group.bench_function(BenchmarkId::from_parameter(&case.name), |bencher| { + bencher.iter(|| { + black_box(runner.run(black_box(&feed)).expect("run ONNX model")); + }); + }); + } + group.finish(); +} + +criterion_group!(benches, bench_onnx_models); +criterion_main!(benches); From b9f5ade9db3b369cf193938e2c8310dee7957c49 Mon Sep 17 00:00:00 2001 From: human9000 Date: Tue, 14 Jul 2026 19:00:21 +0300 Subject: [PATCH 2/2] ONNX BENCH REWORK !!!!111!! there were 2 onnx benches: * new one, uses criterion and various models * old one, used for onnx models profiling Those 2 guys had some shared logic, which is moved into `benchmarks/onnx-models/src/lib.rs` --- .github/workflows/pr-onnx-bench.yml | 22 +- .../onnx-pr-bench => onnx-models}/.gitignore | 0 benchmarks/onnx-models/Cargo.lock | 1933 +++++++++++++++++ .../onnx-pr-bench => onnx-models}/Cargo.toml | 18 +- benchmarks/onnx-models/benches/onnx_models.rs | 50 + .../onnx-pr-bench => onnx-models}/compare.py | 0 .../download-assets.sh | 0 .../onnx-models/examples}/bench_yolo.rs | 50 +- .../run-suite.sh | 2 +- benchmarks/onnx-models/src/lib.rs | 215 ++ .../onnx-pr-bench => onnx-models}/src/main.rs | 67 +- .../onnx-pr-bench => onnx-models}/suite.json | 0 .../perf-runners/onnx-pr-bench/Cargo.lock | 957 -------- .../onnx-pr-bench/benches/onnx_models.rs | 246 --- examples/Cargo.toml | 4 +- scripts/bench-all-competitors.sh | 2 +- 16 files changed, 2262 insertions(+), 1304 deletions(-) rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/.gitignore (100%) create mode 100644 benchmarks/onnx-models/Cargo.lock rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/Cargo.toml (53%) create mode 100644 benchmarks/onnx-models/benches/onnx_models.rs rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/compare.py (100%) rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/download-assets.sh (100%) rename {examples/src => benchmarks/onnx-models/examples}/bench_yolo.rs (92%) rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/run-suite.sh (95%) create mode 100644 benchmarks/onnx-models/src/lib.rs rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/src/main.rs (92%) rename benchmarks/{perf-runners/onnx-pr-bench => onnx-models}/suite.json (100%) delete mode 100644 benchmarks/perf-runners/onnx-pr-bench/Cargo.lock delete mode 100644 benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs diff --git a/.github/workflows/pr-onnx-bench.yml b/.github/workflows/pr-onnx-bench.yml index ab1d76e..f237d14 100644 --- a/.github/workflows/pr-onnx-bench.yml +++ b/.github/workflows/pr-onnx-bench.yml @@ -47,7 +47,7 @@ jobs: - name: Cache Cargo uses: Swatinem/rust-cache@v2 with: - workspaces: benchmarks/perf-runners/onnx-pr-bench -> target + workspaces: benchmarks/onnx-models -> target - name: Cache benchmark assets uses: actions/cache@v4 @@ -56,7 +56,7 @@ jobs: key: onnx-pr-bench-assets-v2 - name: Download benchmark assets - run: benchmarks/perf-runners/onnx-pr-bench/download-assets.sh "$ASSET_DIR" + run: benchmarks/onnx-models/download-assets.sh "$ASSET_DIR" - name: Resolve PR SHAs id: pr @@ -75,13 +75,21 @@ jobs: - name: Bench base run: | git checkout --detach "${{ steps.pr.outputs.base_sha }}" - benchmarks/perf-runners/onnx-pr-bench/run-suite.sh "$ASSET_DIR" "$OUT_DIR/base" + if git cat-file -e "${{ steps.pr.outputs.base_sha }}:benchmarks/onnx-models/Cargo.toml"; then + git checkout "${{ steps.pr.outputs.base_sha }}" -- benchmarks/onnx-models + else + git checkout pr-head -- benchmarks/onnx-models + fi + benchmarks/onnx-models/run-suite.sh "$ASSET_DIR" "$OUT_DIR/base" - name: Bench head run: | - git checkout --detach pr-head - git checkout "${{ steps.pr.outputs.base_sha }}" -- benchmarks/perf-runners/onnx-pr-bench - benchmarks/perf-runners/onnx-pr-bench/run-suite.sh "$ASSET_DIR" "$OUT_DIR/head" + git reset --hard + git checkout --detach --force pr-head + if git cat-file -e "${{ steps.pr.outputs.base_sha }}:benchmarks/onnx-models/Cargo.toml"; then + git checkout "${{ steps.pr.outputs.base_sha }}" -- benchmarks/onnx-models + fi + benchmarks/onnx-models/run-suite.sh "$ASSET_DIR" "$OUT_DIR/head" - name: Upload benchmark JSON if: always() @@ -117,7 +125,7 @@ jobs: - name: Build benchmark comment run: | - python3 benchmarks/perf-runners/onnx-pr-bench/compare.py \ + python3 benchmarks/onnx-models/compare.py \ --artifact-root "${{ runner.temp }}/onnx-pr-bench-artifacts" \ --output "${{ runner.temp }}/onnx-pr-bench-comment.md" diff --git a/benchmarks/perf-runners/onnx-pr-bench/.gitignore b/benchmarks/onnx-models/.gitignore similarity index 100% rename from benchmarks/perf-runners/onnx-pr-bench/.gitignore rename to benchmarks/onnx-models/.gitignore diff --git a/benchmarks/onnx-models/Cargo.lock b/benchmarks/onnx-models/Cargo.lock new file mode 100644 index 0000000..426923b --- /dev/null +++ b/benchmarks/onnx-models/Cargo.lock @@ -0,0 +1,1933 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bit-set" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cblas-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6feecd82cce51b0204cf063f0041d69f24ce83f680d87514b004248e7b0fa65" +dependencies = [ + "libc", +] + +[[package]] +name = "cc" +version = "1.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags", + "objc2", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "mimalloc" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "naga" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bf919621e7975acb27d881bae2fb993e0d45c8e0446e85e6272971e00dc8df" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror", + "unicode-ident", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck", + "itertools 0.14.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost", +] + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "spirv" +version = "0.4.0+sdk-1.4.341.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e8840e1ba2881d4cbb18d2147627a56af426ff064c0401eb0c8410c6325d07" +dependencies = [ + "arrayvec", + "bitflags", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f519832254e56965a9940c4af57dcb75f702b6f6fa4a0b172f685395843a4d7" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-naga-bridge", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e39e26c4c0e07589e67d18546cf79ff45383659fc72fca4dd293358a0347f3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e09be551dc939498bdd5f6b2c66e55ab275dad25825267a08605a80fc9f0af" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e592c1bbef6ad047647ae6e666ebd8cee7a32bb4544d9700ec96cbf73230257" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ace1c17727311c22a46e4e3faf56ea6de81af99dcc839bdfb54857b94d448d" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags", + "block2", + "bytemuck", + "cfg-if", + "cfg_aliases", + "glow", + "glutin_wgl_sys", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "naga", + "ndk-sys", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "raw-window-metal", + "renderdoc-sys", + "smallvec", + "thiserror", + "wasm-bindgen", + "wayland-sys", + "web-sys", + "wgpu-naga-bridge", + "wgpu-types", + "windows", + "windows-core", + "windows-result", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95226013f547544b223281cd16a4fb549aa9dcb562adbda0faae4c73ffbbc161" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84bf84cd9ca8ca45e2b223a3868f1adf9bfc0c66aeac212e76ee7e40fdadf8f5" +dependencies = [ + "bitflags", + "bytemuck", + "js-sys", + "log", + "raw-window-handle", + "web-sys", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "yscv-cpu" +version = "0.1.10" + +[[package]] +name = "yscv-detect" +version = "0.1.10" +dependencies = [ + "rustc-hash 2.1.3", + "thiserror", + "yscv-tensor", + "yscv-video", +] + +[[package]] +name = "yscv-kernels" +version = "0.1.10" +dependencies = [ + "bytemuck", + "cblas-sys", + "cc", + "pollster", + "rayon", + "rustc-hash 2.1.3", + "thiserror", + "wgpu", + "yscv-cpu", + "yscv-tensor", + "yscv-threadpool", +] + +[[package]] +name = "yscv-onnx" +version = "0.1.10" +dependencies = [ + "prost", + "prost-build", + "rayon", + "rustc-hash 2.1.3", + "thiserror", + "yscv-cpu", + "yscv-kernels", + "yscv-tensor", + "yscv-threadpool", +] + +[[package]] +name = "yscv-onnx-model-bench" +version = "0.1.0" +dependencies = [ + "criterion", + "image", + "mimalloc", + "rustc-hash 2.1.3", + "serde_json", + "yscv-detect", + "yscv-kernels", + "yscv-onnx", + "yscv-tensor", +] + +[[package]] +name = "yscv-tensor" +version = "0.1.10" +dependencies = [ + "rayon", + "thiserror", + "yscv-cpu", +] + +[[package]] +name = "yscv-threadpool" +version = "0.1.10" +dependencies = [ + "crossbeam-deque", + "libc", + "rayon", +] + +[[package]] +name = "yscv-video" +version = "0.1.10" +dependencies = [ + "arc-swap", + "bytes", + "rayon", + "rustc-hash 2.1.3", + "thiserror", + "yscv-cpu", + "yscv-tensor", +] + +[[package]] +name = "zerocopy" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/benchmarks/perf-runners/onnx-pr-bench/Cargo.toml b/benchmarks/onnx-models/Cargo.toml similarity index 53% rename from benchmarks/perf-runners/onnx-pr-bench/Cargo.toml rename to benchmarks/onnx-models/Cargo.toml index d9736bc..b4648f5 100644 --- a/benchmarks/perf-runners/onnx-pr-bench/Cargo.toml +++ b/benchmarks/onnx-models/Cargo.toml @@ -1,20 +1,24 @@ [package] -name = "yscv-onnx-pr-bench" +name = "yscv-onnx-model-bench" version = "0.1.0" edition = "2024" publish = false [workspace] +[features] +default = [] +gpu = ["yscv-kernels/gpu", "yscv-onnx/gpu"] + [dependencies] image = { version = "0.25", default-features = false, features = ["jpeg", "png"] } mimalloc = { version = "0.1", default-features = false } rustc-hash = "2.1.3" serde_json = "1" -yscv-detect = { path = "../../../crates/yscv-detect" } -yscv-kernels = { path = "../../../crates/yscv-kernels", default-features = false } -yscv-onnx = { path = "../../../crates/yscv-onnx", default-features = false } -yscv-tensor = { path = "../../../crates/yscv-tensor" } +yscv-detect = { path = "../../crates/yscv-detect" } +yscv-kernels = { path = "../../crates/yscv-kernels", default-features = false } +yscv-onnx = { path = "../../crates/yscv-onnx", default-features = false } +yscv-tensor = { path = "../../crates/yscv-tensor" } [dev-dependencies] criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] } @@ -23,6 +27,10 @@ criterion = { version = "0.5", default-features = false, features = ["cargo_benc name = "onnx_models" harness = false +[[example]] +name = "bench_yolo" +path = "examples/bench_yolo.rs" + [profile.release] lto = "fat" codegen-units = 1 diff --git a/benchmarks/onnx-models/benches/onnx_models.rs b/benchmarks/onnx-models/benches/onnx_models.rs new file mode 100644 index 0000000..6547732 --- /dev/null +++ b/benchmarks/onnx-models/benches/onnx_models.rs @@ -0,0 +1,50 @@ +use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main}; +use yscv_onnx::{OnnxModel, OnnxRunner, load_onnx_model_from_file, optimize_onnx_graph}; +use yscv_onnx_model_bench::{asset_dir, download_assets, make_inputs, model_cases}; +use yscv_tensor::Tensor; + +struct PreparedCase { + name: String, + model: OnnxModel, + inputs: Vec<(String, Tensor)>, +} + +fn bench_onnx_models(criterion: &mut Criterion) { + let asset_dir = asset_dir(); + download_assets(&asset_dir).expect("download model benchmark assets"); + let cases: Vec<_> = model_cases() + .expect("load model benchmark cases") + .into_iter() + .map(|case| { + let mut model = load_onnx_model_from_file(asset_dir.join(&case.model)) + .unwrap_or_else(|error| panic!("load {}: {error}", case.model)); + optimize_onnx_graph(&mut model); + let inputs = make_inputs(&case, &asset_dir).expect("build model benchmark inputs"); + PreparedCase { + name: case.name, + model, + inputs, + } + }) + .collect(); + let mut group = criterion.benchmark_group("onnx_models"); + + for case in &cases { + let runner = OnnxRunner::new(&case.model).expect("initialize ONNX runner"); + let feed: Vec<_> = case + .inputs + .iter() + .map(|(name, tensor)| (name.as_str(), tensor)) + .collect(); + runner.run(&feed).expect("warm up ONNX model"); + group.bench_function(BenchmarkId::from_parameter(&case.name), |bencher| { + bencher.iter(|| { + black_box(runner.run(black_box(&feed)).expect("run ONNX model")); + }); + }); + } + group.finish(); +} + +criterion_group!(benches, bench_onnx_models); +criterion_main!(benches); diff --git a/benchmarks/perf-runners/onnx-pr-bench/compare.py b/benchmarks/onnx-models/compare.py similarity index 100% rename from benchmarks/perf-runners/onnx-pr-bench/compare.py rename to benchmarks/onnx-models/compare.py diff --git a/benchmarks/perf-runners/onnx-pr-bench/download-assets.sh b/benchmarks/onnx-models/download-assets.sh similarity index 100% rename from benchmarks/perf-runners/onnx-pr-bench/download-assets.sh rename to benchmarks/onnx-models/download-assets.sh diff --git a/examples/src/bench_yolo.rs b/benchmarks/onnx-models/examples/bench_yolo.rs similarity index 92% rename from examples/src/bench_yolo.rs rename to benchmarks/onnx-models/examples/bench_yolo.rs index 158b4b5..366ac2e 100644 --- a/examples/src/bench_yolo.rs +++ b/benchmarks/onnx-models/examples/bench_yolo.rs @@ -1,17 +1,18 @@ //! Quick benchmark: measure YOLO ONNX inference time (CPU vs GPU). //! -//! Set BENCH_COOLDOWN= to insert a cooldown pause between benchmarks -//! (default: 20s). This prevents CPU thermal throttling from skewing results. +//! Set BENCH_COOLDOWN= to insert a cooldown pause between benchmarks. +//! The default is 0; callers that need thermal control must opt in. use rustc_hash::FxHashMap; use yscv_onnx::load_onnx_model_from_file; +use yscv_onnx_model_bench::{asset_dir, download_assets, make_inputs, model_cases}; use yscv_tensor::Tensor; fn cooldown(label: &str) { let secs: u64 = std::env::var("BENCH_COOLDOWN") .ok() .and_then(|v| v.parse().ok()) - .unwrap_or(20); + .unwrap_or(0); if secs > 0 { println!("\n --- cooldown {secs}s before {label} ---"); std::thread::sleep(std::time::Duration::from_secs(secs)); @@ -19,21 +20,29 @@ fn cooldown(label: &str) { } fn main() { - let models = [ - "examples/src/slowwork/yolov8n.onnx", - "examples/src/slowwork/yolo11n.onnx", - ]; + let asset_dir = asset_dir(); + download_assets(&asset_dir).expect("download benchmark assets"); + let cases: Vec<_> = model_cases() + .expect("load benchmark cases") + .into_iter() + .filter(|case| case.name.starts_with("yolo")) + .collect(); - let input_data = vec![0.5f32; 3 * 640 * 640]; - let input_tensor = Tensor::from_vec(vec![1, 3, 640, 640], input_data).unwrap(); - - for (model_idx, model_path) in models.iter().enumerate() { + for (model_idx, case) in cases.iter().enumerate() { if model_idx > 0 { cooldown("next model"); } - println!("\n{} {} {}", "=".repeat(20), model_path, "=".repeat(20)); + let model_path = asset_dir.join(&case.model); + let inputs = make_inputs(case, &asset_dir).expect("build model inputs"); + let (input_name, input_tensor) = inputs.first().expect("YOLO benchmark input"); + println!( + "\n{} {} {}", + "=".repeat(20), + model_path.display(), + "=".repeat(20) + ); - let model = match load_onnx_model_from_file(model_path) { + let model = match load_onnx_model_from_file(&model_path) { Ok(m) => m, Err(e) => { eprintln!(" Failed to load: {e}"); @@ -47,17 +56,17 @@ fn main() { #[allow(unused_variables)] let cpu_out = { let mut inp = FxHashMap::default(); - inp.insert("images".to_string(), input_tensor.clone()); + inp.insert(input_name.clone(), input_tensor.clone()); yscv_onnx::run_onnx_model(&model, inp).expect("cpu fail") }; - bench_run(&model, &input_tensor, |m, inp| { + bench_run(&model, input_name, input_tensor, |m, inp| { yscv_onnx::run_onnx_model(m, inp) }); { println!("\n [CPU Profile]"); let mut inp = FxHashMap::default(); - inp.insert("images".to_string(), input_tensor.clone()); + inp.insert(input_name.clone(), input_tensor.clone()); let _ = yscv_onnx::profile_onnx_model_cpu(&model, inp); } @@ -66,7 +75,7 @@ fn main() { { cooldown("GPU profile"); let mut inp = FxHashMap::default(); - inp.insert("images".to_string(), input_tensor.clone()); + inp.insert(input_name.clone(), input_tensor.clone()); let _ = yscv_onnx::profile_onnx_model_gpu(&model, inp); } @@ -82,7 +91,7 @@ fn main() { // Warmup (populates weight cache) let mut inputs = FxHashMap::default(); - inputs.insert("images".to_string(), input_tensor.clone()); + inputs.insert(input_name.clone(), input_tensor.clone()); let _ = yscv_onnx::run_onnx_model_gpu_cached(&gpu, &model, inputs, &mut wc, Some(&plan)); let dispatches = gpu.take_dispatch_count(); @@ -398,6 +407,7 @@ fn main() { fn bench_run( model: &yscv_onnx::OnnxModel, + input_name: &str, input_tensor: &Tensor, run_fn: impl Fn( &yscv_onnx::OnnxModel, @@ -406,14 +416,14 @@ fn bench_run( ) { // Warmup let mut inputs = FxHashMap::default(); - inputs.insert("images".to_string(), input_tensor.clone()); + inputs.insert(input_name.to_string(), input_tensor.clone()); let _ = run_fn(model, inputs); let n = 5; let mut times = Vec::new(); for i in 0..n { let mut inputs = FxHashMap::default(); - inputs.insert("images".to_string(), input_tensor.clone()); + inputs.insert(input_name.to_string(), input_tensor.clone()); let start = std::time::Instant::now(); let result = run_fn(model, inputs); let elapsed = start.elapsed(); diff --git a/benchmarks/perf-runners/onnx-pr-bench/run-suite.sh b/benchmarks/onnx-models/run-suite.sh similarity index 95% rename from benchmarks/perf-runners/onnx-pr-bench/run-suite.sh rename to benchmarks/onnx-models/run-suite.sh index 0ad21f9..1560783 100755 --- a/benchmarks/perf-runners/onnx-pr-bench/run-suite.sh +++ b/benchmarks/onnx-models/run-suite.sh @@ -22,7 +22,7 @@ out_dir = Path(sys.argv[4]) suite = json.loads(suite_path.read_text()) manifest = runner_dir / "Cargo.toml" -base_cmd = ["cargo", "run", "--release", "--manifest-path", str(manifest), "--"] +base_cmd = ["cargo", "run", "--locked", "--release", "--manifest-path", str(manifest), "--"] subprocess.run( base_cmd + ["prepare-small", "--asset-dir", str(asset_dir)], diff --git a/benchmarks/onnx-models/src/lib.rs b/benchmarks/onnx-models/src/lib.rs new file mode 100644 index 0000000..aa58667 --- /dev/null +++ b/benchmarks/onnx-models/src/lib.rs @@ -0,0 +1,215 @@ +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use serde_json::Value; +use yscv_tensor::Tensor; + +#[derive(Clone, Copy)] +pub enum FillMode { + Zero, + Random, +} + +pub struct ModelCase { + pub name: String, + pub model: String, + pub inputs: Vec<(String, Vec)>, + pub fill: FillMode, + pub image: Option, + pub image_input: Option, + pub image_size: usize, +} + +struct XorShift(u32); + +impl XorShift { + fn new(seed: u32) -> Self { + Self(seed.max(1)) + } + + fn next_f32(&mut self) -> f32 { + let mut x = self.0; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + self.0 = x; + x as f32 / u32::MAX as f32 + } +} + +pub fn asset_dir() -> PathBuf { + env::var_os("YSCV_ONNX_MODEL_BENCH_ASSET_DIR") + .map(PathBuf::from) + .unwrap_or_else(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/assets")) +} + +pub fn download_assets(asset_dir: &Path) -> Result<(), String> { + fs::create_dir_all(asset_dir).map_err(|error| format!("create asset directory: {error}"))?; + let status = Command::new("bash") + .arg(Path::new(env!("CARGO_MANIFEST_DIR")).join("download-assets.sh")) + .arg(asset_dir) + .status() + .map_err(|error| format!("start asset download: {error}"))?; + if status.success() { + Ok(()) + } else { + Err(format!("asset download exited with {status}")) + } +} + +fn required_str<'a>(value: &'a Value, field: &str, case: &str) -> Result<&'a str, String> { + value[field] + .as_str() + .ok_or_else(|| format!("case '{case}' has no string '{field}'")) +} + +pub fn model_cases() -> Result, String> { + let suite: Value = serde_json::from_str(include_str!("../suite.json")) + .map_err(|error| format!("parse suite.json: {error}"))?; + let assets = suite["assets"] + .as_array() + .ok_or("suite.json has no assets array")?; + let model_assets: Vec<_> = assets + .iter() + .filter_map(|asset| asset["path"].as_str()) + .filter(|path| path.ends_with(".onnx")) + .collect(); + suite["cases"] + .as_array() + .ok_or("suite.json has no cases array")? + .iter() + .filter(|case| { + let case_name = case["name"].as_str().unwrap_or("unknown"); + required_str(case, "model", case_name).is_ok_and(|model| model_assets.contains(&model)) + }) + .map(|case| { + let name = required_str(case, "name", "unknown")?.to_string(); + let inputs = case["inputs"] + .as_array() + .ok_or_else(|| format!("case '{name}' has no inputs"))? + .iter() + .map(|input| { + let input_name = required_str(input, "name", &name)?.to_string(); + let shape = input["shape"] + .as_array() + .ok_or_else(|| format!("case '{name}' input '{input_name}' has no shape"))? + .iter() + .map(|dimension| { + dimension + .as_u64() + .map(|dimension| dimension as usize) + .ok_or_else(|| { + format!( + "case '{name}' input '{input_name}' has a non-integer shape" + ) + }) + }) + .collect::, _>>()?; + Ok((input_name, shape)) + }) + .collect::, String>>()?; + let has_random_input = case["inputs"] + .as_array() + .is_some_and(|inputs| inputs.iter().any(|input| input["source"] == "random")); + Ok(ModelCase { + model: required_str(case, "model", &name)?.to_string(), + inputs, + fill: if case["fill"] == "random" || has_random_input { + FillMode::Random + } else { + FillMode::Zero + }, + image: case["image"].as_str().map(ToOwned::to_owned), + image_input: case["image_input"].as_str().map(ToOwned::to_owned), + image_size: case["image_size"].as_u64().unwrap_or(640) as usize, + name, + }) + }) + .collect() +} + +pub fn make_tensor(shape: &[usize], fill: FillMode, seed: u32) -> Result { + let len = shape.iter().product(); + let data = match fill { + FillMode::Zero => vec![0.0; len], + FillMode::Random => { + let mut rng = XorShift::new(seed); + (0..len).map(|_| rng.next_f32()).collect() + } + }; + Tensor::from_vec(shape.to_vec(), data) + .map_err(|error| format!("input tensor build failed: {error}")) +} + +pub fn load_image_tensor(path: &Path, target_size: usize) -> Result { + let image = image::ImageReader::open(path) + .map_err(|error| format!("open image {}: {error}", path.display()))? + .decode() + .map_err(|error| format!("decode image {}: {error}", path.display()))? + .to_rgb8(); + let (width, height) = image.dimensions(); + let rgb = image + .as_raw() + .iter() + .map(|&value| value as f32 / 255.0) + .collect(); + let hwc = Tensor::from_vec(vec![height as usize, width as usize, 3], rgb) + .map_err(|error| format!("image tensor build failed: {error}"))?; + let (letterboxed, _, _, _) = yscv_detect::letterbox_preprocess(&hwc, target_size); + let src = letterboxed.data(); + let hw = target_size * target_size; + let mut nchw = vec![0.0; 3 * hw]; + for y in 0..target_size { + for x in 0..target_size { + let source = (y * target_size + x) * 3; + let destination = y * target_size + x; + nchw[destination] = src[source]; + nchw[hw + destination] = src[source + 1]; + nchw[2 * hw + destination] = src[source + 2]; + } + } + Tensor::from_vec(vec![1, 3, target_size, target_size], nchw) + .map_err(|error| format!("image NCHW tensor build failed: {error}")) +} + +pub fn make_inputs(case: &ModelCase, asset_dir: &Path) -> Result, String> { + let image_name = case.image.as_ref().map(|_| { + case.image_input.clone().unwrap_or_else(|| { + if case.inputs.len() == 1 { + case.inputs[0].0.clone() + } else { + "images".to_string() + } + }) + }); + let image = case + .image + .as_ref() + .map(|path| load_image_tensor(&asset_dir.join(path), case.image_size)) + .transpose()?; + case.inputs + .iter() + .enumerate() + .map(|(index, (name, shape))| { + if image_name.as_deref() == Some(name) { + let tensor = image + .as_ref() + .ok_or("image input requires an image asset")?; + if tensor.shape() != shape { + return Err(format!( + "image shape for case '{}' does not match input", + case.name + )); + } + Ok((name.clone(), tensor.clone())) + } else { + Ok(( + name.clone(), + make_tensor(shape, case.fill, 0xC0FFEE ^ index as u32)?, + )) + } + }) + .collect() +} diff --git a/benchmarks/perf-runners/onnx-pr-bench/src/main.rs b/benchmarks/onnx-models/src/main.rs similarity index 92% rename from benchmarks/perf-runners/onnx-pr-bench/src/main.rs rename to benchmarks/onnx-models/src/main.rs index af40395..e94558f 100644 --- a/benchmarks/perf-runners/onnx-pr-bench/src/main.rs +++ b/benchmarks/onnx-models/src/main.rs @@ -8,20 +8,15 @@ use std::time::Instant; use serde_json::json; use yscv_onnx::{ + OnnxExportAttr, OnnxExportGraph, OnnxExportNode, OnnxExportValueInfo, OnnxRunner, export_onnx_model_to_file, graph_cost, graph_cost_report, infer_shapes_from_tensors, - load_onnx_model_from_file, optimize_onnx_graph, OnnxExportAttr, OnnxExportGraph, - OnnxExportNode, OnnxExportValueInfo, OnnxRunner, + load_onnx_model_from_file, optimize_onnx_graph, }; +use yscv_onnx_model_bench::{FillMode, load_image_tensor, make_tensor}; use yscv_tensor::Tensor; use rustc_hash::FxHashMap; -#[derive(Clone, Copy)] -enum FillMode { - Zero, - Random, -} - enum Command { PrepareSmall { asset_dir: PathBuf, @@ -484,62 +479,6 @@ fn prepare_small(asset_dir: &Path) -> Result<(), String> { .map_err(|e| format!("export medium gemm: {e}")) } -struct XorShift(u32); - -impl XorShift { - fn new(seed: u32) -> Self { - Self(seed.max(1)) - } - - fn next_f32(&mut self) -> f32 { - let mut x = self.0; - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - self.0 = x; - x as f32 / u32::MAX as f32 - } -} - -fn make_tensor(shape: &[usize], fill: FillMode, seed: u32) -> Result { - let len = shape.iter().product(); - let data = match fill { - FillMode::Zero => vec![0.0; len], - FillMode::Random => { - let mut rng = XorShift::new(seed); - (0..len).map(|_| rng.next_f32()).collect() - } - }; - Tensor::from_vec(shape.to_vec(), data).map_err(|e| format!("input tensor build failed: {e}")) -} - -fn load_image_tensor(path: &Path, target_size: usize) -> Result { - let img = image::ImageReader::open(path) - .map_err(|e| format!("open image {}: {e}", path.display()))? - .decode() - .map_err(|e| format!("decode image {}: {e}", path.display()))? - .to_rgb8(); - let (width, height) = img.dimensions(); - let rgb: Vec = img.as_raw().iter().map(|&v| v as f32 / 255.0).collect(); - let hwc = Tensor::from_vec(vec![height as usize, width as usize, 3], rgb) - .map_err(|e| format!("image tensor build failed: {e}"))?; - let (letterboxed, _, _, _) = yscv_detect::letterbox_preprocess(&hwc, target_size); - let src = letterboxed.data(); - let hw = target_size * target_size; - let mut nchw = vec![0.0; 3 * hw]; - for y in 0..target_size { - for x in 0..target_size { - let s = (y * target_size + x) * 3; - let d = y * target_size + x; - nchw[d] = src[s]; - nchw[hw + d] = src[s + 1]; - nchw[2 * hw + d] = src[s + 2]; - } - } - Tensor::from_vec(vec![1, 3, target_size, target_size], nchw) - .map_err(|e| format!("image NCHW tensor build failed: {e}")) -} - fn percentile(sorted: &[u64], p: f64) -> u64 { let idx = ((sorted.len() - 1) as f64 * p).round() as usize; sorted[idx.min(sorted.len() - 1)] diff --git a/benchmarks/perf-runners/onnx-pr-bench/suite.json b/benchmarks/onnx-models/suite.json similarity index 100% rename from benchmarks/perf-runners/onnx-pr-bench/suite.json rename to benchmarks/onnx-models/suite.json diff --git a/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock b/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock deleted file mode 100644 index 8a77ab3..0000000 --- a/benchmarks/perf-runners/onnx-pr-bench/Cargo.lock +++ /dev/null @@ -1,957 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstyle" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" - -[[package]] -name = "anyhow" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" - -[[package]] -name = "arc-swap" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" -dependencies = [ - "rustversion", -] - -[[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - -[[package]] -name = "bitflags" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" - -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - -[[package]] -name = "bytes" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cblas-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6feecd82cce51b0204cf063f0041d69f24ce83f680d87514b004248e7b0fa65" -dependencies = [ - "libc", -] - -[[package]] -name = "cc" -version = "1.2.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clap" -version = "4.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "either" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fastrand" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "getrandom" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" -dependencies = [ - "cfg-if", - "libc", - "r-efi", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "is-terminal" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libmimalloc-sys" -version = "0.1.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" -dependencies = [ - "cc", -] - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "log" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" - -[[package]] -name = "memchr" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" - -[[package]] -name = "mimalloc" -version = "0.1.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" -dependencies = [ - "libmimalloc-sys", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "multimap" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "petgraph" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" -dependencies = [ - "heck", - "itertools 0.14.0", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn", - "tempfile", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-types" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" -dependencies = [ - "prost", -] - -[[package]] -name = "pxfm" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" - -[[package]] -name = "quote" -version = "1.0.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "regex" -version = "1.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" - -[[package]] -name = "rustc-hash" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "shlex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" - -[[package]] -name = "simd-adler32" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" - -[[package]] -name = "syn" -version = "2.0.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom", - "once_cell", - "rustix", - "windows-sys", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "yscv-cpu" -version = "0.1.10" - -[[package]] -name = "yscv-detect" -version = "0.1.10" -dependencies = [ - "rustc-hash", - "thiserror", - "yscv-tensor", - "yscv-video", -] - -[[package]] -name = "yscv-kernels" -version = "0.1.10" -dependencies = [ - "cblas-sys", - "cc", - "rayon", - "rustc-hash", - "thiserror", - "yscv-cpu", - "yscv-tensor", - "yscv-threadpool", -] - -[[package]] -name = "yscv-onnx" -version = "0.1.10" -dependencies = [ - "prost", - "prost-build", - "rayon", - "rustc-hash", - "thiserror", - "yscv-cpu", - "yscv-kernels", - "yscv-tensor", - "yscv-threadpool", -] - -[[package]] -name = "yscv-onnx-pr-bench" -version = "0.1.0" -dependencies = [ - "criterion", - "image", - "mimalloc", - "rustc-hash", - "serde_json", - "yscv-detect", - "yscv-kernels", - "yscv-onnx", - "yscv-tensor", -] - -[[package]] -name = "yscv-tensor" -version = "0.1.10" -dependencies = [ - "rayon", - "thiserror", - "yscv-cpu", -] - -[[package]] -name = "yscv-threadpool" -version = "0.1.10" -dependencies = [ - "crossbeam-deque", - "libc", - "rayon", -] - -[[package]] -name = "yscv-video" -version = "0.1.10" -dependencies = [ - "arc-swap", - "bytes", - "rayon", - "rustc-hash", - "thiserror", - "yscv-cpu", - "yscv-tensor", -] - -[[package]] -name = "zerocopy" -version = "0.8.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zune-core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" - -[[package]] -name = "zune-jpeg" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" -dependencies = [ - "zune-core", -] diff --git a/benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs b/benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs deleted file mode 100644 index 6890edc..0000000 --- a/benchmarks/perf-runners/onnx-pr-bench/benches/onnx_models.rs +++ /dev/null @@ -1,246 +0,0 @@ -use std::env; -use std::fs; -use std::path::{Path, PathBuf}; -use std::process::Command; - -use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main}; - -use serde_json::Value; -use yscv_onnx::{OnnxModel, OnnxRunner, load_onnx_model_from_file, optimize_onnx_graph}; -use yscv_tensor::Tensor; - -struct CaseSpec { - name: String, - model: String, - inputs: Vec<(String, Vec)>, - fill_random: bool, - image: Option, - image_input: Option, - image_size: usize, -} - -struct PreparedCase { - name: String, - model: OnnxModel, - inputs: Vec<(String, Tensor)>, -} - -struct XorShift(u32); - -impl XorShift { - fn new(seed: u32) -> Self { - Self(seed.max(1)) - } - - fn next_f32(&mut self) -> f32 { - self.0 ^= self.0 << 13; - self.0 ^= self.0 >> 17; - self.0 ^= self.0 << 5; - self.0 as f32 / u32::MAX as f32 - } -} - -fn asset_dir() -> PathBuf { - env::var_os("YSCV_ONNX_PR_BENCH_ASSET_DIR") - .map(PathBuf::from) - .unwrap_or_else(|| { - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/criterion-assets") - }) -} - -fn run_command(command: &mut Command, description: &str) { - let status = command - .status() - .unwrap_or_else(|error| panic!("{description}: {error}")); - assert!(status.success(), "{description} exited with {status}"); -} - -fn prepare_assets(asset_dir: &Path) { - fs::create_dir_all(asset_dir).expect("create Criterion asset directory"); - let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - run_command( - Command::new("bash") - .arg(manifest_dir.join("download-assets.sh")) - .arg(asset_dir), - "download Criterion benchmark assets", - ); -} - -fn required_str<'a>(value: &'a Value, field: &str, case: &str) -> &'a str { - value[field] - .as_str() - .unwrap_or_else(|| panic!("case '{case}' has no string '{field}'")) -} - -fn suite_cases() -> Vec { - let suite: Value = - serde_json::from_str(include_str!("../suite.json")).expect("parse suite.json"); - let model_assets: Vec<_> = suite["assets"] - .as_array() - .expect("suite.json assets array") - .iter() - .filter_map(|asset| asset["path"].as_str()) - .filter(|path| path.ends_with(".onnx")) - .collect(); - suite["cases"] - .as_array() - .expect("suite.json cases array") - .iter() - .filter(|case| { - let case_name = case["name"].as_str().unwrap_or("unknown"); - let model = required_str(case, "model", case_name); - model_assets.contains(&model) - }) - .map(|case| { - let name = required_str(case, "name", "unknown").to_string(); - let inputs = case["inputs"] - .as_array() - .unwrap_or_else(|| panic!("case '{name}' has no inputs")) - .iter() - .map(|input| { - let input_name = required_str(input, "name", &name).to_string(); - let shape = input["shape"] - .as_array() - .unwrap_or_else(|| { - panic!("case '{name}' input '{input_name}' has no shape") - }) - .iter() - .map(|dimension| { - dimension.as_u64().unwrap_or_else(|| { - panic!("case '{name}' input '{input_name}' has a non-integer shape") - }) as usize - }) - .collect(); - (input_name, shape) - }) - .collect(); - let has_random_input = case["inputs"] - .as_array() - .is_some_and(|inputs| inputs.iter().any(|input| input["source"] == "random")); - CaseSpec { - name: name.clone(), - model: required_str(case, "model", &name).to_string(), - inputs, - fill_random: case["fill"] == "random" || has_random_input, - image: case["image"].as_str().map(ToOwned::to_owned), - image_input: case["image_input"].as_str().map(ToOwned::to_owned), - image_size: case["image_size"].as_u64().unwrap_or(640) as usize, - } - }) - .collect() -} - -fn random_tensor(shape: &[usize], seed: u32) -> Tensor { - let mut rng = XorShift::new(seed); - let data = (0..shape.iter().product()) - .map(|_| rng.next_f32()) - .collect(); - Tensor::from_vec(shape.to_vec(), data).expect("build random benchmark input") -} - -fn image_tensor(path: &Path, target_size: usize) -> Tensor { - let image = image::ImageReader::open(path) - .expect("open benchmark image") - .decode() - .expect("decode benchmark image") - .to_rgb8(); - let (width, height) = image.dimensions(); - let rgb = image - .as_raw() - .iter() - .map(|&value| value as f32 / 255.0) - .collect(); - let hwc = Tensor::from_vec(vec![height as usize, width as usize, 3], rgb) - .expect("build benchmark image tensor"); - let (letterboxed, _, _, _) = yscv_detect::letterbox_preprocess(&hwc, target_size); - let src = letterboxed.data(); - let hw = target_size * target_size; - let mut nchw = vec![0.0; 3 * hw]; - for y in 0..target_size { - for x in 0..target_size { - let source = (y * target_size + x) * 3; - let destination = y * target_size + x; - nchw[destination] = src[source]; - nchw[hw + destination] = src[source + 1]; - nchw[2 * hw + destination] = src[source + 2]; - } - } - Tensor::from_vec(vec![1, 3, target_size, target_size], nchw) - .expect("build NCHW benchmark image tensor") -} - -fn prepare_case(spec: CaseSpec, asset_dir: &Path) -> PreparedCase { - let mut model = load_onnx_model_from_file(asset_dir.join(&spec.model)) - .unwrap_or_else(|error| panic!("load {}: {error}", spec.model)); - optimize_onnx_graph(&mut model); - let image_name = spec.image.as_ref().map(|_| { - spec.image_input.clone().unwrap_or_else(|| { - if spec.inputs.len() == 1 { - spec.inputs[0].0.clone() - } else { - "images".to_string() - } - }) - }); - let image = spec - .image - .as_ref() - .map(|path| image_tensor(&asset_dir.join(path), spec.image_size)); - let inputs = spec - .inputs - .iter() - .enumerate() - .map(|(index, (name, shape))| { - let tensor = if image_name.as_deref() == Some(name) { - let tensor = image.as_ref().expect("image input requires an image asset"); - assert_eq!( - tensor.shape(), - shape, - "image shape for case '{}'", - spec.name - ); - tensor.clone() - } else if spec.fill_random { - random_tensor(shape, 0xC0FFEE ^ index as u32) - } else { - Tensor::zeros(shape.clone()).expect("build zero benchmark input") - }; - (name.clone(), tensor) - }) - .collect(); - - PreparedCase { - name: spec.name, - model, - inputs, - } -} - -fn bench_onnx_models(criterion: &mut Criterion) { - let asset_dir = asset_dir(); - prepare_assets(&asset_dir); - let cases: Vec<_> = suite_cases() - .into_iter() - .map(|case| prepare_case(case, &asset_dir)) - .collect(); - let mut group = criterion.benchmark_group("onnx_models"); - - for case in &cases { - let runner = OnnxRunner::new(&case.model).expect("initialize ONNX runner"); - let feed: Vec<_> = case - .inputs - .iter() - .map(|(name, tensor)| (name.as_str(), tensor)) - .collect(); - runner.run(&feed).expect("warm up ONNX model"); - group.bench_function(BenchmarkId::from_parameter(&case.name), |bencher| { - bencher.iter(|| { - black_box(runner.run(black_box(&feed)).expect("run ONNX model")); - }); - }); - } - group.finish(); -} - -criterion_group!(benches, bench_onnx_models); -criterion_main!(benches); diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 7a6ee6e..53732a9 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -59,9 +59,7 @@ path = "src/yolo_detect.rs" name = "yolo_finetune" path = "src/yolo_finetune.rs" -[[example]] -name = "bench_yolo" -path = "src/bench_yolo.rs" + [[example]] name = "bench_gpu" diff --git a/scripts/bench-all-competitors.sh b/scripts/bench-all-competitors.sh index 4229de4..7d87247 100755 --- a/scripts/bench-all-competitors.sh +++ b/scripts/bench-all-competitors.sh @@ -13,7 +13,7 @@ echo "" # ── 1. yscv CPU ── echo "▸ yscv CPU..." -(cd "$REPO_ROOT" && cargo run --release --example bench_yolo 2>/dev/null) \ +(cd "$REPO_ROOT" && BENCH_COOLDOWN=20 cargo run --release --manifest-path benchmarks/onnx-models/Cargo.toml --example bench_yolo 2>/dev/null) \ | tee "$OUT_DIR/yscv-cpu.txt" echo ""