|
11 | 11 | # python3 gqe_h2.py |
12 | 12 | # |
13 | 13 | # In order to leverage CUDA-Q MQPU and distribute the work across |
14 | | -# multiple QPUs (thereby observing a speed-up), set the target and |
15 | | -# use MPI: |
16 | | -# |
17 | | -# cudaq.set_target('nvidia', option='mqpu') |
18 | | -# cudaq.mpi.initialize() |
19 | | -# |
20 | | -# run with |
| 14 | +# multiple QPUs (thereby observing a speed-up), run with: |
21 | 15 | # |
22 | 16 | # mpiexec -np N and vary N to see the speedup... |
23 | | -# e.g. mpiexec -np 2 python3 gqe_h2.py |
24 | | -# |
25 | | -# End the script with |
26 | | -# cudaq.mpi.finalize() |
27 | | - |
28 | | -import numpy as np |
29 | | -import cudaq, cudaq_solvers as solvers |
| 17 | +# e.g. PMIX_MCA_gds=hash mpiexec -np 2 python3 gqe_h2.py --mpi |
| 18 | + |
| 19 | +import argparse, cudaq |
| 20 | + |
| 21 | +parser = argparse.ArgumentParser() |
| 22 | +parser.add_argument('--mpi', action='store_true') |
| 23 | +args = parser.parse_args() |
| 24 | + |
| 25 | +if args.mpi: |
| 26 | + try: |
| 27 | + cudaq.set_target('nvidia', option='mqpu') |
| 28 | + cudaq.mpi.initialize() |
| 29 | + except RuntimeError: |
| 30 | + print( |
| 31 | + 'Warning: NVIDIA GPUs or MPI not available, unable to use CUDA-Q MQPU. Skipping...' |
| 32 | + ) |
| 33 | + exit(0) |
| 34 | +else: |
| 35 | + try: |
| 36 | + cudaq.set_target('nvidia', option='fp64') |
| 37 | + except RuntimeError: |
| 38 | + cudaq.set_target('qpp-cpu') |
| 39 | + |
| 40 | +import cudaq_solvers as solvers |
30 | 41 | from cudaq import spin |
31 | 42 |
|
32 | 43 | from lightning.fabric.loggers import CSVLogger |
|
42 | 53 | torch.backends.cudnn.deterministic = True |
43 | 54 | torch.backends.cudnn.benchmark = False |
44 | 55 |
|
45 | | -# Check if NVIDIA GPUs are available and set target accordingly |
46 | | -try: |
47 | | - cudaq.set_target('nvidia', option='fp64') |
48 | | -except RuntimeError: |
49 | | - # Fall back to CPU target |
50 | | - cudaq.set_target('qpp-cpu') |
51 | | - |
52 | 56 | # Create the molecular hamiltonian |
53 | 57 | geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))] |
54 | 58 | molecule = solvers.create_molecule(geometry, 'sto-3g', 0, 0, casci=True) |
@@ -147,35 +151,39 @@ def cost(sampled_ops: list[cudaq.SpinOperator], **kwargs): |
147 | 151 | full_coeffs += [c.real for c in term_coefficients(op)] |
148 | 152 | full_words += term_words(op) |
149 | 153 |
|
150 | | - # If using CUDA-Q MQPU, |
151 | | - # use observe_async with the provided qpu_id: |
152 | | - # handle = cudaq.observe_async(kernel, |
153 | | - # spin_ham, |
154 | | - # n_qubits, |
155 | | - # n_electrons, |
156 | | - # full_coeffs, |
157 | | - # full_words, |
158 | | - # qpu_id=kwargs['qpu_id']) |
159 | | - # return handle, lambda res: res.get().expectation() |
160 | | - |
161 | | - return cudaq.observe(kernel, spin_ham, n_qubits, n_electrons, full_coeffs, |
162 | | - full_words).expectation() |
| 154 | + if args.mpi: |
| 155 | + handle = cudaq.observe_async(kernel, |
| 156 | + spin_ham, |
| 157 | + n_qubits, |
| 158 | + n_electrons, |
| 159 | + full_coeffs, |
| 160 | + full_words, |
| 161 | + qpu_id=kwargs['qpu_id']) |
| 162 | + return handle, lambda res: res.get().expectation() |
| 163 | + else: |
| 164 | + return cudaq.observe(kernel, spin_ham, n_qubits, n_electrons, |
| 165 | + full_coeffs, full_words).expectation() |
163 | 166 |
|
164 | 167 |
|
165 | 168 | # Configure GQE |
166 | 169 | cfg = get_default_config() |
167 | | -cfg.use_fabric_logging = True |
| 170 | +cfg.use_fabric_logging = False |
168 | 171 | logger = CSVLogger("gqe_h2_logs/gqe.csv") |
169 | 172 | cfg.fabric_logger = logger |
170 | | -cfg.save_trajectory = True |
| 173 | +cfg.save_trajectory = False |
171 | 174 | cfg.verbose = True |
172 | 175 |
|
173 | 176 | # Run GQE |
174 | 177 | minE, best_ops = solvers.gqe(cost, op_pool, max_iters=25, ngates=10, config=cfg) |
175 | 178 |
|
176 | | -print(f'Ground Energy = {minE}') |
177 | | -print('Ansatz Ops') |
178 | | -for idx in best_ops: |
179 | | - # Get the first (and only) term since these are simple operators |
180 | | - term = next(iter(op_pool[idx])) |
181 | | - print(term.evaluate_coefficient().real, term.get_pauli_word(n_qubits)) |
| 179 | +# Only print results from rank 0 when using MPI |
| 180 | +if not args.mpi or cudaq.mpi.rank() == 0: |
| 181 | + print(f'Ground Energy = {minE}') |
| 182 | + print('Ansatz Ops') |
| 183 | + for idx in best_ops: |
| 184 | + # Get the first (and only) term since these are simple operators |
| 185 | + term = next(iter(op_pool[idx])) |
| 186 | + print(term.evaluate_coefficient().real, term.get_pauli_word(n_qubits)) |
| 187 | + |
| 188 | +if args.mpi: |
| 189 | + cudaq.mpi.finalize() |
0 commit comments