Update projects, docs, cpp files for QIR stdlib (#1578)

* Update projects, docs, cpp files for QIR stdlib

This change updates the remaining example and test projects for using the QIR stdlib via the Microsoft.Quantum.Simulator.Runtime as a QIR backend. This resolves #1560, resolves #1568, and resolves #1569.

Note that it does not update the samples under examples\QIR\Simulation as these need to be fully rewritten and likely moved to https://github.com/qir-alliance/qir-runner (see Rewrite or Move docs in examples/QIR/Simulation #1577)

* Fix development project QDK version

* Update examples/QIR/Optimization/README.md

Co-authored-by: Robin Kuzmin <9372582+kuzminrobin@users.noreply.github.com>

* Use alternative method for copying build dependencies

Co-authored-by: Robin Kuzmin <9372582+kuzminrobin@users.noreply.github.com>
This commit is contained in:
Stefan J. Wernli 2022-12-06 16:05:17 -08:00 коммит произвёл GitHub
Родитель 82e9304d61
Коммит 35ac6ceb3a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 67 добавлений и 2219 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -368,6 +368,7 @@ src/ProjectTemplates/Quantum.Test1/.template.config/template.json
src/QsCompiler/QirGeneration/QirGeneration.nuspec
/examples/QIR/Development/qir/*
/examples/QIR/Development/build
/examples/QIR/Optimization/Hello/build
src/Telemetry/Tests/coverage.json
src/Telemetry/.vscode/settings.json
build/267DevDivSNKey2048.snk

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.Quantum.Sdk/0.25.228311"> <!-- TODO(#1569): Requires refactoring for Rust QIR RT. -->
<Project Sdk="Microsoft.Quantum.Sdk/0.27.238334">
<PropertyGroup>
<OutputType>Exe</OutputType>
@ -9,8 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.LlvmBindings.Native" Version="13.0.0-CI-20220129-005156" PrivateAssets="All" GeneratePathProperty="true"/>
<PackageReference Include="Microsoft.Quantum.Qir.Runtime" Version="0.25.228311-alpha" GeneratePathProperty="true" /> <!-- TODO(#1569): Requires refactoring for Rust QIR RT. -->
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.25.228311" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.27.238334" GeneratePathProperty="true" />
</ItemGroup>
<PropertyGroup>
@ -92,18 +91,9 @@
<Target Name="CreateCppDriver">
<PropertyGroup>
<DriverCode>
#include "QirContext.hpp"
#include "QirRuntime.hpp"
#include "SimFactory.hpp"
using namespace Microsoft::Quantum%3B
using namespace std%3B
extern "C" void Microsoft__Quantum__Qir__Development__RunExample()%3B // NOLINT
int main(int argc, char* argv[]){
unique_ptr&lt;IRuntimeDriver&gt; sim = CreateFullstateSimulator()%3B
QirContextScope qirctx(sim.get(), true /*trackAllocatedObjects*/)%3B
Microsoft__Quantum__Qir__Development__RunExample()%3B
return 0%3B
}
@ -114,24 +104,17 @@
<Target Name="BuildExecutable" Condition="'$(DesignTimeBuild)' != 'true'" DependsOnTargets="CreateCppDriver;Restore" AfterTargets="QSharpCompile;CoreBuild">
<PropertyGroup>
<QirRuntimeHeaders>$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/any/native/include</QirRuntimeHeaders>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/osx-x64/native</QirRuntimeLibs>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/win-x64/native</QirRuntimeLibs>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/linux-x64/native</QirRuntimeLibs>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/osx-x64/native/libMicrosoft.Quantum.Simulator.Runtime.dylib</SimulatorRuntime>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/linux-x64/native/libMicrosoft.Quantum.Simulator.Runtime.so</SimulatorRuntime>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/osx-x64/native</SimulatorFolder>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native</SimulatorFolder>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/linux-x64/native</SimulatorFolder>
<ClangOptions Condition="$([MSBuild]::IsOsPlatform('Linux')) Or $([MSBuild]::IsOsPlatform('OSX'))">-fseh-exceptions -lstdc++</ClangOptions>
<ClangCommand>clang -std=c++17 -Wno-override-module $(ClangOptions) -o $(ExecutablePath) $(QirOutputPath)$(PathCompatibleAssemblyName).ll $(BuildOutputPath)/Main.cpp -I$(BuildOutputPath) -L$(BuildOutputPath) -lMicrosoft.Quantum.Qir.Runtime -lMicrosoft.Quantum.Qir.QSharp.Core -lMicrosoft.Quantum.Qir.QSharp.Foundation</ClangCommand>
<OmpOptions Condition="$([MSBuild]::IsOsPlatform('Linux'))">-lomp</OmpOptions>
<ClangCommand>clang -std=c++17 -Wno-override-module $(ClangOptions) -o $(ExecutablePath) $(QirOutputPath)$(PathCompatibleAssemblyName).ll $(BuildOutputPath)/Main.cpp -I$(BuildOutputPath) -L$(BuildOutputPath) -lMicrosoft.Quantum.Simulator.Runtime $(OmpOptions)</ClangCommand>
</PropertyGroup>
<ItemGroup>
<_QirRuntimeLibFiles Include="$(QirRuntimeLibs)/**/*.*" Exclude="$(QirRuntimeLibs)/**/*.exe" />
<_QirRuntimeHeaderFiles Include="$(QirRuntimeHeaders)/**/*.hpp" />
<_QirRuntimeHeaderFiles Include="$(QirRuntimeHeaders)/**/*.h" />
<_SimulatorLibraries Include="$(SimulatorFolder)/*.*" />
</ItemGroup>
<Copy SourceFiles="$(SimulatorRuntime)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeLibFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeHeaderFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_SimulatorLibraries)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
<Exec Command="clang --version" IgnoreExitCode="true" ContinueOnError="ErrorAndContinue">
<Output TaskParameter="ExitCode" PropertyName="ClangVersionCheckExitCode"/>
</Exec>

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.Quantum.Sdk/0.25.228311"> <!-- TODO(#1569): Requires refactoring for Rust QIR RT. -->
<Project Sdk="Microsoft.Quantum.Sdk/0.27.238334">
<PropertyGroup>
<QscVerbosity>Detailed</QscVerbosity>

Просмотреть файл

@ -38,7 +38,7 @@ The function below is all that is needed to JIT compile a QIR program, and consi
- load QIR/simulator libraries
- parse the QIR program
- load the JIT compiler
- initialize the QIR Runtime and attach a simulator (see [next section](#building-the-project) for more info)
- initialize and attach a simulator (see [next section](#building-the-project) for more info)
- run a QIR function
```py
@ -48,9 +48,8 @@ def main(qir_file, entry_point):
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
# Load the QIR Runtime libraries
for lib in runtime_libs:
llvm.load_library_permanently(lib)
# Load the simulator library
llvm.load_library_permanently(simulator_lib)
# Parse the provided QIR module
file = open(qir_file, 'r')
@ -60,16 +59,12 @@ def main(qir_file, entry_point):
target = llvm.Target.from_default_triple().create_target_machine()
jit_engine = llvm.create_mcjit_compiler(module, target)
# Initialize the QIR Runtime and simulator via exposed C wrapper
fun_ptr = llvm.address_of_symbol("InitQIRSim")
CFUNCTYPE(None)(fun_ptr)()
# Run the entry point of the QIR module
fun_ptr = jit_engine.get_function_address(entry_point)
CFUNCTYPE(None)(fun_ptr)()
```
Here, `runtime_libs` is a hardcoded list of the system-specific QIR libraries.
Here, `simulator_lib` is the platform specific path to the simulator library.
The name of the QIR source file `qir_file` is provided as a command-line argument, as well the name of the entry point function `entry_point`.
The way external functions with C-style linkage are invoked from Python is by using the ctypes module.
@ -78,44 +73,22 @@ The returned value is a raw pointer that can be converted to a function pointer
This is done via the function `CFUNCTYPE(<return type>, <argument types>..)(<ptr_name>)`, which also specifies the usage of the standard C calling convention.
Refer to the [ctypes documentation](https://docs.python.org/3/library/ctypes.html) for more information on calling external functions from Python.
The full Python script can be found in `jit-qir.py`.
The full Python script can be found in `qir-jit.py`.
## Building the project
Currently, it's not easily possible to set up a JIT for QIR entirely from Python, since the QIR Runtime and simulator are compiled from C++.
To get around this, a small library for which we can specify C-linkage can handle the QIR-specific initialization, which can then be invoked from Python directly using ctypes.
A small function declared with `extern "C"` linkage is sufficient to initialize the Runtime + simulator, as defined in `QIRinit.cpp`:
Before being able run QIR via LLVM's JIT compiler, we need to download the necessary simulator library from the [Quantum Simulators](https://www.nuget.org/packages/Microsoft.Quantum.Simulators/) NuGet packages:
```cpp
#include "QirContext.hpp"
#include "SimFactory.hpp"
#include <memory>
using namespace Microsoft::Quantum;
extern "C" void InitQIRSim()
{
// initialize Quantum Simulator and QIR Runtime
std::unique_ptr<IRuntimeDriver> sim = CreateFullstateSimulator();
InitializeQirContext(sim.release(), true);
}
```
Before being able run QIR via LLVM's JIT compiler, we need to download the necessary header and library files from the [QIR Runtime](https://www.nuget.org/packages/Microsoft.Quantum.Qir.Runtime) and [Quantum Simulators](https://www.nuget.org/packages/Microsoft.Quantum.Simulators/) NuGet packages:
- **Linux** (installs mono for the NuGet CLI):
- **Linux** (install mono for the NuGet CLI):
```shell
mkdir build
sudo apt update && sudo apt install -y mono-complete
curl https://dist.nuget.org/win-x86-commandline/latest/nuget.exe --output build/nuget
mono build/nuget sources add -name nuget.org -source https://api.nuget.org/v3/index.json
mono build/nuget install Microsoft.Quantum.Qir.Runtime -Version 0.18.2106148911-alpha -DirectDownload -DependencyVersion Ignore -OutputDirectory tmp
cp tmp/Microsoft.Quantum.Qir.Runtime.0.18.2106148911-alpha/runtimes/any/native/include/* build
cp tmp/Microsoft.Quantum.Qir.Runtime.0.18.2106148911-alpha/runtimes/linux-x64/native/* build
mono build/nuget install Microsoft.Quantum.Simulators -Version 0.18.2106148911 -DirectDownload -DependencyVersion Ignore -OutputDirectory tmp
cp tmp/Microsoft.Quantum.Simulators.0.18.2106148911/runtimes/linux-x64/native/Microsoft.Quantum.Simulator.Runtime.dll build
mono build/nuget install Microsoft.Quantum.Simulators -Version 0.27.238334 -DirectDownload -DependencyVersion Ignore -OutputDirectory tmp
cp tmp/Microsoft.Quantum.Simulators.0.27.238334/runtimes/linux-x64/native/libMicrosoft.Quantum.Simulator.Runtime.so build
cp tmp/Microsoft.Quantum.Simulators.0.27.238334/runtimes/linux-x64/native/libomp.so build
rm -r tmp
```
@ -124,28 +97,13 @@ Before being able run QIR via LLVM's JIT compiler, we need to download the neces
```shell
mkdir build
curl https://dist.nuget.org/win-x86-commandline/latest/nuget.exe --output build/nuget.exe
build/nuget install Microsoft.Quantum.Qir.Runtime -Version 0.18.2106148911-alpha -DirectDownload -DependencyVersion Ignore -OutputDirectory tmp
cp tmp/Microsoft.Quantum.Qir.Runtime.0.18.2106148911-alpha/runtimes/any/native/include/* build
cp tmp/Microsoft.Quantum.Qir.Runtime.0.18.2106148911-alpha/runtimes/win-x64/native/* build
build/nuget install Microsoft.Quantum.Simulators -Version 0.18.2106148911 -DirectDownload -DependencyVersion Ignore -OutputDirectory tmp
cp tmp/Microsoft.Quantum.Simulators.0.18.2106148911/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.dll build
build/nuget install Microsoft.Quantum.Simulators -Version 0.27.238334 -DirectDownload -DependencyVersion Ignore -OutputDirectory tmp
cp tmp/Microsoft.Quantum.Simulators.0.27.238334/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.dll build
cp tmp/Microsoft.Quantum.Simulators.0.27.238334/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.lib build
cp tmp/Microsoft.Quantum.Simulators.0.27.238334/runtimes/win-x64/native/libomp140.x86_64.dll build
rm -r tmp
```
Then compile the initialization library with the following command:
- **Linux**:
```shell
clang++ -shared -fPIC QIRinit.cpp -Ibuild -o build/libQIRinit.so
```
- **Windows**:
```shell
clang++ -shared QIRinit.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -Wl',/EXPORT:InitQIRSim' -o build/QIRinit.dll
```
## Running a QIR program with JIT
To run any QIR program through the JIT, simply run the Python script and provide the QIR source file name and entry point as command line arguments, for example:

Просмотреть файл

@ -2,22 +2,14 @@ import sys, platform
import llvmlite.binding as llvm
from ctypes import CFUNCTYPE
linux_runtime_libs = ["build/libMicrosoft.Quantum.Qir.Runtime.so",
"build/libMicrosoft.Quantum.Qir.QSharp.Core.so",
"build/libMicrosoft.Quantum.Qir.QSharp.Foundation.so",
"build/Microsoft.Quantum.Simulator.Runtime.dll",
"build/libQIRinit.so"]
linux_simulator_lib = "build/libMicrosoft.Quantum.Simulator.Runtime.so"
windows_runtime_libs = ["build/Microsoft.Quantum.Qir.Runtime.dll",
"build/Microsoft.Quantum.Qir.QSharp.Core.dll",
"build/Microsoft.Quantum.Qir.QSharp.Foundation.dll",
"build/Microsoft.Quantum.Simulator.Runtime.dll",
"build/QIRinit.dll"]
windows_simulator_lib = "build/Microsoft.Quantum.Simulator.Runtime.dll"
if platform.system() == "Linux":
runtime_libs = linux_runtime_libs
simulator_lib = linux_simulator_lib
elif platform.system() == "Windows":
runtime_libs = windows_runtime_libs
simulator_lib = windows_simulator_lib
else:
raise Exception("unsupported platform")
@ -27,9 +19,8 @@ def main(qir_file, entry_point):
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
# Load the QIR Runtime libraries
for lib in runtime_libs:
llvm.load_library_permanently(lib)
# Load the simulator library
llvm.load_library_permanently(simulator_lib)
# Parse the provided QIR module
file = open(qir_file, 'r')
@ -39,10 +30,6 @@ def main(qir_file, entry_point):
target = llvm.Target.from_default_triple().create_target_machine()
jit_engine = llvm.create_mcjit_compiler(module, target)
# Initialize the QIR Runtime and simulator via exposed C wrapper
fun_ptr = llvm.address_of_symbol("InitQIRSim")
CFUNCTYPE(None)(fun_ptr)()
# Run the entry point of the QIR module
fun_ptr = jit_engine.get_function_address(entry_point)
CFUNCTYPE(None)(fun_ptr)()

Просмотреть файл

@ -1,5 +1,4 @@
<Project Sdk="Microsoft.Quantum.Sdk/0.25.228311"> <!-- TODO(#1569): Requires refactoring for Rust QIR RT. -->
<Project Sdk="Microsoft.Quantum.Sdk/0.27.238334">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
@ -8,27 +7,19 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Qir.Runtime" Version="0.25.228311-alpha" GeneratePathProperty="true" /> <!-- TODO(#1569): Requires refactoring for Rust QIR RT. -->
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.25.228311" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.27.238334" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="GetDependencies" AfterTargets="Build">
<PropertyGroup>
<QirRuntimeHeaders>$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/any/native/include</QirRuntimeHeaders>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/osx-x64/native</QirRuntimeLibs>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/win-x64/native</QirRuntimeLibs>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/linux-x64/native</QirRuntimeLibs>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/osx-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/linux-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/osx-x64/native</SimulatorFolder>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native</SimulatorFolder>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/linux-x64/native</SimulatorFolder>
</PropertyGroup>
<ItemGroup>
<_QirRuntimeLibFiles Include="$(QirRuntimeLibs)/**/*.*" Exclude="$(QirRuntimeLibs)/**/*.exe" />
<_QirRuntimeHeaderFiles Include="$(QirRuntimeHeaders)/**/*.hpp" />
<_SimulatorLibraries Include="$(SimulatorFolder)/*.*" />
</ItemGroup>
<Copy SourceFiles="$(SimulatorRuntime)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeLibFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeHeaderFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_SimulatorLibraries)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
</Target>
</Project>

Просмотреть файл

@ -1,15 +1,6 @@
#include "QirContext.hpp"
#include "QirRuntime.hpp"
#include "SimFactory.hpp"
using namespace Microsoft::Quantum;
using namespace std;
extern "C" void Hello__HelloQ();
int main(int argc, char* argv[]){
unique_ptr<IRuntimeDriver> sim = CreateFullstateSimulator();
QirContextScope qirctx(sim.get(), true /*trackAllocatedObjects*/);
Hello__HelloQ();
return 0;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -304,10 +304,11 @@ Check out the full list of [LLVM passes](https://llvm.org/docs/Passes.html) for
Since QIR code *is* LLVM IR, the usual code generation tools provided by LLVM can be used to produce an executable.
However, in order to handle QIR-specific types and functions, proper linkage of the QIR runtime and simulator libraries is required.
### Obtaining the QIR runtime & simulator
### Obtaining the QIR standard library & simulator
The [QIR runtime](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime) is distributed in the form of a NuGet package, from which we will pull the necessary library files.
The same goes for the [full state quantum simulator](https://learn.microsoft.com/azure/quantum/machines/full-state-simulator), which the QIR runtime can hook into to simulate the quantum program.
The [QIR standard library](https://github.com/qir-alliance/qir-runner/tree/main/stdlib) is a native library that exposes the functionality described in the
[QIR specification](https://github.com/qir-alliance/qir-spec), from which the required static libraries are compiled into the the
[full state quantum simulator](https://learn.microsoft.com/azure/quantum/machines/full-state-simulator), which acts as the QIR backend to simulate the quantum program.
In this section, the project file `Hello.csproj` is modified to generate these library files automatically.
For convenience, a variable `BuildOutputPath` is defined with the following line added to the top-level `PropertyGroup` section:
@ -321,19 +322,17 @@ For convenience, a variable `BuildOutputPath` is defined with the following line
</PropertyGroup>
```
All QIR runtime and simulator dependencies will be copied there.
All QIR dependencies will be copied there.
Next, the aforementioned NuGet package dependencies must be declared.
One for the runtime and one for the simulator, using the `PackageReference` command:
Next, the simulator NuGet package dependencies must be declared, using the `PackageReference` command:
```xml
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Qir.Runtime" Version="0.22.187631-alpha" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.22.187631" GeneratePathProperty="true" />
</ItemGroup>
```
The package versions should match the version of the QDK specified at the top of the file, however, the runtime is only available as an alpha version at the moment.
The package version should match the version of the QDK specified at the top of the file.
The `GeneratePathProperty` will allow us to directly reference specific files in the packages later on.
Lastly, a new build target is added called `GetDependencies`:
@ -344,34 +343,19 @@ Lastly, a new build target is added called `GetDependencies`:
The property `AfterTargets` indicates the target is to be run after the regular build stage.
Inside, we simply copy library and C++ header files from the packages into the build folder with the `Copy` command:
Inside, we simply copy the simulator library from the packages into the build folder with the `Copy` command:
```xml
<Copy SourceFiles="$(SimulatorRuntime)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeLibFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeHeaderFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
```
The variables used to specify source files must be defined appropriately for each operating system.
For example, only these definitions would be active on Windows:
```xml
<QirRuntimeHeaders>$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/any/native/include</QirRuntimeHeaders>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/win-x64/native</QirRuntimeLibs>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
```
Note the variable `$(PkgMicrosoft_Quantum_Qir_Runtime)` for example is only available because of the `GeneratePathProperty` in the `Microsoft.Quantum.Qir.Runtime` package declaration.
Since `QirRuntimeHeaders` and `QirRuntimeLibs` only specify directories (whereas `SimulatorRuntime` specifies a single file), we further filter the files to be copied:
```xml
<_QirRuntimeLibFiles Include="$(QirRuntimeLibs)/**/*.*" Exclude="$(QirRuntimeLibs)/**/*.exe" />
<_QirRuntimeHeaderFiles Include="$(QirRuntimeHeaders)/**/*.hpp" />
```
Only `.hpp` files from the QIR header directory will be copied, and no `.exe` files from QIR library directory.
Put together, the new `Hello.csproj` project file should look as follows:
```xml
@ -385,53 +369,31 @@ Put together, the new `Hello.csproj` project file should look as follows:
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Qir.Runtime" Version="0.22.187631-alpha" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.22.187631" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="GetDependencies" AfterTargets="Build">
<PropertyGroup>
<QirRuntimeHeaders>$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/any/native/include</QirRuntimeHeaders>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/osx-x64/native</QirRuntimeLibs>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/win-x64/native</QirRuntimeLibs>
<QirRuntimeLibs Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Qir_Runtime)/runtimes/linux-x64/native</QirRuntimeLibs>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/osx-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorRuntime Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/linux-x64/native/Microsoft.Quantum.Simulator.Runtime.dll</SimulatorRuntime>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('OSX'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/osx-x64/native</SimulatorFolder>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/win-x64/native</SimulatorFolder>
<SimulatorFolder Condition="$([MSBuild]::IsOsPlatform('Linux'))">$(PkgMicrosoft_Quantum_Simulators)/runtimes/linux-x64/native</SimulatorFolder>
</PropertyGroup>
<ItemGroup>
<_QirRuntimeLibFiles Include="$(QirRuntimeLibs)/**/*.*" Exclude="$(QirRuntimeLibs)/**/*.exe" />
<_QirRuntimeHeaderFiles Include="$(QirRuntimeHeaders)/**/*.hpp" />
<_SimulatorLibraries Include="$(SimulatorFolder)/*.*" />
</ItemGroup>
<Copy SourceFiles="$(SimulatorRuntime)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeLibFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_QirRuntimeHeaderFiles)" DestinationFolder="$(BuildOutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(_SimulatorLibraries)" DestinationFolder="$(BuildOutputPath)" SkipUnchangedFiles="true" />
</Target>
</Project>
```
Build the project again with `dotnet build` from the project root directory.
You should see the following important files appear in a folder named `build`, among others:
You should see the simulator library appear in a folder named `build`, among others:
```
build
├── Microsoft.Quantum.Qir.QSharp.Core.dll
├── Microsoft.Quantum.Qir.QSharp.Foundation.dll
├── Microsoft.Quantum.Qir.Runtime.dll
├── Microsoft.Quantum.Simulator.Runtime.dll
├── QirContext.hpp
├── QirRuntime.hpp
└── SimFactory.hpp
```
(**Linux**) The `Microsoft.Quantum.Qir.*` dynamic libraries will already have the right naming scheme for Clang to use, but the `Microsoft.Quantum.Simulator.Runtime` library needs to be renamed.
The proper name format is `lib<library-name>.so`.
Execute the following command from the project root directory:
```bash
mv build/Microsoft.Quantum.Simulator.Runtime.dll build/libMicrosoft.Quantum.Simulator.Runtime.so
└── Microsoft.Quantum.Simulator.Runtime.lib
```
### Adding a driver
@ -440,18 +402,9 @@ Trying to compile the QIR code in `Hello.ll` as is would present some problems,
A small C++ driver program (`Main.cpp`) will handle the setup and invoke Q# operations or functions directly from the QIR code.
```cpp
#include "QirContext.hpp"
#include "QirRuntime.hpp"
#include "SimFactory.hpp"
using namespace Microsoft::Quantum;
using namespace std;
extern "C" void Hello__HelloQ();
int main(int argc, char* argv[]){
unique_ptr<IRuntimeDriver> sim = CreateFullstateSimulator();
QirContextScope qirctx(sim.get(), true /*trackAllocatedObjects*/);
Hello__HelloQ();
return 0;
}
@ -459,17 +412,6 @@ int main(int argc, char* argv[]){
The driver consists of the following elements:
* header files (to interface with the libraries):
- `QirContext` : used to register the simulator with the QIR runtime
- `QirRuntime` : implements the types and functions defined in the [QIR specification](https://github.com/qir-alliance/qir-spec)
- `SimFactory` : provides the Q# simulator
* namespaces :
- `Microsoft::Quantum` : the QIR context and simulator live here
- `std` : needed for `unique_ptr`
* external function declarations :
This is were we declare functions from other compilation units we'd like to invoke.
@ -478,11 +420,6 @@ The driver consists of the following elements:
Normally, C++ function names would be transformed during compilation to include namespace and call argument information in the function name, known as [mangling](https://en.wikipedia.org/wiki/Name_mangling).
We can check that the QIR function `Hello_HelloQ` indeed appears in the `Hello.ll` file with that name.
* simulator invocation:
Here we create a Q# [full state simulator](https://docs.microsoft.com/azure/quantum/user-guide/machines/full-state-simulator) instance that will run our quantum program and register it with the current context.
Following this, everything is set up to call into Q# functions.
### Compiling the program
Multiple tools are available for this step, such as the LLVM static compiler + assembler + linker or the JIT compiler.
@ -491,13 +428,13 @@ Here, Clang is used again, this time to compile and link the `Hello.ll` Q# progr
Invoke the following command on Windows:
```powershell
clang++ qir/Hello.ll Main.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -l'Microsoft.Quantum.Qir.QSharp.Foundation' -o build/Hello.exe
clang++ qir/Hello.ll Main.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe
```
On Linux:
```bash
clang++ qir/Hello.ll Main.cpp -Wl,-rpath=build -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -l'Microsoft.Quantum.Qir.QSharp.Foundation' -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe
clang++ qir/Hello.ll Main.cpp -Wl,-rpath=build -Ibuild -Lbuild -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe
```
Parameters:
@ -521,13 +458,13 @@ The same can be done with the optimized QIR code.
On Windows:
```powershell
clang++ qir/Hello-dce-inline.ll Main.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -l'Microsoft.Quantum.Qir.QSharp.Foundation' -o build/Hello.exe && ./build/Hello.exe
clang++ qir/Hello-dce-inline.ll Main.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe && ./build/Hello.exe
```
On Linux:
```bash
clang++ qir/Hello-dce-inline.ll Main.cpp -Wl,-rpath=build -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -l'Microsoft.Quantum.Qir.QSharp.Foundation' -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe && ./build/Hello.exe
clang++ qir/Hello-dce-inline.ll Main.cpp -Wl,-rpath=build -Ibuild -Lbuild -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe && ./build/Hello.exe
```
As a last example, let's modify the Q# program `Program.qs` with a random bit generator and run through the whole process:
@ -556,10 +493,10 @@ Steps:
* optimize the code `clang -S qir/Hello.ll -O3 -emit-llvm -o qir/Hello-o3.ll`
* compile the code on Windows
```powershell
clang++ qir/Hello-o3.ll Main.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -l'Microsoft.Quantum.Qir.QSharp.Foundation' -o build/Hello.exe
clang++ qir/Hello-o3.ll Main.cpp -Ibuild -Lbuild -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe
```
or Linux
```bash
clang++ qir/Hello.ll Main.cpp -Wl,-rpath=build -Ibuild -Lbuild -l'Microsoft.Quantum.Qir.Runtime' -l'Microsoft.Quantum.Qir.QSharp.Core' -l'Microsoft.Quantum.Qir.QSharp.Foundation' -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe
clang++ qir/Hello.ll Main.cpp -Wl,-rpath=build -Ibuild -Lbuild -l'Microsoft.Quantum.Simulator.Runtime' -o build/Hello.exe
```
* simulate the program `./build/Hello.exe`

Просмотреть файл

@ -11,12 +11,6 @@ namespace Microsoft.Quantum.QsCompiler.Testing.Qir
{
public static class JitCompilation
{
[DllImport("Microsoft.Quantum.Qir.QSharp.Core", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateFullstateSimulatorC(long seed);
[DllImport("Microsoft.Quantum.Qir.Runtime", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] // TODO(#1569): Requires refactoring for Rust QIR RT.
public static extern void InitializeQirContext(IntPtr driver, bool trackAllocatedObjects);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SimpleFunction();
@ -79,13 +73,8 @@ namespace Microsoft.Quantum.QsCompiler.Testing.Qir
NativeLibrary.Load("omp", typeof(JitCompilation).Assembly, null);
}
// Explicitly load dependent libraries so that they are already present in memory when pinvoke
// triggers for the Microsoft.Quantum.Qir.QSharp.Core call below.
// Explicitly load dependent libraries so that they are already present in memory.
NativeLibrary.Load("Microsoft.Quantum.Simulator.Runtime", typeof(JitCompilation).Assembly, null);
NativeLibrary.Load("Microsoft.Quantum.Qir.Runtime", typeof(JitCompilation).Assembly, null);
NativeLibrary.Load("Microsoft.Quantum.Qir.QSharp.Foundation", typeof(JitCompilation).Assembly, null);
InitializeQirContext(CreateFullstateSimulatorC(0), true);
if (!File.Exists(pathToBitcode))
{
@ -111,9 +100,7 @@ namespace Microsoft.Quantum.QsCompiler.Testing.Qir
// Linux requires an additional explicit load of the libraries into MCJIT.
// Full paths are not needed since .NET already loaded these into program memory above,
// but without this explict load the JIT logic won't find them.
ExplicitLibraryLoad("libMicrosoft.Quantum.Qir.Runtime.so");
ExplicitLibraryLoad("libMicrosoft.Quantum.Qir.QSharp.Foundation.so");
ExplicitLibraryLoad("libMicrosoft.Quantum.Qir.QSharp.Core.so");
ExplicitLibraryLoad("libMicrosoft.Quantum.Simulator.Runtime.so");
}
var engine = modRef.CreateMCJITCompiler();

Просмотреть файл

@ -18,8 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Qir.Runtime" Version="0.25.228311-alpha" ExcludeAssets="compile" /> <!-- TODO(#1569): Requires refactoring for Rust QIR RT. -->
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.25.228311" ExcludeAssets="compile" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Quantum.Simulators" Version="0.27.238334" ExcludeAssets="compile" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="PrepareReferenceTests" Condition="'$(DesignTimeBuild)' != 'true' And $([MSBuild]::IsOsPlatform('OSX'))" BeforeTargets="CoreCompile">

Просмотреть файл

@ -162,7 +162,7 @@ type ExecutionTests(output: ITestOutputHelper) =
"interpolated string"
true or false, true, false, true, false
1, -1, 0
1.0, 2.0, 100000.0, 0.10000000000000001, -1.0, 0.0
1.0, 2.0, 100000.0, 0.1, -1.0, 0.0
Zero, One
PauliZ, PauliX, PauliY, [PauliI]
1..3, 3..-1..1, 0..-1..0