I am attempting to run parallel computations on two different backends from within the same Jupyter notebook, though it appears these two jobs are running sequentially. I understand the jobs will be asynchronous, but is there any way to submit two jobs to differing backends at the same time? I'm not seeing anything allowing for providing multiple backends. Thank you!
2 Answers
$\begingroup$
$\endgroup$
There is a (much simpler in my opinion) solution that does not require multiprocessing
at all: use qiskit
API.
A code sample is worth a thousand words:
# Load the packages
from qiskit import IBMQ, QuantumCircuit, execute
# Log in to your IBMQ account
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
# Get the backends you are interested in
backends = [provider.get_backend(b) for b in ["ibmq_athens", "ibmq_quito"]]
# Build the quantum circuit
qc = QuantumCircuit(5)
qc.h(list(range(5)))
qc.cx(0, 1)
qc.cx(1, 2)
qc.cx(3, 4)
qc.cx(5, 2)
qc.measure_all()
# Asynchronously submit the circuit on all the backends.
# This will only submit the circuits, not wait for their completion.
jobs = [execute(qc, backend) for backend in backends]
# Do some work...
# When you need your job results:
# You can also query the results individually if needed.
# The call to "result()" blocks until the job is finished.
results = [j.result() for j in jobs]
# Now you can use the results, for example to recover the counts
# This is a non-blocking operation as the counts are already in
# the results obtained in the previous step
counts = [result.get_counts() for result in results]
$\begingroup$
$\endgroup$
As I commented above, this can be done through python multiprocessing
tool. Here is an example:
import multiprocessing
import numpy as np
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, IBMQ, execute
provider = IBMQ.load_account()
num_qubits = 2
qreg_q = QuantumRegister(num_qubits, 'q')
creg_c = ClassicalRegister(num_qubits, 'c')
circuit = QuantumCircuit(qreg_q,creg_c)
for i in range(num_qubits):
circuit.h(qreg_q[i])
circuit.measure(qreg_q[i], creg_c[i] )
print(circuit)
def quantum_jobs(i, return_jobs, backend):
print(backend)
jobs = execute(circuit, backend, shots = 1000).result().get_counts()
i = jobs['00'] # get 00 counts just as an example....
return_jobs[i] = i
backends = [provider.get_backend('ibmq_athens'), provider.get_backend('ibmq_santiago') ]
if __name__ == "__main__":
manager = multiprocessing.Manager()
return_jobs = manager.dict()
jobs = []
for i in range(2):
p = multiprocessing.Process(target=quantum_jobs, args=(i, return_jobs , backends[i]))
jobs.append(p)
p.start()
for proc in jobs:
proc.join()
print(return_jobs.values())
The output would be something like:
┌───┐┌─┐
q_0: ┤ H ├┤M├───
├───┤└╥┘┌─┐
q_1: ┤ H ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/══════╩══╩═
0 1
ibmq_athens
ibmq_santiago
[277, 271]
I think you do have a maximum of 5 jobs being submitted at a time so keep this in mind.
All the best.
multiprocessing
. At least this is how I do mine parallelization. Maybe there are other ways. $\endgroup$