Questions about parallel execution

Hi.
For context, I’m trying to optimize the execution of VQE calculating the expected value of each group in parallel (I follow this tutorial for the grouping the terms Measurement optimization). I know that exist a demo (VQE with parallel QPUs with Rigetti) but I want to do it without installing external libraries.

I was looking this question (Parallel Circuit execution during optimisation), and I want to know if it possible to apply broadcasting when the circuit have more than one variable, in the answer he create some batches for a circuit that required only one parameter of input, but I want to know if it’s possible to do something similar when the circuit require two or more inputs in a simple way (for example, the parameters and one of the hamiltonian’s group).

The second thing, how can I see how many threads are using when I’m doing these parallel executions? (with the observables and circuits). As you can see, I’m not an expert in parallel calculations, this is one of my first attempt to work with it, so I’m not sure if I need to do something more to do parallel executions (modify some environment variable, installing some obligatory things or something else)
Thank in advance.

Hi @jnorambu, thanks for checking in! :slight_smile:

Hmm, actually, it’s definitely possible to feed two different sets of inputs to the circuit where you want to have parameter broadcasting. Here’s what structure a simple extension of the example you found in the forum thread could take:

import pennylane as qml
from pennylane import numpy as np

dev = qml.device("default.qubit", wires=2)

@qml.qnode(dev)
def circuit2(features):
    qml.AngleEmbedding(features[0], wires=range(2))
    qml.AngleEmbedding(features[1], wires=range(2))
    return [qml.expval(qml.PauliZ(i)) for i in range(2)]

batch1 = [0.1, 0.2]
batch2 = [0.3, 0.4]
batches = [batch1, batch2]

batches2 = [[0.2, 0.4], [0.6, 0.8]]
batchesbatches=[batches, batches2]

print(circuit2(batchesbatches))
print(dev.num_executions)

As for your second question, if I understood you correctly, I don’t think you need to worry about that in this instance. I believe parameter broadcasting here leans onto NumPy, which has its own thread logic.

I think a great place to start would be the QNode documentation, where we have a great section on parameter broadcasting, with lots of examples. :slight_smile:

Let me know if anything goes wrong!

Oh sorry, I think that I don’t express correctly my first question, now that I look the Qnode documentation, I think that I can make clearer.

My question was something like if the bellow code is possible.

import pennylane as qml
from pennylane import numpy as np

dev = qml.device(“default.qubit”, wires=4)
@qml.qnode(dev)
def circuit(x, Um):
qml.RX(x, wires=0)
return [qml.expval(u) for u in Um]

x = np.array([2*np.pi])
U = [[qml.PauliZ(0), qml.PauliZ(1), qml.PauliZ(2), qml.PauliZ(3)], [qml.PauliZ(0), qml.PauliZ(1), qml.PauliZ(2)]]

circuit(x, U)

The code fails (the error is AttributeError: ‘list’ object has no attribute ‘is_hermitian’) but I think that the idea is a little clearer. The x is a fixed 1d-array of circuit’s parameters and I want to apply the broadcast on a list of list of operators (U variable) not on the x variable, I mean, evaluate the circuit in different list of operators with a fixed parameters (the x is fixed for each operator’s list) using the broadcast, and I want to know if it’s possible?.
I don’t know if it’s clearer or not my question. I will stay tuned in case you have any doubts about the previous paragraph.

I see, I think I understand. In this case, my question is — is there a specific type of output you’d like to get? From this example, it doesn’t seem like the problem you’re having is with parameter broadcasting. :slight_smile:
If you look at the way PennyLane handles measurements (especially the section on combined measurements!), it might be worth it to first think about if you actually need to use this approach with your U.

And to anwswer the implicit question about measurement, you can perform a combined measurement as a list. Depending on the specific things you’re trying to measure (I can’t say from the example), this might be enough. :smiley:

For example:

import pennylane as qml
from pennylane import numpy as np

dev = qml.device('default.qubit', wires=4)
@qml.qnode(dev)
def circuit2(x, Um):
    qml.RX(x, wires=0)
    return [qml.expval(u) for u in Um]

x = np.array([2*np.pi])
U2 = [qml.PauliZ(0), qml.PauliZ(1), qml.PauliZ(2), qml.PauliZ(3)]

circuit2(x, U2)

I mean, the reason that I use that structure for U was for this demo Measurement optimization, in order to reduce the overhead of calculate the expected value of each term of the molecular hamiltonian (measure commutative operators).

Could you point me to the part of the demo you were trying to replicate? :slight_smile: I’m afraid I can’t find it.

If you’re dealing with a measurement of observables that commute, one measurement should suffice. If they don’t commute, multiple device executions will occur (see here). Does that make sense?
Depending on what exactly you’re trying to measure (and why), there might be a more intuitive way of setting up your circuit and measurements, sometimes you just have to think about the problem from a different angle. :slight_smile:

Maybe you are right, I should try to think in a different way to do it, maybe I’m forcing too much to match with my first idea. Thanks, i will give a try to dask to parallel.

Anyways, I was talking about “Putting it all together” section, this function

obs_groupings = qml.pauli.group_observables(terms, grouping_type='qwc', method='rlf')

Absolutely, that happens to us all when we start thinking about a problem in a specific way. :slight_smile: But a very cool thing about research is that stepping back and looking at something a bit differently can lead us to interesting and sometimes more intuitive solutions.

Best of luck with figuring it out! If something doesn’t work in your code, feel free to drop into the forum. :slight_smile: