![]() |
The Quantum Exact Simulation Toolkit v4.0.0
|
QuEST can be compiled with CMake to make a standalone executable, or an exported library, or a library installed on the system. Compiling is configured with variables supplied by the -D
flag to the CMake CLI. This page details how to compile QuEST for varying purposes and hardwares.
TOC:
See also:
cmake.md
for the full list of passable compiler variables.compilers.md
for a list of compatible and necessary compilers.qtechtheory.org
for help downloading the necessary compilers.launch.md
for a guide to executing the compiled application.
108
combinations! The compile.yml
workflow can serve as a concrete example of how to compile QuEST in a sanitised, virtual setting.Compilation is a two-step process which can generate lots of temporary files and so should be performed in a build/
folder to avoid clutter. From the QuEST/
root, run (in terminal):
or more safely from within the QuEST/build/
folder (as we from here assume):
-j
or --parallel
With no additional arguments, these commands compile min_example.cpp
into an executable min_example
in the build
folder which can be run via
You should expect to see
How boring! We must pass additional arguments in order to link QuEST to our own code; build other examples; run the unit tests; enable compiler optimisations; enable hardware acceleration; and integrate additional libraries and backends.
QuEST's source code is careful to enable a myriad of optimisations such as inlining, loop unrolling, auto-vectorisation and cache optimisations. To utilise them fully, we must instruct our compilers to enable them; like we might do with the -O3
flag when invoking a compiler like gcc
directly.
On most platforms (with the exception of Windows), this is automatic with the commands above, but can otherwise be forced by specifying CMAKE_BUILD_TYPE
at configure time:
When compiling on Windows however (using Visual Studio), or otherwise using a "[_multi-config generator_](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#other-generators)", we must always supply the build type at build time via config
:
Otherwise, such generators may default to the Debug
configuration which can produce executables over 10x
slower than Release
!
It is always safe to specify either flag even when not used, so one can gaurantee optimisations are enabled by cautiously performing:
Read more about CMake generator configurations here.
-D CMAKE_BUILD_TYPE=Release
as previously set.--config Release
must be re-specified (on Windows)QuEST can be pre-compiled and later linked to other binaries, or compiled directly alongside the user's source code. We focus on the latter use-case, common among scientists when writing simulation scripts. Users seeking to integrate QuEST into larger stacks are likely already familiar with linking libraries through CMake and should check out cmake.md
directly.
To compile a C
or C++
file such as
simply specify variables USER_SOURCE
and OUTPUT_EXE
at configure time:
where
myfile.c
is your C
source file (or myfile.cpp
if using C++
).myexec
is the output executable name, which will be saved in build
.To compile multiple dependent files, such as
simply separate them by ;
in USER_SOURCE
, wrapped in quotations:
Building then proceeds as normal, e.g.
and the executable can thereafter be run (from within build
) via
You can pass compiler and linker flags needed by your source files through the CMAKE_C_FLAGS
, CMAKE_CXX_FLAGS
and CMAKE_EXE_LINKER_FLAGS
CMake flags as detailed in the below section. Note however that if your configuration becomes complicated or your source code requires different C
/C++
standards than the QuEST source, you should consider separately compiling QuEST then linking it to your project as a library!
QuEST's numerical precision can be configured at compile-time, informing what type, and ergo how many bytes, are used to represent each qreal
(a floating-point real number) and qcomp
(a complex amplitude). This affects the memory used by each Qureg
, but also the user-facing qreal
and qcomp
types, as detailed below. Reducing the precision accelerates QuEST at the cost of worsened numerical accuracy.
Precision is set at configure-time using the FLOAT_PRECISION
cmake variable, taking on the values 1
, 2
(default) or 4
. For example
The values inform types:
Value | Precision | qreal | size | C (gcc ) qcomp | C (msvc ) qcomp | C++ qcomp | size |
---|---|---|---|---|---|---|---|
1 | Single | float | 4 bytes | float _Complex | _Fcomplex | std::complex<float> | 8 bytes |
2 | Double | double | 8 bytes | double _Complex | _Dcomplex | std::complex<double> | 16 bytes |
4 | Quadruple* | long double | <= 16 bytes | long double _Complex | _Lcomplex | std::complex<long double> | <= 32 bytes |
float
and double
are fixed by IEEE 754 format, the size of the long double
is platform and compiler dependent, and not necessarily a genuine quadruple-precision float. For example, the size of long double
in Clang can be set to 64
, 80
or 128
bits at compile-time. Never hardcode the size; always use sizeof
!1
or 2
since GPUs do not support quad precision.If multiple compilers are installed, you can choose which to use to compile your C
and C++
sources (the latter including the QuEST source) with respective configure-time commands:
replacing gcc
and g++
with e.g. clang
, cl
, icc
, ibm-clang
, or aliases for specific versions like gcc-8.5
.
These compilers will also be used as the host compilers (around which bespoke compilers wrap) when enabling GPU-acceleration or distribution.
nvcc
or mpicc
, via the above flags. See the respective GPU and MPI sections.Additional flags needed by your files can be passed to the C
and C++
compilers, and the linker (respectively), at configuration time via
For example,
Such flags are listed in cmake.md
. However, if your configuration is any more complicated or your source code requires different C
/C++
standards than the QuEST source, you should consider separately compiling QuEST then linking it to your source code as a library!
QuEST itself accepts a variety of its preprocessors (mostly related to testing) to be overriden by compiler flags, passed through custom CMake variables, as detailed in cmake.md
.
To compile all of QuEST's examples/
, use
The executables will be saved in the (current) build
directory, in a sub-directory structure mimicking the examples/
folder. They can be run by e.g.
as elaborated upon in launch.md
.
To compile QuEST's latest unit and integration tests, use
This will compile an executable tests
in subdirectory build/tests/
, which can be run as explained in launch.md
.
QuEST's deprecated v3 API has its own unit tests which can be additionally compiled (except on Windows) via
and run as explained in launch.md
.
Multithreading allows multiple cores of a CPU, or even multiple connected CPUs, to cooperatively perform and ergo accelerate QuEST's expensive functions. Practically all modern computers have the capacity for, and benefit from, multithreading. Note it requires that the CPUs have shared memory (such as through NUMA) and so ergo live in the same machine. CPUs on different machines, connected via a network, can be parallelised over using distribution.
QuEST uses OpenMP to perform multithreading, so accelerating QuEST over multiple CPUs or cores requires a compiler integrated with OpenMP. This is true of almost all major compilers - see a list of tested compilers in compilers.md
.
Clang
on MacOS requires use of the libomp
library, obtainable via Homebrew: To compile with multithreading, simply enable it during configuration:
This is in fact the default behaviour!
The number of threads over which to parallelise QuEST's execution is chosen through setting environment variables, like OMP_NUM_THREADS
, immediately before execution. See launch.md
for a general guide on multithreaded deployment.
QuEST's core functions perform simple mathematical transformations on very large arrays, and are ergo well suited to parallelisation using general purpose GPUs. This involves creating persistent memory in the GPU VRAM which mirrors the ordinary CPU memory in RAM, and dispatching the transformations to the GPU, updating the GPU memory. The greater number of cores and massive internal memory bandwidth of the GPU can make this extraordinarily faster than using multithreading.
QuEST supports parallelisation using both NVIDIA GPUs (using CUDA) and AMD GPUs (using HIP). Using either requires obtaining a specialised compiler and passing some GPU-specific compiler flags.
TODO!
- CUDA-compatible GPGPU
- nvcc compiler
- nvidia-smi
- minimum compute-capability
Check the CUDA compiler is installed correctly via
To compile your QuEST application with CUDA-acceleration, specify both
where $CC
is your GPU's compute capability (excluding the full-stop) which you can look up here. For example, compiling for the NVIDIA A100 looks like:
Building then proceeds as normal, e.g.
The compiled executable can be run like any other, though the GPU behaviour can be prior configured with environment variables. See launch.md
for a general guide on GPU-accelerated deployment.
TODO!
- ROCm
- ENABLE_HIP
- CMAKE_HIP_ARCHITECTURES
To compile your QuEST application with HIP-acceleration, specify both
where $TN
is your AMD GPU's LLVM target name. You can look this up here, or find the names of all of your local GPUs by running the ROCM agent enumerator command, i.e.
For example, compiling for the AMD Instinct MI210 accelerator looks like:
Building then proceeds as normal, e.g.
The compiled executable can be run like any other, though the GPU behaviour can be prior configured with environment variables. See launch.md
for a general guide on GPU-accelerated deployment.
When compiling for NVIDIA GPUs, you can choose to optionally enable cuQuantum. This will replace some of QuEST's custom GPU functions with cuStateVec routines which are likely to use tailored optimisations for your particular GPU and ergo run faster.
11
or 12
, and modern GPUs with a compute capability equal or above 7.0
(Volta
, Turing
, Ampere
, Ada
, Hopper
, Blackwell
). Check the updated requirements here.Using the cuQuantum backend requires separately downloading cuStateVec, as detailed here. Note it is not necessary to download cuTensorNet and cuDensityMatrix which are not used. We recommend downloading...
wget
as detailed here.After download and installation, and before compiling, you must set the CUQUANTUM_ROOT
environment variable to the cuQuantum download location:
Compilation is then simple; we specify ENABLE_CUQUANTUM
in addition to the above GPU CMake variables. For example
No other changes are necessary, nor does cuQuantum affect hybridising GPU acceleration and distribution. Launching the executable is the same as in the above section. See launch.md
.
Because statevectors grow exponentially with the number of simulated qubits, it is easy to run out of memory. In such settings, we may seek to use distribution whereby multiple cooperating machines on a network each store a tractable partition of the state. Distribution can also be useful to speed up our simulations, when the benefit of additional parallelisation outweighs the inter-machine communication penalties.
Enabling distribution requires compiling QuEST with an MPI compiler, such as those listed in compilers.md
. Test your compiler is working via
This command may differ on Intel MPI compilers; try
mpiicpc
.
Compiling QuEST's distributed backend is as simple as
Note that distributed executables are launched in a distinct way to the other deployment mods, as explained in launch.md
,
TODO!
- CUDA-aware MPI
- UCX
- launch flags
- checking via reportenv