Download src/bench/eval_ncnn.py from Aryan006/cone-distance: direct link, hf CLI and curl.
- Browser
- Download file 3.45 kB
-
https://huggingface.co/Aryan006/cone-distance/resolve/main/src/bench/eval_ncnn.py
- Command line
-
hf download hf://Aryan006/cone-distance/src/bench/eval_ncnn.py
-
curl -L -o eval_ncnn.py https://huggingface.co/Aryan006/cone-distance/resolve/main/src/bench/eval_ncnn.py
3.45 kB
| """Benchmark the NCNN export. | |
| The one that matters for the Pi. NCNN is Tencent's ARM-targeted inference | |
| framework, which is why it wins on a Cortex-A76 -- Ultralytics' published Pi 5 | |
| table has it at 93.9 ms against PyTorch's 524.8 ms, 5.6x, with mAP slightly | |
| *up* rather than degraded. On x86 that advantage largely disappears, so a number | |
| from this machine is a plumbing check, not a prediction of Pi performance. | |
| `--weights` takes the exported *directory*, not a file: NCNN splits a model into | |
| `model.ncnn.param` (the graph) and `model.ncnn.bin` (the weights). | |
| python -m src.bench.eval_ncnn | |
| A note on the preflight below. A mismatch between the pnnx that wrote the export | |
| and the ncnn runtime loading it does not fail cleanly -- both files load, the | |
| extractor is created, the input is accepted, and the process then segfaults | |
| inside the forward pass. A segfault cannot be caught in-process, so a bad | |
| combination would take the benchmark down with no diagnosis and no output. The | |
| check therefore runs one forward pass in a child process first, where a crash is | |
| just a return code. | |
| """ | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| from src.bench.common_cli import build_parser, run | |
| PROBE = """ | |
| import ncnn, sys | |
| net = ncnn.Net() | |
| if net.load_param({param!r}) != 0 or net.load_model({bin!r}) != 0: | |
| sys.exit(2) | |
| ex = net.create_extractor() | |
| mat = ncnn.Mat(64, 64, 3); mat.fill(0.0) | |
| ex.input(net.input_names()[0], mat) | |
| ex.extract(net.output_names()[0]) | |
| """ | |
| def preflight(weights: str) -> None: | |
| """Run one forward pass in a child process and explain any crash.""" | |
| directory = Path(weights) | |
| param, binary = directory / "model.ncnn.param", directory / "model.ncnn.bin" | |
| if not param.exists() or not binary.exists(): | |
| raise SystemExit(f"{directory} is not an NCNN export " | |
| f"(expected model.ncnn.param and model.ncnn.bin). " | |
| f"Create it with conversions.py.") | |
| result = subprocess.run( | |
| [sys.executable, "-c", PROBE.format(param=str(param), bin=str(binary))], | |
| capture_output=True) | |
| if result.returncode == 0: | |
| return | |
| import ncnn | |
| if result.returncode < 0: | |
| raise SystemExit( | |
| f"\nThe NCNN runtime crashed running this model " | |
| f"(signal {-result.returncode}).\n\n" | |
| f"The export loads -- both files parse and the graph builds -- and then\n" | |
| f"dies in the forward pass. That is the signature of a version mismatch\n" | |
| f"between the pnnx that wrote {directory}/ and the ncnn that is\n" | |
| f"reading it: the weight layout changed between them, so ncnn walks off\n" | |
| f"the end of the buffer.\n\n" | |
| f" installed ncnn: {ncnn.__version__}\n\n" | |
| f"Fixes, cheapest first:\n" | |
| f" * re-export on the machine that will run it -- this is the usual\n" | |
| f" answer for the Pi, where you install ncnn from its own toolchain\n" | |
| f" * pin the ncnn wheel to the version pnnx targeted\n" | |
| f" * benchmark ONNX instead on this box; it measures the same pipeline\n") | |
| raise SystemExit(f"NCNN probe failed (exit {result.returncode}): " | |
| f"{result.stderr.decode()[:400]}") | |
| if __name__ == "__main__": | |
| parser = build_parser(__doc__, default_weights="yolo11n_ncnn_model") | |
| args = parser.parse_args() | |
| preflight(args.weights) | |
| run(args, label="NCNN", tag="ncnn") | |