How to optimize running large programs with the Resource Estimator
In this article, you learn how to optimize the execution time when running large Q# programs with the Azure Quantum Resource Estimator.
For information about how to run the Resource Estimator, see Different ways to run the Resource Estimator.
Prerequisites
- The latest version of Visual Studio Code or open VS Code on the Web.
- The latest version of the Quantum Development Kit extension. For installation details, see Installing the QDK on VS Code.
If you want to use Python in VS Code, you also need the following:
Install the latest version of the Python, and Jupyter extensions for VS Code.
The latest Azure Quantum
qsharp
package.python -m pip install --upgrade qsharp
How to handle large Q# programs
When you submit a resource estimation job to the Resource Estimator, the quantum program is evaluated completely to extract the resource estimates. If you want estimate the resources of a Q# operation that is invoked many times, for example, in a loop with many iterations, the execution of the resource estimation job may take a long time. One way to reduce long execution times is to run the operation once, compute and cache its costs, and use the data on subsequent calls. This technique is called manual caching.
Manual caching
The Resource Estimator target supports two Q# functions to perform manual caching: BeginEstimateCaching(name: String, variant: Int): Bool
and EndEstimateCaching(): Unit
. BeginEstimateCaching
function takes as inputs a name
which is the unique name of the code fragment for which you want to cache costs, and an integer variant
that distinguishes different variants of cost for the same fragment.
Note
The two special operations BeginEstimateCaching
and EndEstimateCaching
are intrinsic operations for the Resource Estimator. They're not supported by other execution targets.
For example, let's say you have a Q# operation called ExpensiveOperation
that is called many times in an iteration. You can use caching to reduce its estimation time:
operation ExpensiveOperation(c: Int, b : Bool): Unit {
if BeginEstimateCaching("MyNamespace.ExpensiveOperation", SingleVariant()) {
// Code block to be cached
EndEstimateCaching();
}
}
When ExpensiveOperation
is used repeatedly, BeginEstimateCaching
is called each time. When BeginEstimateCaching
is called for the first time, it returns true
and begins accumulation of cost data. This causes code to proceed with execution of the expensive code fragment. When EndEstimateCaching
is called, the cost data is stored for the future use and it's incorporated into overall cost of the program.
When ExpensiveOperation
is called the second time (and subsequently), the Resource Estimator finds the stored (cached) cost data, incorporates it into overall cost of the program and returns false
. This causes expensive code fragment to be skipped therefore the Resource Estimator executes program faster. EndEstimateCaching
should be placed at the end of the condition, and regions enclosed in BeginEstimateCaching-EndEstimateCaching
can be nested.
SingleVariant()
indicates that the cost data collected on the first execution can be reused in all subsequent executions of the code fragment. This might be not always the case. For example, if your code have different cost for odd and even values of a variable 'c', you can provide a variant
value:
operation ExpensiveOperation(c: Int, b : Bool): Unit {
if BeginEstimateCaching("MyNamespace.ExpensiveOperation", c % 2) {
// Some code
EndEstimateCaching();
}
}
In this case, the cache is different for odd and even values of c
. In other words, data collected for even values of c
is only reused for even values of c
, and the same applies for odd values of c
.
Note
If you run into any issue while working with the Resource Estimator, check out the Troubleshooting page, or contact AzureQuantumInfo@microsoft.com.