quantrs2_sim/automatic_parallelization/
autoparallelengine_execute_parallel_tasks_group.rs1use quantrs2_core::{
8 error::{QuantRS2Error, QuantRS2Result},
9 gate::GateOp,
10 qubit::QubitId,
11};
12use scirs2_core::parallel_ops::{current_num_threads, IndexedParallelIterator, ParallelIterator};
13use scirs2_core::Complex64;
14use std::sync::{Arc, Barrier, Mutex, RwLock};
15
16use super::types::ParallelTask;
17
18use super::autoparallelengine_type::AutoParallelEngine;
19
20impl AutoParallelEngine {
21 pub(super) fn execute_parallel_tasks(
23 &self,
24 tasks: &[ParallelTask],
25 shared_state: Arc<RwLock<Vec<Complex64>>>,
26 results: Arc<Mutex<Vec<Complex64>>>,
27 barrier: Arc<Barrier>,
28 ) -> QuantRS2Result<()> {
29 use scirs2_core::parallel_ops::{parallel_map, IndexedParallelIterator};
30 let _ = parallel_map(tasks, |task| {
31 barrier.wait();
32 let mut state = shared_state
33 .write()
34 .expect("Failed to acquire write lock on shared state");
35 for gate in &task.gates {
36 let qubits = gate.qubits();
37 match qubits.len() {
38 1 => {
39 Self::apply_single_qubit_gate_to_state(
40 &mut state,
41 gate.as_ref(),
42 qubits[0].0 as usize,
43 );
44 }
45 2 => {
46 Self::apply_two_qubit_gate_to_state(
47 &mut state,
48 gate.as_ref(),
49 qubits[0].0 as usize,
50 qubits[1].0 as usize,
51 );
52 }
53 _ => {
54 eprintln!(
55 "Warning: {}-qubit gates not optimized for parallel execution",
56 qubits.len()
57 );
58 }
59 }
60 }
61 barrier.wait();
62 });
63 let final_state = shared_state
64 .read()
65 .expect("Failed to acquire read lock on shared state");
66 let mut result_vec = results.lock().expect("Failed to acquire lock on results");
67 result_vec.clone_from(&final_state);
68 Ok(())
69 }
70 pub(super) fn apply_single_qubit_gate_to_state(
72 state: &mut [Complex64],
73 gate: &dyn GateOp,
74 qubit: usize,
75 ) {
76 let num_qubits = (state.len() as f64).log2() as usize;
77 let stride = 1 << qubit;
78 for base in 0..state.len() {
79 if (base & stride) == 0 {
80 let idx0 = base;
81 let idx1 = base | stride;
82 let amp0 = state[idx0];
83 let amp1 = state[idx1];
84 state[idx0] = amp0;
85 state[idx1] = amp1;
86 }
87 }
88 }
89 pub(super) fn apply_two_qubit_gate_to_state(
91 state: &mut [Complex64],
92 gate: &dyn GateOp,
93 qubit1: usize,
94 qubit2: usize,
95 ) {
96 let num_qubits = (state.len() as f64).log2() as usize;
97 let stride1 = 1 << qubit1;
98 let stride2 = 1 << qubit2;
99 for base in 0..state.len() {
100 if (base & stride1) == 0 && (base & stride2) == 0 {
101 let idx00 = base;
102 let idx01 = base | stride1;
103 let idx10 = base | stride2;
104 let idx11 = base | stride1 | stride2;
105 let amp00 = state[idx00];
106 let amp01 = state[idx01];
107 let amp10 = state[idx10];
108 let amp11 = state[idx11];
109 state[idx00] = amp00;
110 state[idx01] = amp01;
111 state[idx10] = amp10;
112 state[idx11] = amp11;
113 }
114 }
115 }
116}