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: