Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Python] Missing objects. #2343

Open
boschmitt opened this issue Nov 1, 2024 · 0 comments
Open

[Python] Missing objects. #2343

boschmitt opened this issue Nov 1, 2024 · 0 comments

Comments

@boschmitt
Copy link
Collaborator

High-level description

Inside quantum kernels, CUDA-Q accepts various constructs that are not backed by a python objects. For example:

>>> print(cudaq.qubit)
<class 'cudaq.mlir._mlir_libs._quakeDialects.cudaq_runtime.qubit'>
>>> print(cudaq.x)
AttributeError: module 'cudaq' has no attribute 'x'
>>> print(cudaq.h)
AttributeError: module 'cudaq' has no attribute 'h'
>>> print(cudaq.adjoint)
AttributeError: module 'cudaq' has no attribute 'adjoint'
>>> print(cudaq.control)
AttributeError: module 'cudaq' has no attribute 'control'

Note that cudaq.qubit is indeed part of cudaq while the gates, adjoint and control are not.

The lack of such objects complicates the AST bridge ability to handle Call nodes. Currently, visit_Call is a 1300+ lines of code, somewhat redoing the similar work in different points and having to work around the fact that some of these call are to non-existent python objects:

# First let's check for registered C++ kernels
cppDevModNames = []
value = node.func.value
if isinstance(value, ast.Name) and value.id != 'cudaq':
cppDevModNames = [node.func.attr, value.id]
else:
while isinstance(value, ast.Attribute):
cppDevModNames.append(value.attr)
value = value.value
if isinstance(value, ast.Name):
cppDevModNames.append(value.id)
break

# Start by seeing if we have mod1.mod2.mod3...
moduleNames = []
value = node.func.value
while isinstance(value, ast.Attribute):
moduleNames.append(value.attr)
value = value.value
if isinstance(value, ast.Name):
moduleNames.append(value.id)
break

Note that in the second snippet, the code is, somewhat, not doing what the comment is suggesting. The way it handles mod1.mod2.mod3.<...> is by ignoring the first two, thus populating moduleNames with ['mod3', ...], and using the result as a base to look for registered kernels.

Why it matters?

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++ module that gets imported into a python module.

When the bridge is analyzing calls, it might be that one is to a bound device kernel. In such cases, there is a need to figure it out what is the real path of the module where function is found because the kernel gets registered with the real module path in the name. If every construct inside a kernel was backed by a python object, then we would be able to uniformly check for the real module path for all calls and handle possible aliases (related to #2341).

Also, I don't use a python language server but I assume this also make them complain about calls to non-existent functions/objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant