Skip to content

[Analysis] Create simple analysis pass to group unitary operations#4611

Open
cabreraam wants to merge 2 commits into
NVIDIA:mainfrom
cabreraam:group-unitaries
Open

[Analysis] Create simple analysis pass to group unitary operations#4611
cabreraam wants to merge 2 commits into
NVIDIA:mainfrom
cabreraam:group-unitaries

Conversation

@cabreraam
Copy link
Copy Markdown
Collaborator

Overview

This PR aims to create a simple analysis pass to group unitary operations. This is an intermediary step for more complmex groupings (e.g., coalescing groups) and downstream passes (consuming the grouping to inform lowering to hardware). The analysis pass creates a vector of UnitaryOpGroup structs that, where each struct contains, in part, a vector of all the unitary ops grouped in a given pass.

Implementation

For now, this pass groups unbroken sequences of unitary operations, i.e., ops that contain the QuantumGate type but are not quake.reset ops.

The entry point for the analysis are func ops. With the func op region as the starting point, we recursively search regions to find groups of unitary operations. To account for nested regions within ops (e.g., cc.if), we examine all ops in a given block, and then we check each op to see if there are nested regions that require examining.

The testing of this pass is driven through cudaq-opt, and the pass is only registered if the CUDAQ_BUILD_TESTS CMake variable is supplied. A test pass is implemented to show how one might interpret the results of the unitary op group analysis pass.

Adding infrastructure for Analysis Passes

Currently, there is no formal infrastructure for pure analysis passes in the code base; while there are analysis passes that exist in CUDA-Q, there are one off analyses that are tied to a transformation pass. Taking inspiration from the mlir and flang LLVM subproject directory hierarchies, we introduce the same structure here when implementing this simple unitary op grouping. Namely:

  • A new directory called cudaq/include/cudaq/Optimizer/Analysis is created
  • A new directory called cudaq/lib/cudaq/Optimizer/Analysis is created
  • A new directory called cudaq/test/lib/Analysis is created
    • lit.cfg.py is updated to ignore files in the cudaq/test/lib directory

Signed-off-by: Anthony <antcabrera@nvidia.com>
Signed-off-by: Anthony <antcabrera@nvidia.com>
@github-actions
Copy link
Copy Markdown

CI Summary (push) — ✅ passed

Run #26491110486 · ✅ 6 · ⏩ 7 · ❌ 0 · ⛔ 0

Top-level jobs (13)
Job Result
binaries ⏩ skipped
build_and_test ✅ success
config_devdeps ✅ success
config_source_build ⏩ skipped
config_wheeldeps ✅ success
devdeps ✅ success
docker_image ⏩ skipped
gen_code_coverage ⏩ skipped
metadata ✅ success
python_metapackages ⏩ skipped
python_wheels ⏩ skipped
source_build ⏩ skipped
wheeldeps ✅ success
⏩ Skipped jobs (7) — intentionally skipped on PR builds; run on merge_group / workflow_dispatch
Job
binaries
config_source_build
docker_image
gen_code_coverage
python_metapackages
python_wheels
source_build
All sub-jobs (42) — every matrix leg, with links
Job Status Link
Build and test (amd64, gcc12, openmpi) / Dev environment (Debug) ✅ success view
Build and test (amd64, gcc12, openmpi) / Dev environment (Python) ✅ success view
Build and test (amd64, llvm, openmpi) / Dev environment (Debug) ✅ success view
Build and test (amd64, llvm, openmpi) / Dev environment (Python) ✅ success view
Build and test (arm64, llvm, openmpi) / Dev environment (Debug) ✅ success view
Build and test (arm64, llvm, openmpi) / Dev environment (Python) ✅ success view
CI Summary ❔ in_progress view
Configure build (devdeps) ✅ success view
Configure build (source_build) ⏩ skipped view
Configure build (wheeldeps) ✅ success view
Create CUDA Quantum installer ⏩ skipped view
Create Docker images ⏩ skipped view
Create Python metapackages ⏩ skipped view
Create Python wheels ⏩ skipped view
Gen code coverage ⏩ skipped view
Load dependencies (amd64, gcc12) / Caching ✅ success view
Load dependencies (amd64, gcc12) / Finalize ✅ success view
Load dependencies (amd64, gcc12) / Metadata ✅ success view
Load dependencies (amd64, llvm) / Caching ✅ success view
Load dependencies (amd64, llvm) / Finalize ✅ success view
Load dependencies (amd64, llvm) / Metadata ✅ success view
Load dependencies (arm64, gcc12) / Caching ✅ success view
Load dependencies (arm64, gcc12) / Finalize ✅ success view
Load dependencies (arm64, gcc12) / Metadata ✅ success view
Load dependencies (arm64, llvm) / Caching ✅ success view
Load dependencies (arm64, llvm) / Finalize ✅ success view
Load dependencies (arm64, llvm) / Metadata ✅ success view
Load source build cache ⏩ skipped view
Load wheel dependencies (amd64, 12.6) / Caching ✅ success view
Load wheel dependencies (amd64, 12.6) / Finalize ✅ success view
Load wheel dependencies (amd64, 12.6) / Metadata ✅ success view
Load wheel dependencies (amd64, 13.0) / Caching ✅ success view
Load wheel dependencies (amd64, 13.0) / Finalize ✅ success view
Load wheel dependencies (amd64, 13.0) / Metadata ✅ success view
Load wheel dependencies (arm64, 12.6) / Caching ✅ success view
Load wheel dependencies (arm64, 12.6) / Finalize ✅ success view
Load wheel dependencies (arm64, 12.6) / Metadata ✅ success view
Load wheel dependencies (arm64, 13.0) / Caching ✅ success view
Load wheel dependencies (arm64, 13.0) / Finalize ✅ success view
Load wheel dependencies (arm64, 13.0) / Metadata ✅ success view
Prepare cache clean-up ❔ in_progress view
Retrieve PR info ✅ success view
✅ Required checks (6/6) — declared in .github/required-checks.yml for push
Required check Status Link
Build and test (amd64, llvm, openmpi) / Dev environment (Debug) ✅ success view
Build and test (amd64, llvm, openmpi) / Dev environment (Python) ✅ success view
Build and test (arm64, llvm, openmpi) / Dev environment (Debug) ✅ success view
Build and test (arm64, llvm, openmpi) / Dev environment (Python) ✅ success view
Build and test (amd64, gcc12, openmpi) / Dev environment (Debug) ✅ success view
Build and test (amd64, gcc12, openmpi) / Dev environment (Python) ✅ success view

Copy link
Copy Markdown
Collaborator

@taalexander taalexander left a comment

Choose a reason for hiding this comment

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

Hi @cabreraam, thanks for putting this together. I was wondering if you could frame this analysis in how it would eventually be used? I can imagine either:

  1. Circuit outlining to a canonical IR form
  2. Circuit lowering to a hardware form

In both cases I imagine the analysis may only be required once or twice. That being said if I were to use it for the above I would expect that I would need methods to interact with the analysis as I was writing the transformation pass. Something like:

  • const UnitaryOpGroup *getGroupContaining(Operation *op) const;
  • ArrayRef<UnitaryOpGroup> getGroupsIn(Block *block) const;
  • bool inSameGroup(Operation *a, Operation *b) const;

Comment on lines +24 to +26
static bool isUnitaryOp(Operation *op) {
return op->hasTrait<cudaq::QuantumGate>() && !isa<cudaq::quake::ResetOp>(op);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A reset is not unitary.

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.

2 participants