MCPcopy Create free account
hub / github.com/NVIDIA/cuda-quantum / pyObservePar

Function pyObservePar

python/runtime/cudaq/algorithms/py_observe_async.cpp:110–170  ·  view source on GitHub ↗

@brief Run `cudaq::observe` on the provided kernel and spin operator.

Source from the content-addressed store, hash-verified

108
109/// @brief Run `cudaq::observe` on the provided kernel and spin operator.
110static observe_result
111pyObservePar(const PyParType &type, const std::string &shortName,
112 mlir::ModuleOp module, spin_op &spin_operator, int shots,
113 std::optional<noise_model> noise, nanobind::args args) {
114 // Ensure the user input is correct.
115 auto &platform = get_platform();
116 if (!platform.supports_task_distribution())
117 throw std::runtime_error(
118 "The current quantum_platform does not support parallel distribution "
119 "of observe() expectation value computations.");
120
121 // FIXME Handle noise modeling with parallel distribution.
122 if (noise)
123 TODO("Handle Noise Models with python parallel distribution.");
124
125 auto nQpus = platform.num_qpus();
126 if (type == PyParType::thread) {
127 // Does this platform expose more than 1 QPU
128 // If so, let's distribute the work amongst the QPUs
129 if (nQpus == 1)
130 printf(
131 "[cudaq::observe warning] distributed observe requested but only 1 "
132 "QPU available. no speedup expected.\n");
133 nanobind::gil_scoped_release release;
134 return detail::distributeComputations(
135 [&](std::size_t i, const spin_op &op) {
136 nanobind::gil_scoped_acquire acquire;
137 return pyObserveAsync(shortName, module, op, i, shots, args);
138 },
139 spin_operator, nQpus);
140 }
141
142 if (!mpi::is_initialized())
143 throw std::runtime_error("Cannot use mpi multi-node observe() without "
144 "MPI (did you initialize MPI?).");
145
146 // Necessarily has to be MPI
147 // Get the rank and the number of ranks
148 auto rank = mpi::rank();
149 auto nRanks = mpi::num_ranks();
150
151 // Each rank gets a subset of the spin terms
152 auto spins = spin_operator.distribute_terms(nRanks);
153
154 // Get this rank's set of spins to compute
155 auto localH = spins[rank];
156
157 // Distribute locally, i.e. to the local nodes QPUs
158 nanobind::gil_scoped_release release;
159 auto localRankResult = detail::distributeComputations(
160 [&](std::size_t i, const spin_op &op) {
161 nanobind::gil_scoped_acquire acquire;
162 return pyObserveAsync(shortName, module, op, i, shots, args);
163 },
164 localH, nQpus);
165
166 // combine all the data via an all_reduce
167 auto exp_val = localRankResult.expectation();

Callers 1

observe_parallel_implFunction · 0.85

Calls 10

distributeComputationsFunction · 0.85
pyObserveAsyncFunction · 0.85
is_initializedFunction · 0.85
rankFunction · 0.85
num_ranksFunction · 0.85
all_reduceFunction · 0.85
num_qpusMethod · 0.80
distribute_termsMethod · 0.80
expectationMethod · 0.45

Tested by

no test coverage detected