You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consult the security policy. If reporting a security vulnerability, do not report the bug using this form. Use the process described in the policy to report the issue.
Make sure you've read the documentation. Your issue may be addressed there.
Search the issue tracker to verify that this hasn't already been reported. +1 or comment there if it has.
If possible, make a PR with a failing test to give us a starting point to work on!
Describe the bug
With python device kernel interoperability, users can write quantum kernels in C++ and bind them to python. In such cases, the common pattern is to have a C++ python module that gets imported into a python module.
For example, if we have a python package named foo to which we add C++ extensions using pybind11. The common pattern is to end up with a with a module named _cppfoo (or whaterver). Then, we import all of its symbols to foo:
foo/__init__.py:
from ._cppfoo import *
Now, if _cppfoo contains a device kernel named bar, then users are able to access it using foo.bar(...). This, however, is not the real path of bar, the real path is foo._cppfoo.bar(..).
Currently, device kernels get registered with their real path name, and thus, when the python AST bridge parse another kernel that uses foo.bar(...), it needs to figure it out if that is its real path or not. This process is not working correctly when there is this extra level of indirection.
Steps to reproduce the bug
Applying the following patch to the repo will create a test case that fails:
diff --git a/python/tests/interop/qlib.py b/python/tests/interop/qlib.py
new file mode 100644
index 000000000..cea8b1861
--- /dev/null+++ b/python/tests/interop/qlib.py@@ -0,0 +1,10 @@+# ============================================================================ #+# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. #+# All rights reserved. #+# #+# This source code and the accompanying materials are made available under #+# the terms of the Apache License 2.0 which accompanies this distribution. #+# ============================================================================ #++from cudaq_test_cpp_algo import *+diff --git a/python/tests/interop/test_interop.py b/python/tests/interop/test_interop.py
index 78d46e576..0d52d8e4e 100644
--- a/python/tests/interop/test_interop.py+++ b/python/tests/interop/test_interop.py@@ -222,6 +222,27 @@ def test_cpp_kernel_from_python_2():
callUCCSD()
+def test_cpp_kernel_from_python_3():++ import qlib++ # Sanity checks+ print(qlib.qstd.qft)+ print(qlib.qstd.another)++ @cudaq.kernel+ def callQftAndAnother():+ q = cudaq.qvector(4)+ qlib.qstd.qft(q)+ h(q)+ qlib.qstd.another(q, 2)++ callQftAndAnother()++ counts = cudaq.sample(callQftAndAnother)+ counts.dump()+ assert len(counts) == 1 and '0010' in counts+
def test_capture():
@cudaq.kernel
def takesCapture(s : int):
@@ -232,4 +253,4 @@ def test_capture():
@cudaq.kernel(verbose=True)
def entry():
takesCapture(spin)
- entry.compile()
\ No newline at end of file
+ entry.compile()
It creates a level of indirection by creating a new module, qlib, importing the symbols from cudaq_test_cpp_algo, and then trying to call the kernels from qlib, e.g., qlib.qstd.qft.
Expected behavior
CUDA-Q should correctly find the kernel.
Is this a regression? If it is, put the last known working version (or commit) here.
Required prerequisites
Describe the bug
With python device kernel interoperability, users can write quantum kernels in C++ and bind them to python. In such cases, the common pattern is to have a C++ python module that gets imported into a python module.
For example, if we have a python package named
foo
to which we add C++ extensions using pybind11. The common pattern is to end up with a with a module named _cppfoo (or whaterver). Then, we import all of its symbols to foo:Now, if
_cppfoo
contains a device kernel named bar, then users are able to access it usingfoo.bar(...)
. This, however, is not the real path ofbar
, the real path isfoo._cppfoo.bar(..)
.Currently, device kernels get registered with their real path name, and thus, when the python AST bridge parse another kernel that uses
foo.bar(...)
, it needs to figure it out if that is its real path or not. This process is not working correctly when there is this extra level of indirection.Steps to reproduce the bug
Applying the following patch to the repo will create a test case that fails:
It creates a level of indirection by creating a new module,
qlib
, importing the symbols fromcudaq_test_cpp_algo
, and then trying to call the kernels fromqlib
, e.g.,qlib.qstd.qft
.Expected behavior
CUDA-Q should correctly find the kernel.
Is this a regression? If it is, put the last known working version (or commit) here.
Not a regression
Environment
Suggestions
No response
The text was updated successfully, but these errors were encountered: