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

Add Moment.from_ops to more efficiently construct moments #6078

Merged
merged 5 commits into from
Apr 25, 2023

Conversation

maffoo
Copy link
Contributor

@maffoo maffoo commented Apr 24, 2023

This adds a new classmethod cirq.Moment.from_ops for constructing a moment from operations without calling flatten_to_ops. This can save a significant amount of time in workloads that construct a lot of circuits. For example, in one internal benchmark we spend almost 3% of the total runtime in the cirq.Moment construct (20s out of 676s total).

This also adds functions cirq.m and cirq.c as shorthands for cirq.Moment.from_ops and cirq.FrozenCircuit.from_moments, repsectively. These are similar to the cirq.q helper for constructing qubit types (#5181) while trying to guide users to use cirq in the most performant way: avoiding the OP_TREE overhead associated with the default moment and circuit constructors, and preferring FrozenCircuit which is immutable and so can cache computed properties of the circuit. These single-letter aliases may be more controversial, but I thought I'd at least propose them. They could also be split out from this PR because I think cirq.Moment.from_ops is useful even without the helper functions.

@maffoo maffoo requested review from a team, vtomole and cduck as code owners April 24, 2023 17:51
@maffoo maffoo requested a review from pavoljuhas April 24, 2023 17:51
@tanujkhattar tanujkhattar self-assigned this Apr 24, 2023
@tanujkhattar tanujkhattar self-requested a review April 24, 2023 17:54
@mpharrigan
Copy link
Collaborator

+1 from ops. I've hacked in my own constructor in the past for performance reasons; would be nice to have this.

The single letter things seem not very readable. Even if I grant that you can tell cirq.m(...) is creating a moment, I wouldn't guess that it is the more strict ops-only version. I would probably guess the opposite: shortcut is for general purpose and spelling things out gives you general behavior.

@dstrain115
Copy link
Collaborator

Agree with Matt. I think the from_ops looks fine to me, but I don't think we should include the one-letter short-hand. It's too ambiguous and having the short-hand bypass validation seems risky.

@tanujkhattar
Copy link
Collaborator

tanujkhattar commented Apr 24, 2023

+1 to everything said above by Doug and Matt.

If you want the shorthand to bypass validation, I'm fine with cirq.m(*ops, flatten=False); though the character savings are marginal at this point.

@mpharrigan
Copy link
Collaborator

cc = CirqVerbatimBuilder()

circuit = cc.c([
  cc.m([cirq.H]),
  cc.m(ops),
])
c = CirqVerbatimBuilderWithOperatorOverrides()

# use `__call__` and `__item__`
circuit = c([
  c[cirq.H, cirq.Z],
  c[ops]
])

@maffoo maffoo force-pushed the u/maffoo/moment-from-ops branch from 40a8e3a to 72ed1eb Compare April 24, 2023 21:16
@maffoo
Copy link
Contributor Author

maffoo commented Apr 24, 2023

Thanks for the comments, everyone. I've stripped out the cirq.c and cirq.m helpers and just kept cirq.Moment.from_ops. PTAL.

@maffoo
Copy link
Contributor Author

maffoo commented Apr 24, 2023

Even if I grant that you can tell cirq.m(...) is creating a moment, I wouldn't guess that it is the more strict ops-only version. I would probably guess the opposite: shortcut is for general purpose and spelling things out gives you general behavior.

I agree with this in principle. Unfortunately we tried to cram a lot much flexibility into the constructors of basic data structures like Moment and Circuit, rather than putting the flexibility into helpers, so we pay a lot of extra cost whenever we construct these objects. I think it would be nice if we can build a better set of "default" APIs that are more strictly typed and avoid a lot of validation overhead, but maybe we can continue to explore this outside of cirq core like with the builder you showed.

@@ -80,17 +81,26 @@ class Moment:
are no such operations, returns an empty Moment.
"""

def __init__(self, *contents: 'cirq.OP_TREE') -> None:
def __init__(self, *contents: 'cirq.OP_TREE', _flatten_contents: bool = True) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we update the serialization to also include this flag? If not, deserialization would still be inefficient even if the serialized list of operations is flat.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea. Done.

@mpharrigan
Copy link
Collaborator

Unfortunately we tried to cram a lot much flexibility into the constructors of basic data structures

yeah, I likewise agree that we messed up our constructors :/

@CirqBot CirqBot added the size: S 10< lines changed <50 label Apr 25, 2023
@@ -106,6 +116,10 @@ def __init__(self, *contents: 'cirq.OP_TREE') -> None:
self._measurement_key_objs: Optional[FrozenSet['cirq.MeasurementKey']] = None
self._control_keys: Optional[FrozenSet['cirq.MeasurementKey']] = None

@classmethod
def from_ops(cls, *ops: 'cirq.Operation') -> 'cirq.Moment':
Copy link
Collaborator

Choose a reason for hiding this comment

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

doc that this doesn't do any flattening

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added docstring.

@maffoo maffoo changed the title Add utility methods for efficiently constructing circuits and moments Add Moment.from_ops to more efficiently construct moments Apr 25, 2023
@maffoo maffoo enabled auto-merge (squash) April 25, 2023 20:46
@maffoo maffoo merged commit c5367eb into master Apr 25, 2023
@maffoo maffoo deleted the u/maffoo/moment-from-ops branch April 25, 2023 20:58
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/performance size: S 10< lines changed <50
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants