From 0de759ef371f4b9110b0412e8de3fc7058430cdb Mon Sep 17 00:00:00 2001 From: eliotheinrich <38039898+eliotheinrich@users.noreply.github.com> Date: Thu, 23 Nov 2023 20:48:35 -0500 Subject: [PATCH] Fix extended stabilizer thread safety in apply_ops_parallel (#1993) * Extended stabilizer simulator no longer shares RngEngine amongst states when ops are applied in parallel * Added release note * Fixed ugly cast --------- Co-authored-by: Jun Doi --- ...fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml | 6 ++++++ .../extended_stabilizer/extended_stabilizer_state.hpp | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml diff --git a/releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml b/releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml new file mode 100644 index 0000000000..2551b8bc47 --- /dev/null +++ b/releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml @@ -0,0 +1,6 @@ +fixes: + - | + Extended stabilizer simulation was sharing a single copy of RngEngine amongst + parallelized states in ``ExtendedStabilizer::State::apply_ops_parallel``, + leading to thread safety issue. Now, a new RngEngine is seeded for each parallel + state. \ No newline at end of file diff --git a/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp b/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp index 86947f9b5a..be6a8af609 100644 --- a/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp +++ b/src/simulators/extended_stabilizer/extended_stabilizer_state.hpp @@ -463,6 +463,12 @@ template void State::apply_ops_parallel(InputIterator first, InputIterator last, ExperimentResult &result, RngEngine &rng) { const int_t NUM_STATES = BaseState::qreg_.get_num_states(); + + std::vector rng_seeds(NUM_STATES); + for (int_t i = 0; i < NUM_STATES; i++) { + rng_seeds[i] = rng.rand_int(0, SIZE_MAX); + } + #pragma omp parallel for if (BaseState::qreg_.check_omp_threshold() && \ BaseState::threads_ > 1) \ num_threads(BaseState::threads_) @@ -470,10 +476,11 @@ void State::apply_ops_parallel(InputIterator first, InputIterator last, if (!BaseState::qreg_.check_eps(i)) { continue; } + RngEngine local_rng(rng_seeds[i]); for (auto it = first; it != last; it++) { switch (it->type) { case Operations::OpType::gate: - apply_gate(*it, rng, i); + apply_gate(*it, local_rng, i); break; case Operations::OpType::barrier: case Operations::OpType::qerror_loc: