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 __cirq_debug__ flag and conditionally disable qid validations in gates and operations #6000

Merged
merged 6 commits into from
Feb 16, 2023

Conversation

tanujkhattar
Copy link
Collaborator

This is the first PR in a series of PRs to provide cirq users to conditionally disable validations in cirq to boost runtime performance. The proposal for adding a __cirq_debug__ flag is presented in #5988

This PR adds:

  1. A cirq.__debug__ flag, which is thread safe and implemented using contextvars. The default value is set to __debug__ global constant in python.
  2. Conditions the qid shape validations in Gate.validate_args(), Operation.validate_args and Gate.on_each on the value of cirq.__debug__ flag.

Benchmarks on my laptop show improvement of about ~20%.

$> asv run --python=same --bench XOnAllQubitsCircuit
· Discovering benchmarks
· Running 2 total benchmarks (1 commits * 2 environments * 1 benchmarks)
[  0.00%] ·· Benchmarking existing-py_Users_tanujkhattar_opt_anaconda3_envs_cirq_bin_python-PYTHONOPTIMIZE-O
[ 25.00%] ··· Running (circuit_construction.XOnAllQubitsCircuit.time_circuit_construction--).
[ 50.00%] ··· circuit_construction.XOnAllQubitsCircuit.time_circuit_construction                                                                                                                          ok
[ 50.00%] ··· ===================== ============ ============= ============= ============
              --                                           Depth(D)
              --------------------- -----------------------------------------------------
               Number of Qubits(N)       1             10           100          1000
              ===================== ============ ============= ============= ============
                        1             23.6±3μs      151±3μs     1.39±0.07ms   14.4±0.3ms
                        10            89.4±3μs      790±50μs     7.68±0.2ms   77.7±0.9ms
                       100            722±20μs    7.14±0.09ms    70.8±0.7ms    731±5ms
                       1000          7.05±0.1ms     71.2±1ms      748±10ms    7.69±0.2s
              ===================== ============ ============= ============= ============

[ 50.00%] ·· Benchmarking existing-py_Users_tanujkhattar_opt_anaconda3_envs_cirq_bin_python-PYTHONOPTIMIZE
[ 75.00%] ··· Running (circuit_construction.XOnAllQubitsCircuit.time_circuit_construction--).
[100.00%] ··· circuit_construction.XOnAllQubitsCircuit.time_circuit_construction                                                                                                                          ok
[100.00%] ··· ===================== ============ ============= ============= ============
              --                                           Depth(D)
              --------------------- -----------------------------------------------------
               Number of Qubits(N)       1             10           100          1000
              ===================== ============ ============= ============= ============
                        1             25.5±2μs      223±60μs    1.75±0.03ms   16.2±0.4ms
                        10            109±4μs       978±20μs     9.80±0.2ms   99.7±0.5ms
                       100            939±30μs    8.95±0.09ms     91.1±1ms     954±20ms
                       1000          9.42±0.2ms     89.9±1ms      949±10ms    9.63±0.03s
              ===================== ============ ============= ============= ============

This should also make the cirq.contrib.hacks.disable_validation obsolete.

cc @maffoo @zchen088 @dabacon @dstrain115

@tanujkhattar tanujkhattar requested review from a team, vtomole and cduck as code owners February 7, 2023 04:43
@tanujkhattar tanujkhattar changed the title Add __cirq_debug__ flag and conditionally disable qid validations in gates and operations Add __cirq_debug__ flag and conditionally disable qid validations in gates and operations Feb 7, 2023
@tanujkhattar tanujkhattar requested a review from maffoo February 7, 2023 04:45
cirq-core/cirq/ops/raw_types.py Outdated Show resolved Hide resolved
cirq-core/requirements.txt Outdated Show resolved Hide resolved
Comment on lines 165 to 168
cirq.__cirq_debug__.set(False)
op = cirq.H(q0, q1)
assert op.qubits == (q0, q1)
h_op.validate_args([q0, q1])
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it'd be nice to add a context manager for changing the __cirq_debug__ flag and making that the default way of using it. This ensures that state is restored even if an exception happens, which makes it much easier to know the state of the flag when looking at code.

@contextlib.contextmanager
def with_debug(value: bool) -> Iterator[None]:
    token = __cirq_debug__.set(value)
    try:
        yield
    finally:
        token.reset()

Then can use that in these tests:

with cirq.with_debug(False):
    op = cirq.H(q0, q1)
    assert op.qubits == (q0, q1)
    h_op.valudate_args([q0, q1])

I think we should encourage using a mechanism like this and discourage setting cirq.__cirq_debug__ manually (other than maybe for interactive use).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think adding the context manager is fine, but I'd still like to set the default value to __debug__ so that users have a way to disable validations in existing codebase without major modifications in the code.

What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added a context manager, PTAL

@mpharrigan
Copy link
Collaborator

semi-serious question: did you benchmark whether the new if statements measurably slow down existing code with debug turned on?

I don't know how common running python with -O is, but I guess one can set this flag independently of __debug__.

@tanujkhattar
Copy link
Collaborator Author

@mpharrigan I did some more measurements as per your suggestion and here are the findings.

Setup

I benchmark different versions of Cirq for the time it takes to construct 300_000 single / two qubit operations using snakeviz. The code is as follows:

def constuct_operations(q: List[cirq.Qid]) -> Iterator[cirq.Operation]:
    for q1, q2 in zip(q[:-1], q[1:]):
        yield cirq.X(q1)
        yield cirq.Y(q2)
        yield cirq.CNOT(q1, q2)
n = 100_000
q = cirq.LineQubit.range(n)
%snakeviz [*constuct_operations(q)]

Cirq master without __cirq_debug__

image

This PR with __cirq_debug__=True

image

This PR with __cirq_debug__=False

image

Conclusion

There is a minor cost for adding the if statement when __cirq_debug__=True but we shave off a large percent of time spent inside validate_args when __cirq_debug__=False.

@maffoo The PR is ready for another look.

@tanujkhattar tanujkhattar requested a review from maffoo February 9, 2023 20:08
@CirqBot CirqBot added the size: M 50< lines changed <250 label Feb 12, 2023
Copy link
Contributor

@maffoo maffoo left a comment

Choose a reason for hiding this comment

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

LGTM with one minor comment.

@@ -15,6 +15,8 @@
"""Workarounds for compatibility issues between versions and libraries."""
import contextlib
import dataclasses

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: remove blank line and sort imports since contextvars is part of the stdlib.

@tanujkhattar tanujkhattar merged commit 27dd607 into quantumlib:master Feb 16, 2023
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
…n gates and operations (quantumlib#6000)

* Add __cirq_debug__ flag and conditionally disable qid validations in gates and operations

* fix mypy errors

* Fix typo

* Address comments and add a context manager

* Address nit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/performance size: M 50< lines changed <250
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants