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

State synthesis for quantum devices #2291

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

annagrin
Copy link
Collaborator

@annagrin annagrin commented Oct 17, 2024

Synthesize state pointer for quantum devices:

SimulationState:

  • Add hasData API that returns true iff the vector data exists on the state or can be computed.
  • Add getKernelInfo API that returns optional kernel name and a list of arguments for the kernel that generated the state.

QuantumState:

  • Add QuantumState class that inherits from simulation state and keeps kernel information only.

ArgumentConversion:

  • Substitute state pointer argument with call __nvqpp_cudaq_state_get("callee.modified_N") instruction.
  • Add a modified callee function that is created from the callee code and returns its veq allocations.
  • Add a list of converters for the callees in ArgumentConverter.
  • Generate substitutions for modified callee functions, recursively.

Passes:

  • Add a post-synthesis StateInitialization pass that replaces quake.init_state instructions by a call to callee.modified_N()
  • Add a post-sysnthesis StateValidation pass that validates the syntheszed MLIR for quantum hardware.
    • Removes any runtime function definitions from the module
    • Makes sure there are no state-related calls and quake.init_state instructions in MLIR.

Synthesis:

  • Collect all substitutions for the call tree at the synthesis time for quantum devices.

Tests:

  • Add quake tests for StateInitialization pass
  • Add quake tests for ArgumentSynthesis pass with state pointer substitutions
  • Add targettests/execution/qvector_init_from_state.cpp test that runs for various quantum backends emulation

Notes

Currently state pointer synthesis is only supported for kernels implemented as operator() inside a struct.

TODO (in subsequent PRs)

  • python tests for quantum platforms
  • cpp tests for quantum backend integration
  • Investigate using cudaq::qkernel to support c-like kernels in state pointer synthesis

Requires: #2354

bmhowe23 and others added 4 commits October 17, 2024 14:33
I, Ben Howe <[email protected]>, hereby add my Signed-off-by to this commit: 86681ef

Signed-off-by: Ben Howe <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
@annagrin annagrin force-pushed the quantum-device-state branch from 4517712 to 7969a75 Compare October 17, 2024 21:38
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 👍

Copy link
Collaborator

@schweitzpgi schweitzpgi left a comment

Choose a reason for hiding this comment

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

Still reviewing...

include/cudaq/Optimizer/Builder/Intrinsics.h Outdated Show resolved Hide resolved
include/cudaq/Optimizer/Transforms/Passes.td Outdated Show resolved Hide resolved
include/cudaq/Optimizer/Transforms/Passes.td Outdated Show resolved Hide resolved
include/cudaq/Optimizer/Transforms/Passes.td Outdated Show resolved Hide resolved
include/cudaq/Optimizer/Transforms/Passes.td Outdated Show resolved Hide resolved
Copy link
Collaborator

@schweitzpgi schweitzpgi left a comment

Choose a reason for hiding this comment

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

Still reviewing...

lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
/// %5 = quake.init_state %4, %2 : (!quake.veq<?>, !cc.ptr<!cc.state>) -> !quake.veq<?>
/// ───────────────────────────────────────────
/// ...
/// %5 = call @callee.modified_0() : () -> !quake.veq<?>
Copy link
Collaborator

Choose a reason for hiding this comment

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

This violates the semantics of Quake: all quantum memory allocations happen at the top-level and cannot be returned from other kernels.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is only temporary and does not seem to break anything until the Inlining fixes the semantics... But returning allocations (instead of passing them as a parameter) is much easier to implement. Let me know if it is a showstopper, I can revisit passing allocations as a parameter.

Copy link
Collaborator

@schweitzpgi schweitzpgi Oct 21, 2024

Choose a reason for hiding this comment

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

Well, it's a bug even if it "works" for now, so I think we ought to deal with it now.

I don't see why returning is any easier. Updating the "init kernel" from something like

func.func @init_kernel() {
   %0 = quake.alloca !quake.veq<4>
   ...
}

to a "modified init kernel" of

func.func @init_kernel.modified(%0 : !quake.veq<4>) {
   ...
}

is easy enough.

Also, if we pass in the allocated qubits, we don't have to erase them at the top-level or rely on inlining to get things normalized, etc.

Copy link
Collaborator Author

@annagrin annagrin Oct 21, 2024

Choose a reason for hiding this comment

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

The callee can have multiple allocations, so I would need to know how to split the qvector to pass to those allocations. Not sure how to do that yet (process the function to get allocation sizes first? The size can be a result of a _getNumberOfQubits call though...)

I need time to try changing to passing allocations as parameters, probably won't fit into this release, unless I only support a trivial case of one allocation in a callee kernel. Do you think this part can be done in a later PR?

lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateInitialization.cpp Outdated Show resolved Hide resolved
lib/Optimizer/Transforms/StateValidation.cpp Outdated Show resolved Hide resolved
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
Signed-off-by: Anna Gringauze <[email protected]>
@annagrin annagrin marked this pull request as draft November 5, 2024 18:03
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

Successfully merging this pull request may close these issues.

4 participants