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] Qvector init from state #1713

Conversation

annagrin
Copy link
Collaborator

@annagrin annagrin commented May 24, 2024

Description

Add initialization of qvector from cudaq::State

Details

The changes that allow using cudaq.State in python kernel functions:

  • Add cc.StateType to python bindings

  • Allow arguments of StateType to be passed to kernel functions

  • Made cudaq.from_state fail on incorrect precision data

  • Update ast_bridge.py to create MLIR for initializing qvector from state

  • Support capturing states from python non-kernel code

    • inspired by vector data capture support for qalloc in kernel_builder.py
    • save states in special storage during compilation
    • create a unique MLIR function that takes a state pointer and saves it in a global
    • use the global for accessing the state pointer in the rest of MLIR
    • before execution, run the special functions on storage to save pointers in corresponding globals
    • cleanup the kernel-related state storage after the kernel is executed
  • Convert StateType to ptr<i8> in cudaq::opt::initializeTypeConversions

  • Update QmemRAIIOpRewrite to call a new extern C API on state pointers

    • __quantum__rt__qubit_allocate_array_with_cudaq_state_ptr
  • Implement __quantum__rt__qubit_allocate_array_with_cudaq_state_ptr

    • get a simulation pointer out of the state (use a new class state_helper to access private data)
    • call existing API for allocating qubits from a simulation state pointer
  • Update related intrinsics

    • Implement __nvqpp_cudaq_state_numberOfQubits
    • Remove __nvqpp_cudaq_state_vectorData (to avoid a copy in MLIR)
  • Add tests

    • creating states and passing them as parameters or capture to a kernel function
      • Make sure cudaq.from_state fails on incorrect precision data
    • getting a state from one kernel and passing it to another
  • See python usage examples in [RFC] [Language] Quantum allocation with state initialization #1086

Towards:

@annagrin annagrin marked this pull request as draft May 24, 2024 18:39
@annagrin annagrin changed the title Qvector init from state update [Python] Qvector init from state update May 24, 2024
github-actions bot pushed a commit that referenced this pull request May 24, 2024
github-actions bot pushed a commit that referenced this pull request May 24, 2024
@annagrin annagrin marked this pull request as ready for review May 24, 2024 21:11
@annagrin annagrin changed the title [Python] Qvector init from state update [Python] Qvector init from state May 24, 2024
github-actions bot pushed a commit that referenced this pull request May 24, 2024
python/cudaq/kernel/ast_bridge.py Outdated Show resolved Hide resolved
python/cudaq/kernel/ast_bridge.py Outdated Show resolved Hide resolved
github-actions bot pushed a commit that referenced this pull request May 24, 2024
github-actions bot pushed a commit that referenced this pull request May 24, 2024
Copy link
Collaborator

@1tnguyen 1tnguyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@annagrin annagrin enabled auto-merge (squash) May 28, 2024 21:25
@annagrin annagrin merged commit b5ce9a7 into NVIDIA:experimental/stateHandling May 28, 2024
112 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators May 28, 2024
Comment on lines +123 to +125
auto *ctx = eleTy.getContext();
auto eTy = cudaq::opt::factory::getCharType(ctx);
return cudaq::opt::factory::getPointerType(eTy);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplified to just:

return cudaq::opt::factory::getPointerType(eleTy.getContext());

On the other hand, we don't use the eleTy, so we could erase this function and just use getPointerType at the call site.

Comment on lines +2036 to +2038
if (isa<NoneType>(eleTy))
return factory::getPointerType(type.getContext());

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't the recursion handle this? The recursive call on line 2035 ought to handle pointers to pointers.

@@ -434,8 +434,10 @@ class GenerateKernelExecution
hasTrailingData = true;
continue;
}
if (isa<cudaq::cc::PointerType>(currEleTy))
if (isa<cudaq::cc::PointerType>(currEleTy) &&
!isStatePointerType(currEleTy)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: don't need braces.

@@ -933,6 +935,13 @@ class GenerateKernelExecution
builder.create<cudaq::cc::StoreOp>(loc, endPtr, sret2);
}

static bool isStatePointerType(mlir::Type ty) {
if (auto ptrTy = dyn_cast<cudaq::cc::PointerType>(ty)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no braces

Comment on lines +953 to +954
return isa<cudaq::cc::PointerType>(i.getType()) &&
!isStatePointerType(i.getType());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get this one. We're dropping hidden arguments. Why would a cudaq::state* appear as a this or sret? Do we have an example?

@@ -1207,8 +1217,9 @@ class GenerateKernelExecution
hasTrailingData = true;
continue;
}
if (isa<cudaq::cc::PointerType>(inTy))
if (isa<cudaq::cc::PointerType>(inTy) && !isStatePointerType(inTy))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look correct. We cannot pass a cudaq::state* as a pointer-free value.

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

Successfully merging this pull request may close these issues.

None yet

3 participants