qiboteam / qibocal

Quantum calibration, characterization and validation module for Qibo.
https://qibo.science
Apache License 2.0
31 stars 7 forks source link

Async execution #916

Open alecandido opened 3 months ago

alecandido commented 3 months ago

If execution is by far the slowest operation, Qibocal is already doing its best[*].

However, if fits starts being time-consuming, we're keeping one machine busy just waiting for the results for another one.

In the runcard context, when there are no updates, all protocols are independent of each other. This could be just solved using qq acquire, and then fitting the results a posteriori. However, already for runcards, if only some routines are updating, it starts getting complicated, since some times you could keep acquiring further, but some others you need to wait for the fit results.

This scenario is even more pronounced for scripts, where you don't know in advance which will be the subsequent operation.

All of this can be accounted quite elegantly with futures and execution loops: instead of returning a result, the acquisition could return a future, that can be waited for. But you will need to wait only if strictly required, otherwise the execution is free to continue. In this configuration, the fit will obviously wait for the acquired data, returning a dependent future, that will resolve after the first one. However, if the routine after depends on the fitted parameters on its turn, it will wait for them as well. But if there is any independent routine, it can be queued immediately, without waiting for the first fit to resolve.

This workflow doesn't have to be implemented from scratch, since it is just the description of concurrent execution. The primitives are already exposed to Python as part of the core language and the standard library module asyncio. We only need to make run_protocol and the operation components (acquire, fit, and update) asynchronous.

[*]: ok, operations on separate qubits could be executed in parallel, but this is not necessarily optimal for calibration, unless cross-talk is already well under control

alecandido commented 3 months ago

Btw, together with the scripts, this should be an effective and efficient way (for us) to implement the dependencies, without the need of reactions.

We don't really need components reacting to events: our components are already functions, and they are invoked with parameters. They would just to wait for their parameters to be available (already encoded by scripts), and only for that (enabled by the async execution).

This will also limit the dependencies, since all ingredients are available as part of the language and standard library (which, by now, it is often the case even for other languages - concerning async).