Using the QIR runtime on a Mac #864
Description
Recently I was able to compile and run the database-search sample project using the QIR runtime on a Mac laptop. These are the notes of the steps I followed.
Pre-reqs
Checked out the repos qsharp-runtime and Quantum (i.e. samples) under a ~/Repos
folder
Installed:
- powershell 7+ (brew install --cask powershell): needed to run all build scripts
- cmake 3.20+ (brew install cmake): all our native projects are based on cmake for x-platform support
- clang (xcode-select --install): needed to compile native code
- dotnet: needed by the Q# compiler and qir-cli tool.
Note: there might be other dependencies that were already installed on my environment. Also,
bootstrap.ps1
installs Rust automatically (used for the experimental simulator), and might install other things.
Build Runtime components
Run bootstrap.ps1 under root to build Native simulators and basic Qir runtime
cd ~/Repos/qsharp-rutnime
pwhs ./bootstrap.ps1
Build rest of Qir:
cd ~/Repos/qsharp-runtime/src/Qir
pwsh ./build_all.ps1
Finally, pack and install the qir-cli
:
cd ~/Repos/qsharp-runtime/src/Qir/CommandLineTool
dotnet pack
dotnet tool install -g Microsoft.Quantum.Qir.CommandLineTool --add-source ./bin/Debug/
Using the QIR runtime to simulate a Q# program
1. Generate QIR from Q# project
Generate the QIR representation of a Q# program simply by passing the QirGeneration
flag at build time:
cd ~/Repos/Quantum/samples/algorithms/database-search
dotnet build /property:QirGeneration=true
2. Create an executable to simulate the QIR program using the qir-cli
tool
Currently, the easiest way to compile a QIR program for local simulation is to use the qir-cli
tool, this tools is still under development, though.
The qir-cli
takes as input a dll of a Q# program (that must be generated with the QirGeneration
flag on) and a target folder. The tool compiles the Q# program into one or more executables, one for each @entrypoint.
qir-cli --dll bin/Debug/netcoreapp3.1/DatabaseSearchSample.dll --exe qir
Notice the output:
$ ls qir
-rw-r--r-- 1 anpaz staff 730693 Oct 19 11:47 DatabaseSearchSample.ll
-rwxr-xr-x 1 anpaz staff 1731176 Oct 19 11:48 Microsoft__Quantum__Samples__DatabaseSearch__RunMultipleQuantumSearch__Interop.exe
-rwxr-xr-x 1 anpaz staff 1731176 Oct 19 11:48 Microsoft__Quantum__Samples__DatabaseSearch__RunQuantumSearch__Interop.exe
-rwxr-xr-x 1 anpaz staff 1731176 Oct 19 11:48 Microsoft__Quantum__Samples__DatabaseSearch__RunRandomSearch__Interop.exe
-rwxr--r-- 1 anpaz staff 1151120 Oct 19 11:33 libMicrosoft.Quantum.Qir.QSharp.Core.dylib
-rwxr--r-- 1 anpaz staff 217048 Oct 19 11:33 libMicrosoft.Quantum.Qir.QSharp.Foundation.dylib
-rwxr--r-- 1 anpaz staff 1923040 Oct 19 11:33 libMicrosoft.Quantum.Qir.Runtime.dylib
It created three executables, one for each @entrypoint (RunRandomSearch
, RunQuantumSearch
and RunMultipleQuantumSearch
).
The name reflects the fully qualified name of the EntryPoint, plus __Interop.exe
.
Since the Q# QIR itself doesn't have a main
method, the qir-cli
automatically creates one
that creates an instance of the FullStateSimulator to simulate the corresponding EntryPoint parsing and passing down any arguments.
It also adds the QIR runtime dlls that are needed for execution, but it's critically missing the FullState simulator dll which needs to be manually copied:
cd qir
cp ~/Repos/qsharp-runtime/src/Simulation/Native/build/libMicrosoft.Quantum.Simulator.Runtime.dylib .
To run the program, it needs to find the QIR and Simulator dynamic libraries, so first set the LD_LIBRARY_PATH
to include the current folder, then run the program:
export LD_LIBRARY_PATH=.
./Microsoft__Quantum__Samples__DatabaseSearch__RunQuantumSearch__Interop.exe
It gives an output similar to this:
Quantum search for marked element in database.
Database size: 64.
Classical success probability: 0.015625
Queries per search: 7
Quantum success probability: 0.59138015005737521
Attempt 10. Success: Zero, Probability: 0.5 Speedup: 4.57099999999999973 Found database index [Zero, One, One, Zero, One, Zero]
Attempt 20. Success: Zero, Probability: 0.59999999999999998 Speedup: 5.48599999999999977 Found database index [One, Zero, Zero, Zero, Zero, Zero]
Attempt 30. Success: One, Probability: 0.5 Speedup: 4.57099999999999973 Found database index [One, One, One, One, One, One]
Attempt 40. Success: Zero, Probability: 0.55000000000000004 Speedup: 5.02899999999999991 Found database index [One, One, Zero, Zero, Zero, One]
Attempt 50. Success: One, Probability: 0.56000000000000005 Speedup: 5.12000000000000011 Found database index [One, One, One, One, One, One]
Attempt 60. Success: One, Probability: 0.56699999999999995 Speedup: 5.18400000000000016 Found database index [One, One, One, One, One, One]
Attempt 70. Success: Zero, Probability: 0.51400000000000001 Speedup: 4.69899999999999984 Found database index [Zero, Zero, Zero, Zero, Zero, One]
Attempt 80. Success: One, Probability: 0.55000000000000004 Speedup: 5.02899999999999991 Found database index [One, One, One, One, One, One]
Attempt 90. Success: Zero, Probability: 0.54400000000000004 Speedup: 4.9740000000000002 Found database index [Zero, One, One, One, Zero, One]
Attempt 100. Success: Zero, Probability: 0.56000000000000005 Speedup: 5.12000000000000011 Found database index [One, One, Zero, One, Zero, Zero]