Download and build¶
The easiest way to build qdp-jit together with Chroma is the build package at github.com/fwinter/package. Its scripts download the sources of LLVM, QMP, qdp-jit and Chroma, and build and install them in order, for one GPU architecture.
Prerequisites¶
Before you start, make sure the following are available, on a cluster usually by loading the corresponding modules:
- the GPU software stack: the CUDA toolkit (NVIDIA), ROCm (AMD) or oneAPI with Level Zero (Intel);
- an MPI installation with its compiler wrappers (
mpicxx,mpicc); - a C++ compiler, CMake,
gitandwget.
Get the package:
git clone https://github.com/fwinter/package.git
cd package
1. Choose the GPU architecture¶
Each architecture has its own download script and its own directory of build scripts:
| GPU | Download script | Directory |
|---|---|---|
| NVIDIA | download_sources_cuda.sh |
cuda/ |
| AMD | download_sources_rocm.sh |
rocm/ |
| Intel | download_sources_intel.sh |
level-zero/ |
The examples below are for NVIDIA GPUs; replace cuda by the script and
directory of your architecture.
2. Download the sources¶
From the root of the package, run the download script:
./download_sources_cuda.sh
It clones QMP, qdp-jit and Chroma and downloads the LLVM sources, all into
src/. Unpacking LLVM takes a moment.
3. Configure the environment¶
Change to the directory of your architecture and edit env.sh:
cd cuda
env.sh is read by every build script. Set the compilers to your MPI
compiler wrappers:
export CXX=mpicxx
export CC=mpicc
and add anything else your system needs, such as module load lines or paths.
On some systems the wrappers have other names; on Cray systems, for example,
they are CC and cc.
The directory also holds env_*.sh files for particular machines (for example
env_perlmutter.sh in cuda/, env_frontier.sh in rocm/).
Use one of them as a starting point if your machine is among them.
The rest of env.sh sets where the build happens. Keep it unless you want
another location:
| Variable | Default | Contents |
|---|---|---|
SRCROOT |
../src |
the sources downloaded in step 2 |
BUILDROOT |
./build |
one build directory per package |
INSTALLROOT |
./install |
one install directory per package |
env.sh also adds the LLVM libraries, install/llvm-22/lib, to
LD_LIBRARY_PATH. The package builds LLVM as shared libraries, so qdp-jit
programs such as chroma need this path at run time as well.
A job script can therefore source the same env.sh to set up everything:
the modules, the environment variables and the library search path. env.sh
takes its paths from the current directory, so change to the architecture
directory before sourcing it:
#!/bin/bash
#SBATCH ...
cd /path/to/package/cuda
source ./env.sh
cd /path/to/run
srun ${INSTALLROOT}/chroma/bin/chroma -i input.xml -geom 1 1 1 4
4. Check the host CPU architecture¶
Besides the GPU target, LLVM must be built for the CPU of the machine qdp-jit
will run on: qdp-jit compiles expressions on scalars for the host CPU (the
host JIT, on by default). Before building, check whether the compute nodes
have x86 or ARM CPUs, and set LLVM_TARGETS_TO_BUILD in build_llvm-22.sh
accordingly:
| GPU | x86 host | ARM host |
|---|---|---|
| NVIDIA | "NVPTX;X86" |
"NVPTX;AArch64" |
| AMD | "AMDGPU;X86" |
"AMDGPU;AArch64" |
| Intel | "X86" |
"AArch64" |
The scripts are set up for x86 hosts. For a machine with ARM CPUs, such as
NVIDIA Grace, change X86 to AArch64. Intel GPUs need no GPU target in
LLVM, because their kernels are translated to SPIR-V by a separate tool.
5. Build¶
./build_all.sh
build_all.sh runs the build scripts in order: LLVM, QMP, qdp-jit
(build_qdpxx.sh) and Chroma (build_chroma.sh); in level-zero/ it also
builds the SPIR-V translator after LLVM. Building LLVM takes the
longest. When it has finished, install/ holds:
| Directory | Contents |
|---|---|
install/llvm-* |
LLVM |
install/qmp |
QMP |
install/qdpxx |
qdp-jit |
install/chroma |
Chroma, with the executable install/chroma/bin/chroma |
Rebuilding a part¶
Each package has its own build script, which can be run on its own, from the architecture directory. A script removes its build directory first, so each run is a clean build.
After a change to qdp-jit, rebuild qdp-jit and then Chroma, which is compiled against qdp-jit's headers:
./build_qdpxx.sh
./build_chroma.sh
Build options of qdp-jit¶
build_qdpxx.sh configures qdp-jit with CMake. To change an option, edit the
cmake command in that script. The most important options:
| Option | Values | Description |
|---|---|---|
QDP_ENABLE_BACKEND |
CUDA, ROCM, L0 |
the GPU backend |
QDP_PRECISION |
single, double (default) |
the precision of Real, LatticeFermion, … |
QDP_LAYOUT |
cb2 (default), lexico, cb3d |
the site layout, see Layouts |
QDP_ND, QDP_NC, QDP_NS |
4, 3, 4 (default) | the number of dimensions, and the initial current shape (Ns, Nc), see Shape |
QDP_ENABLE_HOST_COMPILER |
ON (default), OFF |
also JIT-compile scalar expressions for the CPU; needs the host CPU target in LLVM, see step 4 |
LLVM_DIR |
a path | the LLVM installation to use; qdp-jit needs LLVM 22 or newer. With the ROCm backend it defaults to the LLVM that comes with ROCm |
Using qdp-jit in your own program¶
qdp-jit installs a CMake package configuration. A CMake project needs C and
C++ enabled (QMP looks for MPI's C interface); linking QDPXX::qdp compiles it
as C++20:
project(my_program C CXX)
find_package(QDPXX REQUIRED)
target_link_libraries(my_program QDPXX::qdp)
Configure it with the locations of qdp-jit, QMP and LLVM, as build_chroma.sh
does for Chroma:
cmake <source> \
-DQDPXX_DIR=<package>/cuda/install/qdpxx/lib/cmake/QDPXX \
-DQMP_DIR=<package>/cuda/install/qmp/lib/cmake/QMP \
-DLLVM_DIR=<package>/cuda/install/llvm-<version>/lib/cmake/llvm
To run on several GPUs, start one MPI rank per GPU and give the grid of ranks
with -geom; see Command-line options.