Required prerequisites
Describe the bug
Hi, and thank you for all the work on CUDA-Q! I came across a crash that I don't think has been reported yet, though please let me know if I missed an existing issue.
In a Python kernel, calling cudaq.adjoint(k, ...) followed by cudaq.control(k, ...) on the same kernel aborts the process with a failed assertion when the kernel argument is a compile-time constant, either a literal or a local variable:
/usr/include/c++/12/bits/stl_vector.h:1125: ... std::vector<mlir::BlockArgument>::operator[](size_type) ...: Assertion '__n < this->size()' failed.
Aborted (exit code 134)
From what I could narrow down:
| Order in the caller |
Argument passed |
Result |
adjoint, then control |
literal (1.5) |
crash |
adjoint, then control |
local variable (theta = 1.5) |
crash |
adjoint, then control |
caller's kernel argument (theta: float) |
works |
control, then adjoint |
literal (1.5) |
works |
| each on its own |
literal |
works |
The equivalent C++ program, compiled with nvq++, runs fine, so this seems specific to the Python frontend.
Steps to reproduce the bug
import cudaq
@cudaq.kernel
def my_func(q: cudaq.qubit, theta: float):
ry(theta, q)
rz(theta, q)
@cudaq.kernel
def kernel():
ancilla = cudaq.qubit()
q = cudaq.qubit()
h(ancilla)
cudaq.adjoint(my_func, q, 1.5)
cudaq.control(my_func, ancilla, q, 1.5)
cudaq.sample(kernel).dump() # aborts with the assertion above
Swapping the last two lines of kernel, or making theta an argument of kernel and passing it through, makes it run correctly.
For reference, test_control_then_adjoint in python/tests/kernel/test_kernel_features.py covers the control-then-adjoint order with a runtime argument. I couldn't find a test for the reverse order with a constant argument.
Expected behavior
The kernel compiles and samples normally, as it does in C++ and with the reversed call order. For example: { 00:~250 01:~250 10:~500 }.
Is this a regression? If it is, put the last known working version (or commit) here.
Not sure. A related adjoint/control combination was fixed in #1871 (#1979, #1993), but I haven't found a version where this exact case worked.
Environment
- CUDA-Q version: 0.16.0 (pip wheel), and the nightly image
nvcr.io/nvidia/nightly/cuda-quantum:cu12-latest at commit 934e7065
- Python version: 3.12
- C++ compiler: N/A (the C++ equivalent built with
nvq++ from the same nightly image works)
- Operating system: Ubuntu on WSL2 (x86_64) for the wheel; the nightly container for the nightly build
Suggestions
I haven't dug into the root cause yet. Since it only fails for constant arguments and only when adjoint comes first, I wonder whether the argument synthesis or constant propagation for the .adj variant is changing the callee's signature before the .ctrl variant is generated. That's only a guess, though. I'd be happy to contribute a failing regression test, or to help investigate further, if that would be useful.
Required prerequisites
Describe the bug
Hi, and thank you for all the work on CUDA-Q! I came across a crash that I don't think has been reported yet, though please let me know if I missed an existing issue.
In a Python kernel, calling
cudaq.adjoint(k, ...)followed bycudaq.control(k, ...)on the same kernel aborts the process with a failed assertion when the kernel argument is a compile-time constant, either a literal or a local variable:From what I could narrow down:
adjoint, thencontrol1.5)adjoint, thencontroltheta = 1.5)adjoint, thencontroltheta: float)control, thenadjoint1.5)The equivalent C++ program, compiled with
nvq++, runs fine, so this seems specific to the Python frontend.Steps to reproduce the bug
Swapping the last two lines of
kernel, or makingthetaan argument ofkerneland passing it through, makes it run correctly.For reference,
test_control_then_adjointinpython/tests/kernel/test_kernel_features.pycovers the control-then-adjoint order with a runtime argument. I couldn't find a test for the reverse order with a constant argument.Expected behavior
The kernel compiles and samples normally, as it does in C++ and with the reversed call order. For example:
{ 00:~250 01:~250 10:~500 }.Is this a regression? If it is, put the last known working version (or commit) here.
Not sure. A related adjoint/control combination was fixed in #1871 (#1979, #1993), but I haven't found a version where this exact case worked.
Environment
nvcr.io/nvidia/nightly/cuda-quantum:cu12-latestat commit934e7065nvq++from the same nightly image works)Suggestions
I haven't dug into the root cause yet. Since it only fails for constant arguments and only when
adjointcomes first, I wonder whether the argument synthesis or constant propagation for the.adjvariant is changing the callee's signature before the.ctrlvariant is generated. That's only a guess, though. I'd be happy to contribute a failing regression test, or to help investigate further, if that would be useful.