Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ff3c105
Add ONNX Runtime neural net backend
seniorfish Jul 31, 2026
30a01b8
Merge remote-tracking branch 'origin/master' into feature/onnx-backend
seniorfish Jul 31, 2026
46d1842
@
seniorfish Aug 1, 2026
4f86efa
Skip applyScale8ToReduceActivations in ONNX backend to avoid MISH_SCA…
seniorfish Aug 1, 2026
815378d
@
seniorfish Aug 2, 2026
cac464b
Remove deprecated onnxOpenVINOEnableNPUFastCompile; document onnxOpen…
seniorfish Aug 4, 2026
3e71064
Remove alignInputsToConsumptionOrder; declare inputs unconditionally
seniorfish Aug 4, 2026
2e2d772
Remove per-server-thread max batch size feature
seniorfish Aug 5, 2026
f6767d5
Address review feedback and default transformer trunk to NHWC
seniorfish Aug 5, 2026
c2e5552
Restore applyScale8ToReduceActivations in the ONNX backend
seniorfish Aug 5, 2026
8883c4e
Scope SetIntraOpNumThreads(1) to the OpenVINO provider
seniorfish Aug 5, 2026
9f1d598
Drop the deprecated OpenVINO device_id option; map device index into …
seniorfish Aug 5, 2026
ce8c146
Add ONNX backend CI workflow for the fork
seniorfish Aug 5, 2026
e77c88d
Fix ONNX CI: onnxruntime has no v1.29.0 tag
seniorfish Aug 5, 2026
c2cedbc
Merge origin/master into feature/onnx-backend
seniorfish Aug 5, 2026
1bdb258
Document InputMeta position in the OpenVINO input-order comment
seniorfish Aug 5, 2026
3a8ddf2
Fix unexpanded $env:GITHUB_WORKSPACE in CMake -D paths
seniorfish Aug 5, 2026
0909331
Restrict CI trigger back to the PR branch
seniorfish Aug 5, 2026
7b91582
Clean up ONNX backend: plain-bool scale8 flag, drop dead field, warn …
seniorfish Aug 5, 2026
895b266
Document execution-provider verification status; hoist ONNX provider …
seniorfish Aug 5, 2026
22960c0
Add Windows ONNX CPU build CI using the prebuilt ORT package
seniorfish Aug 5, 2026
e99d4d3
Add DirectML execution provider support to the ONNX backend
seniorfish Aug 5, 2026
f7c383b
Consolidate ONNX CI into one matrix workflow with reusable composite …
seniorfish Aug 5, 2026
2346f94
Add Linux CPU backend to the ONNX CI matrix
seniorfish Aug 5, 2026
166a435
Add TensorRT backend to the ONNX CI and cache ORT builds
seniorfish Aug 6, 2026
db0a622
Merge upstream master (v1.17.2) into feature/onnx-backend
seniorfish Aug 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .github/actions/onnx-build-katago/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: Build and test KataGo (ONNX backend)
description: >
Configure, build, run `katago runtests`, verify the ORT backend is wired up, and stage a
self-contained runnable directory under release/ (katago binary + ORT runtime + EP
runtimes + example config). Expects onnx-prepare-ort to have populated
deps/install/{ort,protobuf,zlib} and the MSVC environment to be ready on Windows.
inputs:
ort_root:
description: Path to the ORT install tree (deps/install/ort)
required: true
ep:
description: Execution provider, used for EP-specific runtime staging
required: true

runs:
using: composite
steps:
- name: Configure KataGo (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
cmake -S cpp -B cpp\build -G Ninja -DCMAKE_BUILD_TYPE=Release -DUSE_BACKEND=ONNX `
-DONNXRUNTIME_ROOT=${{ inputs.ort_root }} `
-DProtobuf_PROTOC_EXECUTABLE=${{ github.workspace }}\deps\install\protobuf\bin\protoc.exe `
-DProtobuf_INCLUDE_DIR=${{ github.workspace }}\deps\install\protobuf\include `
-DProtobuf_LIBRARY=${{ github.workspace }}\deps\install\protobuf\lib\libprotobuf.lib `
-DZLIB_INCLUDE_DIR=${{ github.workspace }}\deps\install\zlib\include `
-DZLIB_LIBRARY=${{ github.workspace }}\deps\install\zlib\lib\zlibstatic.lib

- name: Configure KataGo (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
# Use $GITHUB_WORKSPACE (not the github.workspace context): it resolves correctly
# both on plain runners (/home/runner/...) and inside a container job (/__w/...).
cmake -S cpp -B cpp/build -G Ninja -DCMAKE_BUILD_TYPE=Release -DUSE_BACKEND=ONNX \
-DONNXRUNTIME_ROOT="$GITHUB_WORKSPACE/deps/install/ort" \
-DProtobuf_PROTOC_EXECUTABLE="$GITHUB_WORKSPACE/deps/install/protobuf/bin/protoc" \
-DProtobuf_INCLUDE_DIR="$GITHUB_WORKSPACE/deps/install/protobuf/include" \
-DProtobuf_LIBRARY="$GITHUB_WORKSPACE/deps/install/protobuf/lib/libprotobuf.a" \
-DZLIB_INCLUDE_DIR="$GITHUB_WORKSPACE/deps/install/zlib/include" \
-DZLIB_LIBRARY="$GITHUB_WORKSPACE/deps/install/zlib/lib/libz.a"

- name: Build KataGo
shell: bash
run: cmake --build cpp/build

- name: Run tests
shell: bash
run: |
if [ "${{ runner.os }}" = "Windows" ]; then ./cpp/build/katago.exe runtests; else ./cpp/build/katago runtests; fi

- name: Verify backend wiring
shell: bash
run: |
# Command substitution flattens multi-line output: testing the raw array for a
# substring is unreliable, so check the flattened string with grep.
if [ "${{ runner.os }}" = "Windows" ]; then OUT=$(cpp/build/katago.exe version 2>&1); else OUT=$(cpp/build/katago version 2>&1); fi
if ! echo "$OUT" | grep -q "ONNX Runtime"; then
echo "unexpected backend version output: $OUT"
exit 1
fi
echo "$OUT" | head -8

- name: Stage release directory (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path "release" | Out-Null
Copy-Item "cpp\build\katago.exe" "release\"
Get-ChildItem "deps\install\ort\bin\*.dll" -ErrorAction SilentlyContinue | Copy-Item -Destination "release\" -Force
# EP-specific runtime DLLs
if ("${{ inputs.ep }}" -eq "openvino") {
Get-ChildItem "deps\install\ort\lib\onnxruntime_providers_openvino.dll" -ErrorAction SilentlyContinue | Copy-Item -Destination "release\" -Force
$ovBin = "deps\openvino\runtime\bin\intel64\Release"
if (Test-Path $ovBin) {
Copy-Item "$ovBin\*.dll" "release\"
Copy-Item "$ovBin\*.json" "release\"
} else {
Write-Warning "OpenVINO runtime bin dir not found at $ovBin"
}
$tbb = Get-ChildItem "deps\openvino" -Recurse -Filter "tbb12.dll" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($tbb) { Copy-Item $tbb.FullName "release\" }
}
Copy-Item "cpp\configs\gtp_example.cfg" "release\"
Write-Output "--- release contents ---"
Get-ChildItem "release" | Select-Object Name, Length

- name: Stage release directory (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
mkdir -p release
cp cpp/build/katago release/
cp deps/install/ort/lib/libonnxruntime*.so* release/ 2>/dev/null || true
# EP-specific runtime libs (TensorRT/CUDA/ROCm, etc.) go here once wired up.
cp cpp/configs/gtp_example.cfg release/
# katago's build-time DT_RUNPATH points at the CI workspace
# (deps/install/ort/lib), which no longer exists once the artifact is downloaded
# elsewhere. Rewrite it to $ORIGIN so the binary finds the sibling
# libonnxruntime.so* in the release dir, matching the Windows DLL convention.
if ! command -v patchelf >/dev/null 2>&1; then
# Ubuntu runners have sudo; the NGC TensorRT container runs as root without it.
if command -v sudo >/dev/null 2>&1; then sudo apt-get install -y patchelf >/dev/null; else apt-get install -y patchelf >/dev/null; fi
fi
patchelf --set-rpath '$ORIGIN' release/katago
ls -la release
264 changes: 264 additions & 0 deletions .github/actions/onnx-prepare-ort/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
name: Prepare ONNX Runtime
description: >
Fetch or build an ONNX Runtime install tree carrying the requested execution provider,
plus KataGo's own zlib/protobuf deps. Everything lands under deps/install/ and is
cached, so only the first run pays for ORT acquisition (from-source ORT builds are the
expensive case, 1-3h; prebuilt/nuget are minutes).
inputs:
ep:
description: Execution provider to wire up (cpu, directml, openvino, ...)
required: true
mode:
description: >
How to obtain ORT. 'prebuilt' = official release zip (CPU EP ships inside it),
'nuget' = Microsoft.ML.OnnxRuntime.DirectML package, 'from-source' = build ORT
ourselves with the EP.
required: true
ort_version:
description: ORT release version for prebuilt/nuget modes
required: false
default: "1.28.0"
ort_ref:
description: ORT git ref (tag/SHA) for from-source mode
required: false
default: ""
ov_version:
description: OpenVINO toolkit version (from-source/openvino only)
required: false
default: ""
ov_url:
description: OpenVINO toolkit download URL (from-source/openvino only)
required: false
default: ""
pb_version:
description: protobuf version built for KataGo (3.x, no abseil dependency)
required: false
default: "3.21.12"
pb_tag:
description: >
protobuf release tag for pb_version. protobuf 3.x tags drop the major (3.21.12
-> v21.12), so this cannot be derived from pb_version.
required: false
default: "21.12"
zlib_version:
description: zlib version built for KataGo
required: false
default: "1.3.1"

outputs:
ort_root:
description: Path to the prepared ORT install tree
value: ${{ github.workspace }}/deps/install/ort

runs:
using: composite
steps:
# ---------------------------------------------------------------------------
# Common deps: zlib + protobuf, always built from source and cached separately
# from the ORT tree so a from-source ORT cache miss does not rebuild them.
# ---------------------------------------------------------------------------
- name: Restore common-dep cache
id: cache-common
uses: actions/cache@v4
with:
path: |
deps/install/zlib
deps/install/protobuf
key: onnx-common-${{ runner.os }}-pb-${{ inputs.pb_version }}-zl-${{ inputs.zlib_version }}

- name: Build zlib (static, Windows)
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Windows'
shell: pwsh
run: |
curl.exe -L -o "$env:RUNNER_TEMP\zlib.tar.gz" "https://github.com/madler/zlib/releases/download/v${{ inputs.zlib_version }}/zlib-${{ inputs.zlib_version }}.tar.gz"
tar -xzf "$env:RUNNER_TEMP\zlib.tar.gz" -C "$env:RUNNER_TEMP"
cmake -S "$env:RUNNER_TEMP\zlib-${{ inputs.zlib_version }}" -B "$env:RUNNER_TEMP\zlib-build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}\deps\install\zlib
cmake --build "$env:RUNNER_TEMP\zlib-build"
cmake --install "$env:RUNNER_TEMP\zlib-build"

- name: Build zlib (static, Linux)
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Linux'
shell: bash
run: |
curl -L -o "$RUNNER_TEMP/zlib.tar.gz" "https://github.com/madler/zlib/releases/download/v${{ inputs.zlib_version }}/zlib-${{ inputs.zlib_version }}.tar.gz"
tar -xzf "$RUNNER_TEMP/zlib.tar.gz" -C "$RUNNER_TEMP"
cmake -S "$RUNNER_TEMP/zlib-${{ inputs.zlib_version }}" -B "$RUNNER_TEMP/zlib-build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/deps/install/zlib"
cmake --build "$RUNNER_TEMP/zlib-build"
cmake --install "$RUNNER_TEMP/zlib-build"

- name: Build protobuf (static, /MD, Windows)
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Windows'
shell: pwsh
run: |
curl.exe -L -o "$env:RUNNER_TEMP\pb.tar.gz" "https://github.com/protocolbuffers/protobuf/releases/download/v${{ inputs.pb_tag }}/protobuf-cpp-${{ inputs.pb_version }}.tar.gz"
tar -xzf "$env:RUNNER_TEMP\pb.tar.gz" -C "$env:RUNNER_TEMP"
# protobuf_MSVC_STATIC_RUNTIME=OFF is REQUIRED: the protobuf default (/MT) would
# clash with KataGo's /MD Release build (LNK2038) when linking libprotobuf statically.
cmake -S "$env:RUNNER_TEMP\protobuf-${{ inputs.pb_version }}" -B "$env:RUNNER_TEMP\pb-build" -G Ninja `
-DCMAKE_BUILD_TYPE=Release `
-Dprotobuf_BUILD_TESTS=OFF `
-Dprotobuf_BUILD_SHARED_LIBS=OFF `
-Dprotobuf_MSVC_STATIC_RUNTIME=OFF `
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}\deps\install\protobuf
cmake --build "$env:RUNNER_TEMP\pb-build"
cmake --install "$env:RUNNER_TEMP\pb-build"

- name: Build protobuf (static, Linux)
if: steps.cache-common.outputs.cache-hit != 'true' && runner.os == 'Linux'
shell: bash
run: |
curl -L -o "$RUNNER_TEMP/pb.tar.gz" "https://github.com/protocolbuffers/protobuf/releases/download/v${{ inputs.pb_tag }}/protobuf-cpp-${{ inputs.pb_version }}.tar.gz"
tar -xzf "$RUNNER_TEMP/pb.tar.gz" -C "$RUNNER_TEMP"
cmake -S "$RUNNER_TEMP/protobuf-${{ inputs.pb_version }}" -B "$RUNNER_TEMP/pb-build" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-Dprotobuf_BUILD_TESTS=OFF \
-Dprotobuf_BUILD_SHARED_LIBS=OFF \
-DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/deps/install/protobuf"
cmake --build "$RUNNER_TEMP/pb-build"
cmake --install "$RUNNER_TEMP/pb-build"

# ---------------------------------------------------------------------------
# ONNX Runtime install tree, cached per (os, ep, version/ref).
# ---------------------------------------------------------------------------
- name: Restore ORT cache
id: cache-ort
uses: actions/cache@v4
with:
path: deps/install/ort
key: onnx-ort-${{ runner.os }}-${{ inputs.ep }}-${{ inputs.ort_version }}-${{ inputs.ort_ref }}

# --- prebuilt: official ORT release package (CPU EP ships inside it): zip on Windows, tgz on Linux ---
- name: Fetch prebuilt ORT (Windows)
if: inputs.mode == 'prebuilt' && runner.os == 'Windows' && steps.cache-ort.outputs.cache-hit != 'true'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path "deps\install\ort" | Out-Null
curl.exe -sfL -o "$env:RUNNER_TEMP\ort.zip" "https://github.com/microsoft/onnxruntime/releases/download/v${{ inputs.ort_version }}/onnxruntime-win-x64-${{ inputs.ort_version }}.zip"
Expand-Archive -Path "$env:RUNNER_TEMP\ort.zip" -DestinationPath "$env:RUNNER_TEMP\ort" -Force
$inner = Get-ChildItem "$env:RUNNER_TEMP\ort" -Directory | Select-Object -First 1
if ($inner) {
Get-ChildItem $inner.FullName | Move-Item -Destination "deps\install\ort" -Force
Remove-Item $inner.FullName -Recurse -Force
}
Remove-Item "$env:RUNNER_TEMP\ort.zip" -Force
# Hoist lib/*.dll into bin/ too: the release-staging step globs bin/.
New-Item -ItemType Directory -Force -Path "deps\install\ort\bin" | Out-Null
Get-ChildItem "deps\install\ort\lib\*.dll" -ErrorAction SilentlyContinue | Copy-Item -Destination "deps\install\ort\bin" -Force

- name: Fetch prebuilt ORT (Linux)
if: inputs.mode == 'prebuilt' && runner.os == 'Linux' && steps.cache-ort.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p deps/install/ort
curl -sfL -o "$RUNNER_TEMP/ort.tgz" "https://github.com/microsoft/onnxruntime/releases/download/v${{ inputs.ort_version }}/onnxruntime-linux-x64-${{ inputs.ort_version }}.tgz"
tar -xzf "$RUNNER_TEMP/ort.tgz" -C deps/install/ort --strip-components=1
# No lib/*.dll hoist is needed here: Linux resolves libonnxruntime.so through the
# binary's DT_RUNPATH, which onnx-build-katago rewrites to $ORIGIN at staging time.
ls deps/install/ort

# --- nuget: Microsoft.ML.OnnxRuntime.DirectML package (DirectML EP) ---
- name: Fetch DirectML NuGet package (Windows)
if: inputs.mode == 'nuget' && runner.os == 'Windows' && steps.cache-ort.outputs.cache-hit != 'true'
shell: pwsh
run: |
$src = "$env:RUNNER_TEMP\dml"
New-Item -ItemType Directory -Force -Path "$src" | Out-Null
curl.exe -sfL -o "$src\dml.nupkg" "https://api.nuget.org/v3-flatcontainer/microsoft.ml.onnxruntime.directml/${{ inputs.ort_version }}/microsoft.ml.onnxruntime.directml.${{ inputs.ort_version }}.nupkg"
tar -xzf "$src\dml.nupkg" -C "$src"
$root = "deps\install\ort"
New-Item -ItemType Directory -Force -Path "$root\include","$root\lib","$root\bin" | Out-Null
Copy-Item "$src\build\native\include\*" "$root\include" -Force
Copy-Item "$src\runtimes\win-x64\native\onnxruntime.lib" "$root\lib" -Force
Get-ChildItem "$src\runtimes\win-x64\native\*.dll" | Copy-Item -Destination "$root\lib" -Force
Get-ChildItem "$root\lib\*.dll" | Copy-Item -Destination "$root\bin" -Force

# --- from-source: build ORT ourselves with the requested EP ---
- name: Checkout ONNX Runtime source
if: inputs.mode == 'from-source' && steps.cache-ort.outputs.cache-hit != 'true'
uses: actions/checkout@v4
with:
repository: microsoft/onnxruntime
ref: ${{ inputs.ort_ref }}
path: deps/onnxruntime
submodules: recursive

- name: Fetch OpenVINO toolkit (Windows)
if: inputs.mode == 'from-source' && inputs.ep == 'openvino' && runner.os == 'Windows' && steps.cache-ort.outputs.cache-hit != 'true'
shell: pwsh
run: |
$zip = "$env:RUNNER_TEMP\openvino.zip"
$dest = "deps\openvino"
Invoke-WebRequest -Uri "${{ inputs.ov_url }}" -OutFile $zip
Expand-Archive -Path $zip -DestinationPath $dest
# The zip contains a single top-level directory of the same name; hoist its contents up.
$inner = Get-ChildItem -Path $dest -Directory | Select-Object -First 1
if ($inner) {
Get-ChildItem -Path $inner.FullName | Move-Item -Destination $dest -Force
Remove-Item -Path $inner.FullName -Recurse -Force
}
Remove-Item -Path $zip -Force
$sv = Get-ChildItem "deps\openvino" -Recurse -Filter "setupvars.bat" | Select-Object -First 1
if (-not $sv) { throw "setupvars.bat not found under deps\openvino" }
echo "OV_SETUPVARS=$($sv.FullName)" >> $env:GITHUB_ENV

- name: Build ONNX Runtime with OpenVINO EP
if: inputs.mode == 'from-source' && inputs.ep == 'openvino' && steps.cache-ort.outputs.cache-hit != 'true'
shell: cmd
working-directory: deps/onnxruntime
run: |
call "%OV_SETUPVARS%"
python tools\ci_build\build.py --build_dir build --config Release --use_openvino GPU --build_shared_lib --skip_tests --parallel --compile_no_warning_as_error --cmake_generator Ninja --cmake_extra_defines CMAKE_INSTALL_PREFIX=%CD%\..\install\ort
if errorlevel 1 exit /b 1
cmake --install build\Release --config Release
if errorlevel 1 exit /b 1

- name: Build ONNX Runtime with TensorRT EP (Linux container)
if: inputs.mode == 'from-source' && inputs.ep == 'tensorrt' && runner.os == 'Linux' && steps.cache-ort.outputs.cache-hit != 'true'
shell: bash
working-directory: deps/onnxruntime
run: |
# Runs inside the official NGC TensorRT container
# (nvcr.io/nvidia/tensorrt:25.03-py3 = CUDA 12.8 + TensorRT 10.9, the combo ORT is
# tested against), which preinstalls CUDA/cuDNN/TensorRT under /usr/local/cuda and
# /usr/lib/x86_64-linux-gnu. The container ships cmake + python3; the workflow's
# bootstrap step adds ninja. github-hosted runners have no GPU, so this verifies
# build + EP wiring only - real GPU inference is validated on a GPU machine.
# Build only for sm_89 (RTX 4090): ORT's default 10-arch matrix is huge and slow
# on a no-GPU CI runner. Tune per the GPU you validate on.
python3 tools/ci_build/build.py --build_dir build --config Release \
--use_tensorrt --use_cuda \
--cuda_home /usr/local/cuda \
--cudnn_home /usr/lib/x86_64-linux-gnu \
--tensorrt_home /usr/lib/x86_64-linux-gnu \
--build_shared_lib --skip_tests --parallel \
--cmake_generator Ninja --allow_running_as_root --skip_submodule_sync \
--cmake_extra_defines "CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/deps/install/ort" "CMAKE_CUDA_ARCHITECTURES=89"
cmake --install build/Release --config Release

# NOTE: MIGraphX from-source build slots in here once validated (needs ROCm; deferred).

# Save caches explicitly: actions/cache@v4's post-save does not reliably run inside
# composite actions, so without these every run would rebuild zlib/protobuf and ORT.
# Only save when this run actually built the dep (restore cache-missed); the key must
# match the restore key above.
- name: Save common-dep cache
if: steps.cache-common.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
deps/install/zlib
deps/install/protobuf
key: onnx-common-${{ runner.os }}-pb-${{ inputs.pb_version }}-zl-${{ inputs.zlib_version }}

- name: Save ORT cache
if: steps.cache-ort.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: deps/install/ort
key: onnx-ort-${{ runner.os }}-${{ inputs.ep }}-${{ inputs.ort_version }}-${{ inputs.ort_ref }}

- name: Report ORT install tree
shell: bash
run: |
ls -la deps/install/ort
ls deps/install/ort/bin 2>/dev/null || ls deps/install/ort/lib 2>/dev/null || true
Loading