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

Speed up tests using mocks #2126

Merged
merged 16 commits into from
Dec 14, 2023
Merged

Speed up tests using mocks #2126

merged 16 commits into from
Dec 14, 2023

Conversation

natestemen
Copy link
Member

@natestemen natestemen commented Dec 14, 2023

Description

Speed up the tests round three. This time mostly using the mocking approach in order to cut down on the expensive computations that are performed. I also cleaned up some of the adjacent code while trying to understand the QSE tests.

The following table is the runtime of make test before and after the changes included in this PR.

before after
5:31 3:39

fixes #2080

this function always gets called with a single PauliString object, and
it wouldn't make sense to call with a list/sequence
these two tests do not need to run any of the computation done in the
`test_execute_with_qse` since that test already covers that! no need to
check performance either as, again, the previous test covers that. these
tests exist only to ensure the two alternate workflows run.
seems very strange to me to have it defined after the function that uses
it. It's valid, but harder to understand IMO.
mocking this unearthed a bug with the cost estimator. Since for each
problem/circuit, we compute the noisy value in addition to the EM, we
were actually undercounting the estimation by `num_circuits`
@natestemen natestemen added the infrastructure For issues related to building, packaging, and continuous integration. label Dec 14, 2023
@natestemen natestemen self-assigned this Dec 14, 2023
Copy link

codecov bot commented Dec 14, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (0a9c202) 98.21% compared to head (13d6edd) 98.21%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2126      +/-   ##
==========================================
- Coverage   98.21%   98.21%   -0.01%     
==========================================
  Files          87       87              
  Lines        4150     4140      -10     
==========================================
- Hits         4076     4066      -10     
  Misses         74       74              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@andreamari andreamari left a comment

Choose a reason for hiding this comment

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

Good speed improvement!
To me it seems that mocking is used in a way which is not dangerous (e.g. by implicitly testing less real code). So, LGTM!



def _compute_overlap_matrix(
circuit: QPROGRAM,
executor: Union[Executor, Callable[[QPROGRAM], QuantumResult]],
check_operators: Sequence[PauliString],
pauli_string_to_expectation_cache: Dict[PauliString, complex] = {},
pauli_expectation_cache: Dict[PauliString, complex] = {},
code_hamiltonian: Optional[Observable] = None,
Copy link
Member

Choose a reason for hiding this comment

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

Is this new argument here in order to get rid of _compute_hamiltonian_overlap_matrix ?
Seems good, just trying to understand.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup that's exactly right! We previously had

  1. _compute_hamiltonian_overlap_matrix, and
  2. _compute_overlap_matrix

which were largely the same code, except for one line. I combined the two functions in order to cut down on repeated code.

noise_model_function=cirq.depolarize,
noise_level=(0.01,),
)
assert mock_execute_with_qse.call_count == num_circuits
Copy link
Member

Choose a reason for hiding this comment

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

Do you know how mock_execute_with_qse.call_count "knows" that it should return num_circuits?
All seems to work. I am just curious how unittest.mock.patch is able to mock functions without explicitly setting return values.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was also surprised you don't have to set a return value, but it's nice not having to set some random value for it since it's meaningless (in this instance).

As for how it actually works, unittest.mock.patch creates a MagicMock instance for the execute_with_qse function. Under the hood my guess is that the MagicMock class looks something like this:

class MagicMock:
    def __init__(self):
        self.call_count = 0
    
    def __call__(self):
        self.call_count += 1

@natestemen natestemen merged commit 6aefbfb into master Dec 14, 2023
13 of 16 checks passed
@natestemen natestemen deleted the nts-tests-speedup branch December 14, 2023 23:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
infrastructure For issues related to building, packaging, and continuous integration.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Speed up Mitiq tests (3rd iteration)
2 participants