Skip to content

Commit e98da30

Browse files
use concurrent.futures.Executor instead of multiprocessing pool to resolve conflict with duet
1 parent 4c28746 commit e98da30

File tree

3 files changed

+17
-14
lines changed

3 files changed

+17
-14
lines changed

cirq-core/cirq/experiments/two_qubit_xeb.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from __future__ import annotations
1818

19+
import concurrent.futures as cf
1920
import functools
2021
import itertools
2122
from collections.abc import Mapping, Sequence
@@ -409,7 +410,7 @@ def parallel_xeb_workflow(
409410
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
410411
ax: plt.Axes | None = None,
411412
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
412-
pool: multiprocessing.pool.Pool | None = None,
413+
pool: multiprocessing.pool.Pool | cf.Executor | None = None,
413414
batch_size: int = 9,
414415
tags: Sequence[Any] = (),
415416
**plot_kwargs,
@@ -428,7 +429,7 @@ def parallel_xeb_workflow(
428429
ax: the plt.Axes to plot the device layout on. If not given,
429430
no plot is created.
430431
pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
431-
pool: An optional multiprocessing pool.
432+
pool: An optional pool.
432433
batch_size: We call `run_batch` on the sampler, which can speed up execution in certain
433434
environments. The number of (circuit, cycle_depth) tasks to be run in each batch
434435
is given by this number.

cirq-core/cirq/experiments/xeb_fitting.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from __future__ import annotations
1818

19+
import concurrent.futures as cf
1920
import dataclasses
2021
from abc import ABC, abstractmethod
2122
from collections.abc import Iterable, Sequence
@@ -49,7 +50,7 @@ def benchmark_2q_xeb_fidelities(
4950
circuits: Sequence[cirq.Circuit],
5051
cycle_depths: Sequence[int] | None = None,
5152
param_resolver: cirq.ParamResolverOrSimilarType = None,
52-
pool: multiprocessing.pool.Pool | None = None,
53+
pool: multiprocessing.pool.Pool | cf.Executor | None = None,
5354
) -> pd.DataFrame:
5455
"""Simulate and benchmark two-qubit XEB circuits.
5556
@@ -451,7 +452,7 @@ def characterize_phased_fsim_parameters_with_xeb(
451452
xatol: float = 1e-3,
452453
fatol: float = 1e-3,
453454
verbose: bool = True,
454-
pool: multiprocessing.pool.Pool | None = None,
455+
pool: multiprocessing.pool.Pool | cf.Executor | None = None,
455456
) -> XEBCharacterizationResult:
456457
"""Run a classical optimization to fit phased fsim parameters to experimental data, and
457458
thereby characterize PhasedFSim-like gates.
@@ -470,7 +471,7 @@ def characterize_phased_fsim_parameters_with_xeb(
470471
fatol: The `fatol` argument for Nelder-Mead. This is the absolute error for convergence
471472
in the function evaluation.
472473
verbose: Whether to print progress updates.
473-
pool: An optional multiprocessing pool to execute circuit simulations in parallel.
474+
pool: An optional pool to execute circuit simulations in parallel.
474475
"""
475476
(pair,) = sampled_df['pair'].unique()
476477
initial_simplex, names = options.get_initial_simplex_and_names(
@@ -546,7 +547,7 @@ def characterize_phased_fsim_parameters_with_xeb_by_pair(
546547
initial_simplex_step_size: float = 0.1,
547548
xatol: float = 1e-3,
548549
fatol: float = 1e-3,
549-
pool: multiprocessing.pool.Pool | None = None,
550+
pool: multiprocessing.pool.Pool | cf.Executor | None = None,
550551
) -> XEBCharacterizationResult:
551552
"""Run a classical optimization to fit phased fsim parameters to experimental data, and
552553
thereby characterize PhasedFSim-like gates grouped by pairs.
@@ -570,7 +571,7 @@ def characterize_phased_fsim_parameters_with_xeb_by_pair(
570571
in the parameters.
571572
fatol: The `fatol` argument for Nelder-Mead. This is the absolute error for convergence
572573
in the function evaluation.
573-
pool: An optional multiprocessing pool to execute pair optimization in parallel. Each
574+
pool: An optional pool to execute pair optimization in parallel. Each
574575
optimization (and the simulations therein) runs serially.
575576
"""
576577
pairs = sampled_df['pair'].unique()

cirq-core/cirq/experiments/z_phase_calibration.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from __future__ import annotations
1818

19+
import concurrent.futures as cf
1920
import multiprocessing
2021
import multiprocessing.pool
2122
from collections.abc import Sequence
@@ -46,7 +47,7 @@ def z_phase_calibration_workflow(
4647
cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
4748
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
4849
atol: float = 1e-3,
49-
num_workers_or_pool: int | multiprocessing.pool.Pool = -1,
50+
num_workers_or_pool: int | multiprocessing.pool.Pool | cf.Executor = -1,
5051
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
5152
tags: Sequence[Any] = (),
5253
) -> tuple[xeb_fitting.XEBCharacterizationResult, pd.DataFrame]:
@@ -81,7 +82,7 @@ def z_phase_calibration_workflow(
8182
cycle_depths: The cycle depths to use.
8283
random_state: The random state to use.
8384
atol: Absolute tolerance to be used by the minimizer.
84-
num_workers_or_pool: An optional multi-processing pool or number of workers.
85+
num_workers_or_pool: An optional pool or number of workers.
8586
A zero value means no multiprocessing.
8687
A positive integer value will create a pool with the given number of workers.
8788
A negative value will create pool with maximum number of workers.
@@ -92,12 +93,12 @@ def z_phase_calibration_workflow(
9293
- A `pd.DataFrame` comparing the before and after fidelities.
9394
"""
9495

95-
pool: multiprocessing.pool.Pool | None = None
96+
pool: multiprocessing.pool.Pool | cf.Executor | None = None
9697
local_pool = False
9798
if isinstance(num_workers_or_pool, multiprocessing.pool.Pool):
9899
pool = num_workers_or_pool # pragma: no cover
99100
elif num_workers_or_pool != 0:
100-
pool = multiprocessing.Pool(num_workers_or_pool if num_workers_or_pool > 0 else None)
101+
pool = cf.ThreadPoolExecutor(num_workers_or_pool if num_workers_or_pool > 0 else None)
101102
local_pool = True
102103

103104
fids_df_0, circuits, sampled_df = parallel_xeb_workflow(
@@ -143,8 +144,8 @@ def z_phase_calibration_workflow(
143144
)
144145

145146
if local_pool:
146-
assert isinstance(pool, multiprocessing.pool.Pool)
147-
pool.close()
147+
assert isinstance(pool, cf.Executor)
148+
pool.shutdown()
148149
return result, before_after
149150

150151

@@ -159,7 +160,7 @@ def calibrate_z_phases(
159160
cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
160161
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
161162
atol: float = 1e-3,
162-
num_workers_or_pool: int | multiprocessing.pool.Pool = -1,
163+
num_workers_or_pool: int | multiprocessing.pool.Pool | cf.Executor = -1,
163164
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
164165
tags: Sequence[Any] = (),
165166
) -> dict[tuple[cirq.Qid, cirq.Qid], cirq.PhasedFSimGate]:

0 commit comments

Comments
 (0)