Add ONNX Runtime neural-net backend (OpenVINO EP, v1.17.1) - #1222
Add ONNX Runtime neural-net backend (OpenVINO EP, v1.17.1)#1222seniorfish wants to merge 4 commits into
Conversation
Add a new USE_BACKEND=ONNX option that runs inference through ONNX Runtime, reusing the existing OnnxModelBuilder graph emitter (shared with the TensorRT backend) so the IO protocol and output decode are identical to TensorRT. Only onnxbackend.cpp is new; the rest is wiring (CMake, setup, version info, config keys, example config). The backend supports any ONNX Runtime execution provider. It is primarily useful for running KataGo on non-NVIDIA accelerators that have an EP, e.g. Intel GPUs/NPUs via the OpenVINO EP. Because the official prebuilt ONNX Runtime packages do not ship those EPs, the Compiling.md section documents building ONNX Runtime from source with the desired provider enabled. onnxmodelbuilder.cpp: declare graph inputs in consumption order (InputSpatial, InputGlobal, InputMask) rather than the previous InputMask-first order. This is purely cosmetic for backends that bind inputs by name (TensorRT), but is required for the OpenVINO EP, which builds its name->index map from declaration order while the ORT runtime feeds the EP kernel inputs in consumption order -- with InputMask first the EP misroutes the mask tensor into the InputSpatial port.
onnxmodelbuilder: use Pow(x,2.0) instead of Mul(x,x) for RMSNorm square OpenVINO RMSFusion (rms_fusion.cpp:38) matches Power(x, const(2)) but not Mul(x,x). Without this, all 66 RMSNorm nodes in the b11c768 transformer run as unfused ReduceMean->Sqrt->Div chains. Benchmark (Arc B580, NHWC, numStreams=2, 10 threads, 800 visits): Before: 347.49 visits/s 296.04 nnEvals/s After: 416.52 visits/s 353.14 nnEvals/s (+19.9%) Also add KATAGO_DUMP_ONNX env-var debug aid to dump the serialized ONNX model before session creation. Co-Authored-By: Claude <noreply@anthropic.com> @
|
Prebuilt binaries with ONNX Runtime + OpenVINO 2026.2.1 for Intel GPUs: https://github.com/seniorfish/KataGo/releases/tag/onnx-backend-v2 ~20% faster than v1 on transformer models (numStreams=2, 10 threads, 800 visits, 347.49 visits/s -> 416.52 visits/s). |
|
Thank you for sharing your work! For some reason, it runs at only about 36% of the speed of #1171 in my environment (Intel Core Ultra 7 255U, Linux).
Also, what do you think about supporting the combined use of the NPU and iGPU? Simply setting |
|
(1) (2) It also fails with the model (3) Removing
|
…LE8 subgraphs hurting NPU performance
|
@kaorahi, thank you. That's a very insightful observation. The patch has been committed. The new version gives me roughly a 4x performance improvement here as well (Core Ultra 9 285H reaching 54 visits/s, NPU). Regarding your second issue, kata1-b18c384nbt-s9996604416-d4316597426 seems to run fine on my end, both on the B580 and the 285H, with onnxOpenVINODeviceType = GPU. As for your suggestion about supporting the combined use of the NPU and iGPU, I'll try to implement it. |
Add ONNX Runtime neural-net backend (OpenVINO EP)
Draft PR. Feedback welcome — see notes at the bottom.
Summary
This PR adds a new
USE_BACKEND=ONNXoption that runs KataGo's neural-net inference through ONNX Runtime, with pluggable execution providers.Relation to #1164: an ONNX Runtime backend PR (#1164 by @ChinChangYang) already exists. This PR is offered as an alternative with two differences: (1) it tracks current
master(v1.17.0 + v1.17.1) and supports the transformer trunk models introduced there (the existing PR predates that release); and (2) it reuses master's existingOnnxModelBuilder(shared with the TensorRT backend) instead of introducing a separate graph emitter, so the new backend is a single file plus wiring and touches no other backend.What changed:
cpp/neuralnet/onnxbackend.cpp(new) — the fullNeuralNet::*backend implementation behind#ifdef USE_ONNX_BACKEND. It serializes the model graph via the existingOnnxModelBuilderinto an ONNXModelProtoand feeds it to anOrt::Session; input filling and output decode are copied line-for-line fromtrtbackend, so the IO protocol and post-processing are identical to TensorRT.cpp/neuralnet/onnxmodelbuilder.{h,cpp}— adds an opt-inalignInputsToConsumptionOrderparameter toOnnxModelBuilder::build()(defaultfalse). Whentrue, graph inputs are declared in consumption order (InputSpatial, InputGlobal, InputMask) instead of the default order. This is a no-op for backends that bind inputs by name, but is required for the OpenVINO EP under ORT, which builds its name→index map from declaration order while the runtime feeds the EP kernel ports in consumption order — with the default order the EP misroutes the mask tensor into the InputSpatial port. The ONNX backend requests it only for the OpenVINO provider.cpp/CMakeLists.txt— ONNX branch in theUSE_BACKENDchain (links ONNX Runtime + protobuf + zlib, generatesonnx.proto, definesUSE_ONNX_BACKEND, copies ORT DLLs).cpp/program/setup.cpp— registers theonnxbackend prefix; ONNX defaults to NCHW (inputsUseNHWC = false), otherwisecreateComputeHandlethrows.cpp/main.cpp— version-info#elif USE_ONNX_BACKEND.cpp/program/gtpconfig.cpp— multi-GPUonnxDeviceToUseThreadhandling.cpp/configs/gtp_example.cfg— ONNX settings example block.Compiling.md— a new section documenting how to build ONNX Runtime from source with the desired EP and compile KataGo against it.Compatibility with existing code:
The backend is non-invasive. It reuses master's existing
OnnxModelBuilder(shared with the TensorRT backend) rather than introducing a parallel graph emitter, and the only shared-source change — thealignInputsToConsumptionOrderparameter — is an additive default parameter. The TensorRT call site is unchanged and produces a byte-identical graph (declaration order unchanged), so TRT behavior is zero-diff. Other backends are untouched. IO contract and output decode are identical to TRT, sonneval/nninputs/loadmodelneed no changes. Verified to build onmasterat v1.17.1 and to run both convnet (v15) and transformer (v17) models.Extensibility:
The architecture is provider-agnostic:
onnxProviderselects amongcpu / openvino / cuda / tensorrt / migraphx / coreml, and adding a future EP requires no code change — only config. ThealignInputsToConsumptionOrderescape hatch is generic: any EP that exhibits the same declaration-vs-consumption-order quirk can be opted in at the singlebuild()call site. Newonnx*config keys are auto-recognized by theonnxprefix insetup.cpp, so provider-specific options can be added without touching the backend core. Only the OpenVINO provider has been tested end-to-end in this PR; the other providers are wired in and should work, but are unverified.How To Use
A prebuilt Windows x64 binary with all runtime DLLs bundled is available here:
https://github.com/seniorfish/KataGo/releases/tag/onnx-backend-v1
Download
katago-onnx-backend-v1.zip, unzip, drop in a.bin.gzmodel, and point your config at it.The backend adds a family of
onnx*keys to the config file (seeconfigs/gtp_example.cfgfor the full list). The essential ones:onnxProvidercpucpu/openvino/cuda/tensorrt/migraphx/coremlonnxOpenVINODeviceTypeGPUGPU/CPU/NPU/AUTO:.../MULTI:...onnxOpenVINOCacheDironnxOpenVINONumStreamsonnxOpenVINOPrecisionFP16/FP32/ACCURACYonnxTransformerNHWCTo use an Intel GPU you must set both:
Tip (measured): if you are on a discrete Intel GPU rather than an integrated one, setting
onnxOpenVINONumStreams = 2noticeably improves throughput — two parallel OpenVINO streams keep the GPU saturated at higher thread counts (see the ablation rows in the Benchmark).Benchmark
katago benchmark,-visits 60, default config otherwise noted. EloDiff is relative to the first row of each group.Desktop — Intel Arc B580
OpenCL (baseline). Model
b11c768h12nbt3tflrs-fson-silu.bin.gz(transformer, v17):ONNX Runtime (OpenVINO EP). Model
b11c768h12nbt3tflrs-fson-silu.bin.gz,onnxOpenVINONumStreams = 2,onnxTransformerNHWC = true:Model
kata1-zhizi-b40c768nbt-s11472M-d5982M.bin.gz(convnet, v15),onnxOpenVINONumStreams = 2:Ablation (b11 transformer,
numSearchThreads = 12), isolatingNumStreams/transformerNHWC:Both knobs matter:
NumStreams = 2≈ 3× throughput vs 1, andtransformerNHWC = true≈ 2× vs false on this model.Laptop — Intel Core Ultra 9 285H, Intel Arc 140T
ONNX Runtime (OpenVINO EP),
numSearchThreads = 8:Notes
cpu/cuda/tensorrt/migraphx/coreml) are implemented but unverified — treat them as best-effort until someone confirms them.onnxOpenVINODeviceType = NPUis not working at this time).masterand to address review feedback as time allows. As a solo contributor I can't guarantee indefinite long-term stewardship, but I'm glad to coordinate with anyone — maintainer or fellow contributor — who wants to help carry it forward.Co-authored-by: glm5.2