libparallelproj is a high-performance library for 3D forward and backward projection, supporting both CUDA and non-CUDA builds and a minimal python interface.
Official documentation: https://libparallelproj.readthedocs.io
- Installation
- Build Requirements
- Building and Testing
- Python Interface
- Using libparallelproj from another CMake project
We recommend to install pre-compiled versions of libparallelproj from conda-forge
where cuda 12/13 and non-cuda builds are available (see official docs).
The recommended way to build from source is with pixi, which manages all toolchain and library dependencies (compiler, CMake, Ninja, nanobind, CUDA toolkit, …) automatically.
If you prefer to drive CMake directly, install the dependencies listed below yourself and use the presets in CMakePresets.json.
| Category | Requirement |
|---|---|
| Build tools | CMake ≥ 3.18, Ninja, C++17 compiler |
| Non-CUDA builds | OpenMP |
| Python extension | Python ≥ 3.12, nanobind |
| CUDA builds | CUDA Toolkit 12 or 13 |
| Testing | pytest, numpy, array-api-compat, array-api-strict, pytorch |
| Documentation | Doxygen, Sphinx ≥ 8, breathe, furo, sphinx-gallery, … |
pixi resolves and installs all dependencies into isolated environments.
Each environment (default, cuda12, cuda13, docs) exposes the same set of tasks:
Non-CUDA build (CPU / OpenMP, all platforms):
pixi run -e default configure # cmake --preset non-cuda
pixi run -e default build # cmake --build build
pixi run -e default test # ctest + pytest
pixi run -e default install # cmake --install buildCUDA build (requires a CUDA 12 or 13 driver on the machine):
# CUDA 12
pixi run -e cuda12 configure # cmake --preset cuda12
pixi run -e cuda12 build
pixi run -e cuda12 test
# CUDA 13
pixi run -e cuda13 configure # cmake --preset cuda13
pixi run -e cuda13 build
pixi run -e cuda13 testAll available tasks:
| Task | Description |
|---|---|
configure |
CMake configure (uses the environment's preset) |
build |
CMake build |
test-cpp |
C++ tests via ctest |
test-python |
Python tests via pytest |
test |
Both test suites |
install |
cmake --install |
uninstall |
Remove installed files (default env only) |
The default environment additionally provides configure-coverage, test-python-cov, and
collect-coverage-cpp for coverage reporting.
Install the dependencies listed above yourself, then use the CMake presets directly:
# Non-CUDA
cmake --preset non-cuda
cmake --build build
ctest --output-on-failure --test-dir build
# CUDA 12
cmake --preset cuda12
cmake --build build-cuda12
# CUDA 13
cmake --preset cuda13
cmake --build build-cuda13See CMakePresets.json for all preset options.
- Both
cuda12andcuda13presets useCMAKE_CUDA_ARCHITECTURES=native. For builds targeting multiple GPU generations, override withallorall-major— see the CMake docs. - The Python extension build can be disabled by passing
-DBUILD_PYTHON=OFFto the configure step.
With pixi (recommended):
pixi run -e docs build-docsThis runs the full chain: CMake configure → Doxygen XML → full project build → sphinx-build.
The output is written to docs/_build/html.
Without pixi: install the documentation dependencies and run:
cd docs && make htmlAfter installing libparallelproj, downstream CMake projects can locate it via:
find_package(parallelproj CONFIG REQUIRED)This provides the imported CMake target:
parallelproj::parallelprojwhich should be linked to your executable or library.
cmake_minimum_required(VERSION 3.18)
project(my_project LANGUAGES C CXX)
find_package(parallelproj CONFIG REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE parallelproj::parallelproj)If libparallelproj was installed into a non-standard location, point CMake to the installation prefix:
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/libparallelproj/installCMake will then look for the installed package configuration files in the corresponding install tree.
You can request a minimum version in find_package, for example:
find_package(parallelproj 2.0 CONFIG REQUIRED)The exported package version is numeric, for example 2.0.2, so standard CMake version matching works as expected.
After calling
find_package(parallelproj CONFIG REQUIRED)the following variables are available:
-
PARALLELPROJ_CUDA1iflibparallelprojwas built with CUDA support, otherwise0 -
PARALLELPROJ_VERSIONNumeric package version, for example2.0.2 -
PARALLELPROJ_INCLUDE_DIRSInstall include directory -
PARALLELPROJ_LIBRARY_DIRSInstall library directory -
PARALLELPROJ_VERSION_STRINGfull (more descriptive) package version containing labels for "dirty" versions, for example2.0.2-dirty-0-12ab3
In most cases, it is best to link against the imported target parallelproj::parallelproj rather than manually using include and library directory variables.
At CMake configure time:
find_package(parallelproj CONFIG REQUIRED)
if(PARALLELPROJ_CUDA)
message(STATUS "parallelproj was built WITH CUDA support")
else()
message(STATUS "parallelproj was built WITHOUT CUDA support")
endif()At runtime, the linked library can be queried via the C API:
#include "parallelproj.h"
if (parallelproj_cuda_enabled()) {
/* built with CUDA support */
} else {
/* built without CUDA support */
}
// full version string (the content of the VERSION file, e.g. "2.1.0" or "2.0.6.dev0")
const char* version = parallelproj_version();
// the numeric version components can be checked via
int pp_major_version = parallelproj_version_major();
int pp_minor_version = parallelproj_version_minor();
int pp_patch_version = parallelproj_version_patch();Note:
parallelproj_version()returns the full version string, which for dev builds includes a.devNsuffix (e.g.2.0.6.dev0).
The VERSION file at the repo root is the single source of truth for the
project version (PEP 440 style: X.Y.Z for releases, X.Y.Z.devN between
releases). CMake, the Python extension, the docs, and the conda recipes all
derive their version from it.
To make a release:
- open a release PR that bumps
VERSIONto the release version (e.g.2.1.0) and adds av2.1.0entry todocs/changelog.rst, then merge it - on the up-to-date
mainbranch runpixi run tag-release— this creates the annotated tagv2.1.0after validating that the working tree is clean,VERSIONis a non-dev version, and the changelog entry exists - publish the tag with
git push origin v2.1.0— thecheck_versionworkflow re-verifies that the tag matchesVERSION(mismatched tags fail CI before any release artifacts exist) - open a follow-up PR bumping
VERSIONto the next dev version (e.g.2.1.1.dev0)
The conda-forge feedstock derives its version from the release tag, which the
guards above guarantee to be identical to the VERSION file.
