Backend Selection

HASEonGPU uses alpaka to support different hardware backends.

Backend selection happens in two steps:

  • build-time backend selection

  • runtime backend selection

The build-time selection defines which alpaka backends are compiled into HASEonGPU. The runtime selection chooses one of these compiled and available backends for a specific simulation run.

HASEonGPU also builds a small backend-name library, HaseAlpakaBackendNames, which exposes the backend names detected by the compiled alpaka configuration. The Python interface uses this library to ask the installed build which backend names are valid on the current machine.

Build-time backend selection

The backends available at runtime depend on which alpaka backends were enabled when configuring HASEonGPU with CMake.

By default, HASEonGPU tries to detect supported backend dependencies such as CUDA, HIP, and TBB automatically. In the case of manual compilation: discrete/manual backend selection can be enabled with the CMake option HASE_SELECT_BACKEND_ALPAKA.

When manual selection is enabled, the existing alpaka CMake options can be used directly to select APIs, device kinds, and executors.

The relevant alpaka CMake options are documented in the alpaka CMake argument documentation.

For example, a manual CUDA-focused backend configuration can use:

cmake -S . -B build \
  -DHASE_SELECT_BACKEND_ALPAKA=ON \
  -Dalpaka_DEP_CUDA=ON \
  -Dalpaka_DEP_HIP=OFF \
  -Dalpaka_DEP_TBB=OFF \
  -Dalpaka_EXEC_CpuSerial=OFF

For more information about manually compiling HASEonGPU, see Compilation.

The exact set of available alpaka CMake options may change between alpaka versions. Therefore, the alpaka documentation should be treated as the primary reference for the supported backend configuration flags. It is possible to compile HASEonGPU with all backends provided by alpaka, including SYCL CPU/GPU backends. However, HASEonGPU is currently tested mainly with CUDA, HIP and host backends. Other backends should therefore be treated as experimental.

Backend-name helper library

During the CMake build, HASEonGPU also builds the shared library target HaseAlpakaBackendNames. This library links against the same HASEonGPU core and alpaka configuration as the simulation code. It enumerates alpaka’s enabled APIs and executors, filters them to backends for which a device can be created, and exposes the resulting names through a small C ABI.

For Python builds, CMake copies this library into the build package next to the Python extension:

build/python/HASEonGPU_Bindings/libHaseAlpakaBackendNames.so

On macOS the filename ends in .dylib. On Windows it is HaseAlpakaBackendNames.dll.

This library is useful because backend availability is not only a static CMake setting. A backend must be compiled in and usable on the machine where the code runs. For example, a CUDA backend name should only be reported when that backend was enabled in the build and alpaka can create a CUDA device.

If the Python package cannot find this helper library, build the target explicitly:

cmake --build build --target HaseAlpakaBackendNames

When the Python interface is built, the regular Python extension target also copies the helper library into the Python runtime package.

Runtime backend selection

At runtime, the --backend= command-line option, or the equivalent backend option in the MATLAB and Python interfaces, selects which of the compiled backends should be used for the simulation.

If the command-line binary is given a backend string that does not match any compiled backend with an available device, it prints the list of currently available runtime backends before exiting. Use one of those names as the --backend= value.

Backend names are constructed from alpaka’s api, deviceKind, and executor:

api_deviceKind_executor

Only backends that were enabled at build time can be selected at runtime.

Query available backends from Python

The Python front end exposes the CMake-built backend-name library through AlpakaBackends:

from HASEonGPU import AlpakaBackends

print(AlpakaBackends.all())

AlpakaBackends.known() is an alias for AlpakaBackends.all():

available = AlpakaBackends.known()
backend = available[0]

If a backend name is a valid Python identifier, it is also available as a class attribute:

backend = AlpakaBackends.Host_Cpu_CpuSerial

The returned strings are the values to pass to the new Python interface:

from HASEonGPU import PhiASE

phi_ase = PhiASE(
    spectralProperties=spectra,
    backend=AlpakaBackends.Host_Cpu_CpuSerial,
    parallelMode="single",
)

or to the command-line binary:

./build/calcPhiASE --backend=Host_Cpu_CpuSerial ...

If importing AlpakaBackends raises an error about the backend-name library, the Python package can see the Python files but not the compiled helper library. Build HaseAlpakaBackendNames and make sure the generated library is either installed with the Python package or present under build/python/HASEonGPU_Bindings.

The available APIs, device kinds, and executors are documented in the alpaka cheatsheet.

For a more detailed explanation of alpaka devices and backend selection, see the alpaka device documentation.