Skip to content

Commit d085a37

Browse files
committed
Merge remote-tracking branch 'upstream/main' into melodyr/single-source-of-truth-for-hw-pin
Signed-off-by: Melody Ren <melodyr@nvidia.com> # Conflicts: # libs/qec/lib/realtime/decoding-server-cqr/DecodingSession.cpp
2 parents c42372f + 291aa7f commit d085a37

74 files changed

Lines changed: 6651 additions & 3682 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
name: Build decoding-server image
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
image_name:
7+
type: string
8+
description: GHCR image name, without a tag
9+
default: ghcr.io/nvidia/private/cudaq-decoders
10+
required: true
11+
image_tag:
12+
type: string
13+
description: Base tag; defaults to wiring-<run number>, with -cu<version> added
14+
required: false
15+
16+
jobs:
17+
build:
18+
name: Build decoding-server image (${{ matrix.platform }}, CUDA ${{ matrix.cuda_version }})
19+
if: ${{ github.repository == 'NVIDIA/cudaqx' }}
20+
runs-on: linux-${{ matrix.platform }}-cpu8
21+
permissions:
22+
contents: read
23+
packages: write
24+
strategy:
25+
fail-fast: false
26+
matrix:
27+
platform: [amd64, arm64]
28+
cuda_version: ['12.6', '13.0']
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v4
32+
33+
- name: Set up context for buildx
34+
run: docker context create builder_context
35+
36+
- name: Set up buildx
37+
uses: docker/setup-buildx-action@v3
38+
with:
39+
endpoint: builder_context
40+
version: v0.19.0
41+
driver-opts: |
42+
network=host
43+
image=moby/buildkit:v0.19.0
44+
45+
- name: Log in to GitHub CR
46+
uses: docker/login-action@v3
47+
with:
48+
registry: ghcr.io
49+
username: ${{ github.actor }}
50+
password: ${{ github.token }}
51+
52+
- name: Build and push image by digest
53+
id: docker-build
54+
uses: docker/build-push-action@v5
55+
with:
56+
context: .
57+
file: docker/decoding-server/Dockerfile
58+
platforms: linux/${{ matrix.platform }}
59+
build-args: |
60+
CUDA_VERSION=${{ matrix.cuda_version }}
61+
labels: |
62+
org.opencontainers.image.source=${{ github.repositoryUrl }}
63+
org.opencontainers.image.revision=${{ github.sha }}
64+
outputs: type=image,name=${{ inputs.image_name }},push-by-digest=true,name-canonical=true,push=true
65+
66+
- name: Export image digest
67+
env:
68+
IMAGE_DIGEST: ${{ steps.docker-build.outputs.digest }}
69+
run: |
70+
set -euo pipefail
71+
72+
mkdir -p /tmp/digests
73+
touch "/tmp/digests/${IMAGE_DIGEST#sha256:}"
74+
75+
- name: Upload image digest
76+
uses: actions/upload-artifact@v4
77+
with:
78+
name: decoding-server-digest-cu${{ matrix.cuda_version }}-${{ matrix.platform }}
79+
path: /tmp/digests/*
80+
if-no-files-found: error
81+
retention-days: 1
82+
83+
publish:
84+
name: Publish decoding-server multi-platform image (CUDA ${{ matrix.cuda_version }})
85+
needs: build
86+
runs-on: ubuntu-latest
87+
permissions:
88+
packages: write
89+
strategy:
90+
fail-fast: false
91+
matrix:
92+
cuda_version: ['12.6', '13.0']
93+
steps:
94+
- name: Set up buildx
95+
uses: docker/setup-buildx-action@v3
96+
97+
- name: Log in to GitHub CR
98+
uses: docker/login-action@v3
99+
with:
100+
registry: ghcr.io
101+
username: ${{ github.actor }}
102+
password: ${{ github.token }}
103+
104+
- name: Download image digests
105+
uses: actions/download-artifact@v4
106+
with:
107+
path: /tmp/digests
108+
pattern: decoding-server-digest-cu${{ matrix.cuda_version }}-*
109+
merge-multiple: true
110+
111+
- name: Create and verify multi-platform image
112+
env:
113+
IMAGE_NAME: ${{ inputs.image_name }}
114+
IMAGE_TAG: ${{ inputs.image_tag || format('wiring-{0}', github.run_number) }}
115+
CUDA_VERSION: ${{ matrix.cuda_version }}
116+
run: |
117+
set -euo pipefail
118+
119+
cd /tmp/digests
120+
image_ref="${IMAGE_NAME}:${IMAGE_TAG}-cu${CUDA_VERSION}"
121+
mapfile -t digests < <(find . -maxdepth 1 -type f -printf '%f\n' | sort)
122+
if [[ "${#digests[@]}" != 2 ]]; then
123+
echo "::error::Expected 2 image digests, found ${#digests[@]}"
124+
exit 1
125+
fi
126+
127+
refs=()
128+
for digest in "${digests[@]}"; do
129+
refs+=("${IMAGE_NAME}@sha256:${digest}")
130+
done
131+
132+
docker buildx imagetools create --tag "$image_ref" "${refs[@]}"
133+
134+
manifest=$(docker buildx imagetools inspect --raw "$image_ref")
135+
for architecture in amd64 arm64; do
136+
jq -e \
137+
--arg architecture "$architecture" \
138+
'.manifests[] | select(.platform.os == "linux" and .platform.architecture == $architecture)' \
139+
<<< "$manifest" > /dev/null
140+
done
141+
142+
docker buildx imagetools inspect "$image_ref"

docker/decoding-server/Dockerfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# ============================================================================ #
2+
# Copyright (c) 2025 - 2026 NVIDIA Corporation & Affiliates. #
3+
# All rights reserved. #
4+
# #
5+
# This source code and the accompanying materials are made available under #
6+
# the terms of the Apache License 2.0 which accompanies this distribution. #
7+
# ============================================================================ #
8+
9+
# This is a temporary, minimal image used to validate the decoding-server
10+
# multi-platform publication workflow while getting the CI wiring in place.
11+
FROM ubuntu:24.04
12+
13+
ARG TARGETARCH
14+
ARG CUDA_VERSION
15+
16+
RUN printf '%s\n' \
17+
'CUDA-QX decoding-server image wiring test' \
18+
"architecture=${TARGETARCH}" \
19+
"cuda=${CUDA_VERSION}" \
20+
> /etc/cudaqx-decoding-server-image
21+
22+
CMD ["cat", "/etc/cudaqx-decoding-server-image"]

docs/sphinx/api/qec/cpp_api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ Detector Error Model
3030
.. doxygenstruct:: cudaq::qec::detector_error_model
3131
:members:
3232

33+
.. doxygenstruct:: cudaq::qec::decoder_context
34+
:members:
35+
3336
.. doxygenfunction:: cudaq::qec::dem_from_memory_circuit(const code &, operation, std::size_t, cudaq::noise_model &, bool)
3437
.. doxygenfunction:: cudaq::qec::x_dem_from_memory_circuit(const code &, operation, std::size_t, cudaq::noise_model &, bool)
3538
.. doxygenfunction:: cudaq::qec::z_dem_from_memory_circuit(const code &, operation, std::size_t, cudaq::noise_model &, bool)
39+
.. doxygenfunction:: cudaq::qec::decoder_context_from_memory_circuit(const code &, operation, std::size_t, cudaq::noise_model &, bool)
3640
.. doxygenfunction:: cudaq::qec::dem_from_stim_text(const std::string &, bool)
3741

3842
Decoder Interfaces

docs/sphinx/api/qec/python_api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,13 @@ Detector Error Model
2929
.. autoclass:: cudaq_qec.DetectorErrorModel
3030
:members:
3131

32+
.. autoclass:: cudaq_qec.DecoderContext
33+
:members:
34+
3235
.. autofunction:: cudaq_qec.dem_from_memory_circuit
3336
.. autofunction:: cudaq_qec.x_dem_from_memory_circuit
3437
.. autofunction:: cudaq_qec.z_dem_from_memory_circuit
38+
.. autofunction:: cudaq_qec.decoder_context_from_memory_circuit
3539
.. autofunction:: cudaq_qec.dem_from_stim_text
3640

3741
Decoder Interfaces

docs/sphinx/api/qec/python_realtime_decoding_api.rst

Lines changed: 76 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -72,65 +72,82 @@ Configuration API
7272

7373
The configuration API enables setting up decoders before circuit execution. Decoders are configured using YAML files or programmatically constructed configuration objects.
7474

75-
Configuration Types
76-
^^^^^^^^^^^^^^^^^^^
77-
78-
.. py:class:: cudaq_qec.pymatching_config
79-
80-
Configuration for the PyMatching decoder in the real-time decoding system.
81-
Use this with ``decoder_config.type = "pymatching"``.
82-
Set ``decoder_config.type`` before passing this object to
83-
``decoder_config.set_decoder_custom_args``.
84-
The decoder input matrix must be graphlike: each ``H_sparse`` column can
85-
contain only one or two detector entries.
86-
87-
**Attributes:**
88-
89-
.. py:attribute:: error_rate_vec
90-
:type: Optional[List[float]]
91-
92-
Per-error prior probabilities. When provided, the length must match the
93-
decoder ``block_size`` and each value must be in the range ``(0, 0.5]``.
94-
95-
.. py:attribute:: merge_strategy
96-
:type: Optional[str]
97-
98-
PyMatching edge merge strategy. Supported values are ``"disallow"``,
99-
``"independent"``, ``"smallest_weight"``, ``"keep_original"``, and
100-
``"replace"``.
101-
102-
.. py:class:: cudaq_qec.trt_decoder_config
103-
104-
Configuration for TensorRT decoder in real-time decoding system.
105-
106-
**Attributes:**
107-
108-
.. py:attribute:: onnx_load_path
109-
:type: Optional[str]
110-
111-
Path to ONNX model file. Mutually exclusive with engine_load_path.
112-
113-
.. py:attribute:: engine_load_path
114-
:type: Optional[str]
115-
116-
Path to pre-built TensorRT engine file. Mutually exclusive with
117-
onnx_load_path.
118-
119-
.. py:attribute:: engine_save_path
120-
:type: Optional[str]
121-
122-
Path to save built TensorRT engine for reuse.
123-
124-
.. py:attribute:: precision
125-
:type: Optional[str]
126-
127-
Inference precision mode: "fp16", "bf16", "int8", "fp8", "tf32",
128-
"noTF32", or "best" (default).
129-
130-
.. py:attribute:: memory_workspace
131-
:type: Optional[int]
132-
133-
Workspace memory size in bytes (default: 1073741824 = 1GB).
75+
Decoder Parameters
76+
^^^^^^^^^^^^^^^^^^
77+
78+
Decoder-specific parameters (``decoder_config.decoder_custom_args``) are
79+
plain dicts. The set of accepted keys, their types, and which are required
80+
are defined by the *parameter schema* each decoder registers -- including
81+
out-of-tree decoder plugins. Use ``cudaq_qec.decoder_param_schema(name)`` to
82+
inspect a decoder's parameters and ``cudaq_qec.registered_decoder_schemas()``
83+
to list all decoders with registered schemas.
84+
85+
For example, the ``pymatching`` decoder accepts ``error_rate_vec``
86+
(per-error prior probabilities in the range ``(0, 0.5]``, length matching
87+
the decoder ``block_size``) and ``merge_strategy`` (one of ``"disallow"``,
88+
``"independent"``, ``"smallest_weight"``, ``"keep_original"``,
89+
``"replace"``):
90+
91+
.. code-block:: python
92+
93+
config.type = "pymatching"
94+
config.decoder_custom_args = {
95+
"error_rate_vec": [0.1, 0.1, 0.1],
96+
"merge_strategy": "smallest_weight",
97+
}
98+
99+
The ``trt_decoder`` accepts ``onnx_load_path`` or ``engine_load_path``
100+
(mutually exclusive), ``engine_save_path``, ``precision`` ("fp16", "bf16",
101+
"int8", "fp8", "tf32", "noTF32", or "best"), ``memory_workspace`` (bytes),
102+
``batch_size``, ``use_cuda_graph``, and an optional global decoder attached
103+
via ``global_decoder`` plus ``global_decoder_params`` (a nested dict whose
104+
keys follow the schema of the named global decoder).
105+
106+
.. py:function:: cudaq_qec.decoder_param_schema(decoder_name)
107+
108+
Return the registered parameter schema for a decoder as a list of
109+
descriptors (``key``, ``kind``, ``required``, and, for nested sections,
110+
``subschema`` or ``discriminator``), or ``None`` when the decoder has not
111+
registered one.
112+
113+
.. py:function:: cudaq_qec.registered_decoder_schemas()
114+
115+
Names of all decoders (and nested parameter sections) with registered
116+
parameter schemas.
117+
118+
.. py:function:: cudaq_qec.decoder_config_json_schema()
119+
120+
Return a JSON Schema (draft 2020-12) document, as a string, that
121+
validates ``multi_decoder_config`` YAML files. Generated from the decoder
122+
parameter schemas registered in this installation (including loaded
123+
third-party decoder plugins), for use with standard tools such as
124+
``check-jsonschema``, the python ``jsonschema`` package, or editor YAML
125+
language servers. Schema validation hooks are not representable in JSON
126+
Schema, so a passing document may still be rejected when parsed.
127+
128+
.. py:method:: decoder_config.validate_custom_args()
129+
130+
Validate ``decoder_custom_args`` against the parameter schema registered
131+
for this decoder ``type``: unknown keys, missing required keys, and the
132+
schema's own validation hook. Raises ``RuntimeError`` on the first
133+
violation. YAML parsing applies the same checks automatically; call this
134+
to vet a configuration built programmatically before using it. Also
135+
available on ``multi_decoder_config`` to validate every decoder at once.
136+
137+
Deprecated Typed Configuration Classes
138+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
139+
140+
The typed configuration classes from earlier releases
141+
(``nv_qldpc_decoder_config``, ``trt_decoder_config``, ``pymatching_config``,
142+
``chromobius_config``, ``multi_error_lut_config``, and the
143+
``qecrt.config``-level ``single_error_lut_config``, ``sliding_window_config``,
144+
and ``srelay_bp_config``) remain available as deprecated compatibility shims.
145+
They emit a ``DeprecationWarning`` on construction and will be removed in a
146+
future release; existing code that builds one and passes it to
147+
``decoder_config.set_decoder_custom_args`` (or assigns it to
148+
``decoder_config.decoder_custom_args``) continues to work unchanged. Note
149+
that *reading* ``decoder_custom_args`` now always returns a plain dict, never
150+
a typed object. New code should assign dicts directly, as shown above.
134151

135152
Configuration Functions
136153
^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)