Download src/bench/compare.py from Aryan006/cone-distance: direct link, hf CLI and curl.
- Browser
- Download file 3.1 kB
-
https://huggingface.co/Aryan006/cone-distance/resolve/main/src/bench/compare.py
- Command line
-
hf download hf://Aryan006/cone-distance/src/bench/compare.py
-
curl -L -o compare.py https://huggingface.co/Aryan006/cone-distance/resolve/main/src/bench/compare.py
3.1 kB
| """Read the saved timing files and print the three formats side by side. | |
| Each runner writes `bench/<tag>_timing.json`. This reads whatever is there, so | |
| it works with two of three present -- which is the normal case while NCNN is | |
| waiting on a Pi. | |
| python -m src.bench.eval_pt && python -m src.bench.eval_onnx | |
| python -m src.bench.compare | |
| The row worth checking first is `depth`. It is the same numpy over the same | |
| boxes whatever the backend, so it should be near-identical across columns. When | |
| it is not, the run measured contention rather than the export format -- that is | |
| exactly what happened here before onnxruntime's thread pool was pinned, where it | |
| read 1.5 ms under PyTorch and 16.2 ms under ONNX. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| from pathlib import Path | |
| STAGES = ("read", "preprocess", "inference", "postprocess", "depth", "total") | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description=__doc__, | |
| formatter_class=argparse.RawDescriptionHelpFormatter) | |
| parser.add_argument("--bench-dir", type=Path, default=Path("bench")) | |
| parser.add_argument("--metric", default="p50", choices=["p50", "p95", "mean"]) | |
| args = parser.parse_args() | |
| runs = {} | |
| for tag in ("pt", "onnx", "ncnn"): | |
| path = args.bench_dir / f"{tag}_timing.json" | |
| if path.exists(): | |
| runs[tag] = json.loads(path.read_text()) | |
| if not runs: | |
| raise SystemExit(f"no *_timing.json under {args.bench_dir}; run a benchmark first") | |
| tags = list(runs) | |
| print(f"\n{args.metric} milliseconds per frame\n") | |
| print(f" {'stage':<14}" + "".join(f"{t:>12}" for t in tags)) | |
| print(" " + "-" * (14 + 12 * len(tags))) | |
| for stage in STAGES: | |
| row = "".join(f"{runs[t]['stages'][stage][args.metric]:12.2f}" for t in tags) | |
| print(f" {stage:<14}{row}") | |
| print("\n " + "-" * (14 + 12 * len(tags))) | |
| print(f" {'FPS':<14}" | |
| + "".join(f"{1000 / runs[t]['stages']['total'][args.metric]:12.2f}" for t in tags)) | |
| print(f" {'size (MB)':<14}" + "".join(f"{runs[t]['size_mb']:12.1f}" for t in tags)) | |
| print(f" {'load (ms)':<14}" + "".join(f"{runs[t]['load_ms']:12.0f}" for t in tags)) | |
| print(f" {'cores':<14}" + "".join(f"{str(runs[t].get('cpu_affinity','?')):>12}" for t in tags)) | |
| # Relative to the first column, which is PyTorch when it is present. | |
| base = tags[0] | |
| print(f"\n inference speedup vs {base}:") | |
| for tag in tags: | |
| ratio = (runs[base]["stages"]["inference"][args.metric] | |
| / runs[tag]["stages"]["inference"][args.metric]) | |
| print(f" {tag:<8}{ratio:5.2f}x") | |
| spread = [runs[t]["stages"]["depth"][args.metric] for t in tags] | |
| if len(spread) > 1 and (max(spread) - min(spread)) > 0.25 * max(spread): | |
| print(f"\n !! depth varies {min(spread):.2f}-{max(spread):.2f} ms between formats.") | |
| print(f" It is identical code on the same boxes, so this run measured") | |
| print(f" CPU contention, not the export format. Pin --threads.") | |
| if __name__ == "__main__": | |
| main() | |