Skip to content

Commit dfd4983

Browse files
anjburkhalatepradnyacursoragent
authored
Update cudaq and nanobind versions (#545)
- Updates pinned version of cudaq. - Updates nanobind by reverting previous commits (62936b1 7488c8c a0724f6), except for 7488c8c change to `cmake/Modules/CUDA-QX.cmake`. Wheel build to confirm issue is fixed: https://github.com/NVIDIA/cudaqx/actions/runs/25936612350 --------- Signed-off-by: Pradnya Khalate <pkhalate@nvidia.com> Signed-off-by: Angela Burton <angelab@nvidia.com> Co-authored-by: Pradnya Khalate <pkhalate@nvidia.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Pradnya Khalate <148914294+khalatepradnya@users.noreply.github.com>
1 parent 9c16245 commit dfd4983

15 files changed

Lines changed: 145 additions & 115 deletions

File tree

.cudaq_realtime_version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"cudaq_realtime": {
33
"repository": "NVIDIA/cuda-quantum",
4-
"ref": "cd88025b3d1beb02ca2703de70a583e647af10fb"
4+
"ref": "053480dda0413c219c224d42313aa14d7a17a7fe"
55
}
66
}

.cudaq_version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"cudaq": {
33
"repository": "NVIDIA/cuda-quantum",
4-
"ref": "cd88025b3d1beb02ca2703de70a583e647af10fb"
4+
"ref": "053480dda0413c219c224d42313aa14d7a17a7fe"
55
}
66
}

docs/sphinx/examples/qec/cpp/real_time_complete.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ __qpu__ int64_t qec_circuit() {
122122
cudaq::x(data[i]);
123123
}
124124

125-
return cudaq::to_integer(mz(data));
125+
return cudaq::to_integer(cudaq::to_bools(mz(data)));
126126
}
127127
// [End QEC Circuit]
128128

docs/sphinx/examples/qec/python/real_time_complete.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def prep0(logical: qec.patch):
3131

3232
# Measure ZZ stabilizers for 3-qubit repetition code
3333
@cudaq.kernel
34-
def measure_stabilizers(logical: qec.patch) -> list[bool]:
34+
def measure_stabilizers(logical: qec.patch) -> list[cudaq.measure_handle]:
3535
for i in range(logical.ancz.size()):
3636
reset(logical.ancz[i])
3737

@@ -70,7 +70,7 @@ def qec_circuit() -> int:
7070
for i in range(3):
7171
x(data[i])
7272

73-
return cudaq.to_integer(mz(data))
73+
return cudaq.to_integer(cudaq.to_bools(mz(data)))
7474

7575

7676
# [End QEC Circuit]

libs/qec/include/cudaq/qec/realtime/decoding.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ enqueue_syndromes(std::uint64_t decoder_id,
3434
const std::vector<cudaq::measure_result> &syndromes,
3535
std::uint64_t tag = 0);
3636

37+
/// @brief Test-only entry point for enqueueing pre-discriminated syndrome
38+
/// bits (e.g., raw syndromes replayed from a saved file). Production code
39+
/// must use `enqueue_syndromes`. This entry point exists because raw bits
40+
/// read from disk have no measurement-event identity to preserve, so the
41+
/// `vector<measure_result>` API is the wrong shape for them.
42+
/// @param decoder_id The ID of the decoder to use.
43+
/// @param syndromes Pre-discriminated syndrome bits.
44+
/// @param tag The tag to use for the syndrome (currently useful for logging
45+
/// only)
46+
__qpu__ void enqueue_syndromes_test(std::uint64_t decoder_id,
47+
const std::vector<bool> &syndromes,
48+
std::uint64_t tag = 0);
49+
3750
/// @brief Get the corrections for a given decoder.
3851
/// @param decoder_id The ID of the decoder to use.
3952
/// @param return_size The number of bits to return (in bits). This is expected

libs/qec/lib/realtime/quantinuum/quantinuum_device.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ enqueue_syndromes(std::uint64_t decoder_id,
2121
const std::vector<cudaq::measure_result> &syndromes,
2222
std::uint64_t tag) {
2323
uint64_t syndrome_size = syndromes.size();
24+
// Discriminate first, then bit-pack into the `uint64` wire format.
25+
uint64_t syndrome = cudaq::to_integer(cudaq::to_bools(syndromes));
26+
cudaq::device_call(enqueue_syndromes_ui64, decoder_id, syndrome_size,
27+
syndrome, tag);
28+
}
29+
30+
__qpu__ void enqueue_syndromes_test(std::uint64_t decoder_id,
31+
const std::vector<bool> &syndromes,
32+
std::uint64_t tag) {
33+
uint64_t syndrome_size = syndromes.size();
2434
uint64_t syndrome = cudaq::to_integer(syndromes);
2535
cudaq::device_call(enqueue_syndromes_ui64, decoder_id, syndrome_size,
2636
syndrome, tag);

libs/qec/lib/realtime/simulation/simulation_device.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
// exact signature (other than converting vectors to spans), there will be no
2020
// errors or warnings, other than bad crashes.
2121
extern "C" __attribute__((visibility("default"))) void
22-
simulation_enqueue_syndromes(
23-
std::uint64_t decoder_id,
24-
const std::vector<cudaq::measure_result> &syndromes, std::uint64_t tag);
22+
simulation_enqueue_syndromes(std::uint64_t decoder_id,
23+
const std::vector<bool> &syndromes,
24+
std::uint64_t tag);
2525

2626
extern "C" __attribute__((visibility("default"))) void
2727
simulation_get_corrections(std::uint64_t decoder_id,
@@ -33,6 +33,15 @@ __qpu__ void
3333
enqueue_syndromes(std::uint64_t decoder_id,
3434
const std::vector<cudaq::measure_result> &syndromes,
3535
std::uint64_t tag) {
36+
// The host trampoline takes a bit-typed span (see WARNING above), so
37+
// discriminate the handles before crossing the boundary.
38+
cudaq::device_call(simulation_enqueue_syndromes, decoder_id,
39+
cudaq::to_bools(syndromes), tag);
40+
}
41+
42+
__qpu__ void enqueue_syndromes_test(std::uint64_t decoder_id,
43+
const std::vector<bool> &syndromes,
44+
std::uint64_t tag) {
3645
cudaq::device_call(simulation_enqueue_syndromes, decoder_id, syndromes, tag);
3746
}
3847

libs/qec/python/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ if(NOT COMMAND nanobind_add_module)
1717
FetchContent_Declare(
1818
nanobind
1919
GIT_REPOSITORY https://github.com/wjakob/nanobind
20-
GIT_TAG v2.9.2
20+
GIT_TAG v2.12.0
2121
EXCLUDE_FROM_ALL
2222
)
2323
FetchContent_MakeAvailable(nanobind)

libs/qec/python/bindings/py_decoder.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,6 @@ void bindDecoder(nb::module_ &mod) {
105105
? nb::cast<nb::module_>(mod.attr("qecrt"))
106106
: mod.def_submodule("qecrt");
107107

108-
// Workaround for nanobind v2.9.2: `def_rw` on a `std::optional<T>` field
109-
// does not implicitly allow Python `None` for the setter (that behavior was
110-
// added in v2.12.0 via PR #1262). Passing this annotation makes the setter
111-
// accept None and store `std::nullopt`. Remove once nanobind is bumped to
112-
// >=2.12.0.
113-
const auto setter_accepts_none = nb::for_setter(nb::arg("value").none());
114-
115108
nb::class_<decoder_result>(qecmod, "DecoderResult", R"pbdoc(
116109
A class representing the results of a quantum error correction decoding operation.
117110
@@ -135,8 +128,7 @@ void bindDecoder(nb::module_ &mod) {
135128
the original quantum state. The format depends on the specific decoder
136129
implementation.
137130
)pbdoc")
138-
.def_rw("opt_results", &decoder_result::opt_results, setter_accepts_none,
139-
R"pbdoc(
131+
.def_rw("opt_results", &decoder_result::opt_results, R"pbdoc(
140132
Optional additional results from the decoder stored in a heterogeneous map.
141133
142134
This field may be empty if no additional results are available.
@@ -741,10 +733,23 @@ void bindDecoder(nb::module_ &mod) {
741733
(error_msg ? std::string(error_msg) : "unknown error.")));
742734
}
743735

744-
// List of `init_func` names to call for decoder registration
736+
// List of `init_func` names to call for decoder registration.
737+
//
738+
// The `enqueue_syndromes` mangled string encodes the public API's
739+
// parameter type. Under CUDA-Q alias `using measure_result =
740+
// measure_handle;`, C++ mangling resolves the typedef to its underlying
741+
// type, so `INS_14measure_handleESaIS3_EE` is the inner-vector mangling for
742+
// `std::vector<cudaq::measure_handle>`. If CUDA-Q ever renames the
743+
// underlying handle type or changes the alias direction, this string must
744+
// be re-derived from `nm` on the per-target device .o.
745+
//
746+
// `enqueue_syndromes_test` is the bool-typed counterpart and stays bound
747+
// to `INS_t6vectorIbSaIbEE`; the Python frontend hands it pre-discriminated
748+
// bits via `cudaq.to_bools(...)`.
745749
// clang-format off
746750
static const std::vector<std::string> initFuncNames = {
747-
"function_enqueue_syndromes._ZN5cudaq3qec8decoding17enqueue_syndromesEmRKSt6vectorIbSaIbEEm.init_func",
751+
"function_enqueue_syndromes._ZN5cudaq3qec8decoding17enqueue_syndromesEmRKSt6vectorINS_14measure_handleESaIS3_EEm.init_func",
752+
"function_enqueue_syndromes_test._ZN5cudaq3qec8decoding22enqueue_syndromes_testEmRKSt6vectorIbSaIbEEm.init_func",
748753
"function_get_corrections._ZN5cudaq3qec8decoding15get_correctionsEmmb.init_func",
749754
"function_reset_decoder._ZN5cudaq3qec8decoding13reset_decoderEm.init_func"};
750755
// clang-format on

libs/qec/python/bindings/py_decoding.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ void bindDecoding(nb::module_ &mod) {
5555
- syndromes: A vector of syndrome bits (0 or 1).
5656
- tag: An optional tag for the enqueue operation.
5757
)pbdoc");
58+
// Mirrors the C++ `enqueue_syndromes_test(uint64_t, vector<bool>, uint64_t)`
59+
// entry point. The Python device kernel must pre-discriminate any
60+
// `list[measure_handle]` via `cudaq.to_bools(...)` before the call. Used by
61+
// app examples that already own bool-typed syndrome bits (file replay or
62+
// explicit kernel-side discrimination) where the production
63+
// `enqueue_syndromes(vector<measure_result>)` shape is the wrong fit.
64+
qecSubMod.def(
65+
"enqueue_syndromes_test",
66+
[](std::uint64_t, std::vector<bool>, std::uint64_t) {},
67+
R"pbdoc(Test-only entry point for enqueueing pre-discriminated syndrome
68+
bits. Production code should use `enqueue_syndromes` instead.
69+
Parameters
70+
- decoder_id: The ID of the decoder.
71+
- syndromes: A vector of syndrome bits (0 or 1).
72+
- tag: An optional tag for the enqueue operation.
73+
)pbdoc");
5874
qecSubMod.def(
5975
"get_corrections", [](std::uint64_t, std::uint64_t, bool) {},
6076
R"pbdoc(Get the corrections from the decoder.
@@ -72,6 +88,10 @@ void bindDecoding(nb::module_ &mod) {
7288
qecModName, "enqueue_syndromes",
7389
cudaq::python::getMangledArgsString<std::uint64_t, std::vector<bool>,
7490
std::uint64_t>());
91+
cudaq::python::registerDeviceKernel(
92+
qecModName, "enqueue_syndromes_test",
93+
cudaq::python::getMangledArgsString<std::uint64_t, std::vector<bool>,
94+
std::uint64_t>());
7595
cudaq::python::registerDeviceKernel(
7696
qecModName, "get_corrections",
7797
cudaq::python::getMangledArgsString<std::uint64_t, std::uint64_t,

0 commit comments

Comments
 (0)