Add a backend extension#
The include/ginkgo/extensions/ tree (with its tests under
extensions/) holds user-facing headers that depend on third-party
packages and bridge them with Ginkgo. They are not “backends” in the
kernel-dispatch sense; those live under cuda/, hip/, omp/,
dpcpp/.
Shipped extensions:
Extension |
Shape |
Public header |
|---|---|---|
Kokkos |
Header-only |
|
nlohmann JSON config |
Header-only |
|
yaml-cpp YAML config |
Header-only |
|
The extensions shipped with Ginkgo are header-only: pure bridging
headers that consumers #include. Ginkgo installs them with the other
public headers, and the consumer’s build links the third-party package.
What an extension provides#
Every extension:
Lives under
namespace gko::ext::<name>(e.g.gko::ext::kokkos,gko::ext::config). Internal details go in adetailsub-namespace.Has a public header tree under
include/ginkgo/extensions/<name>/and, for larger extensions, an umbrella headerextensions/<name>.hppthat pulls in the sub-headers.Optionally has a
config.hpp.intemplate processed byconfigure_fileso the extension can see Ginkgo’s compile-time switches.Has its tests under
extensions/test/<name>/. The Kokkos tests are built when Kokkos is found; the config tests are built whenever tests are enabled, because yaml-cpp and nlohmann_json are fetched when missing.
Anatomy of the Kokkos extension#
Umbrella header:
// include/ginkgo/extensions/kokkos.hpp
#include <ginkgo/extensions/kokkos/config.hpp>
#include <ginkgo/extensions/kokkos/spaces.hpp>
#include <ginkgo/extensions/kokkos/types.hpp>
The two substantive sub-headers do the bridging:
kokkos/spaces.hpp: definesdetail::compatible_space<MemorySpace, ExecType>, astd::integral_constant<bool, ...>that answers “can this Kokkos memory space be safely accessed from this Ginkgo executor?”.map_datachecks it throughassert_compatibility, which throws at run time (GKO_THROW_IF_INVALID) for a mismatched pair. The header also providescreate_executor,create_default_executorandcreate_default_host_executor, which build a Ginkgo executor matching a Kokkos execution space.kokkos/types.hpp: definesdetail::value_type<T>::type(Kokkos::complex<T>forstd::complex<T>, identity otherwise) andmap_data, which wraps agko::array<T>ormatrix::Dense<T>storage region as a non-owning KokkosView.
The config.hpp.in is processed by Ginkgo’s top-level CMakeLists:
configure_file(
${Ginkgo_SOURCE_DIR}/include/ginkgo/extensions/kokkos/config.hpp.in
${Ginkgo_BINARY_DIR}/include/ginkgo/extensions/kokkos/config.hpp
@ONLY
)
It substitutes the GINKGO_EXTENSION_KOKKOS_CHECK_TYPE_ALIGNMENT CMake
option into the generated config.hpp, so value_type can verify the
alignment of Ginkgo and Kokkos types at compile time.
Anatomy of the config readers#
The two config extensions turn a parsed file into a
gko::config::pnode property tree, which the runtime registry then
turns into solver and preconditioner factories.
config/json_config.hpp:gko::ext::config::parse_json,parse_json_fileandparse_json_string, built onnlohmann::json.config/yaml_config.hpp:gko::ext::config::parse_yamlandparse_yaml_file, built on yaml-cpp, including YAML anchors and<<merge keys.
Each header includes the third-party header directly, so a consumer’s
build links nlohmann_json or yaml-cpp. Ginkgo’s own tests link the
yaml-cpp::yaml-cpp and nlohmann_json::nlohmann_json targets.
How extensions plug into the build#
The top-level Ginkgo CMakeLists.txt calls
add_subdirectory(extensions) after the core build.
extensions/CMakeLists.txt adds the test/ subdirectory when
GINKGO_BUILD_TESTS=ON. The per-extension tests are registered in
extensions/test/CMakeLists.txt, which discovers the third-party
dependency and adds the matching subdirectory:
# extensions/CMakeLists.txt
if(GINKGO_BUILD_TESTS)
add_subdirectory(test)
endif()
# extensions/test/CMakeLists.txt
find_package(Kokkos 4.1.00 QUIET)
if(Kokkos_FOUND)
add_subdirectory(kokkos)
endif()
add_subdirectory(config)
Header-only extensions build nothing themselves: consumers #include
the header, and Ginkgo’s install step copies the *.hpp files of the
source and binary include/ trees, which installs the generated Kokkos
config.hpp and leaves config.hpp.in in the source tree. The Kokkos
tests are skipped when Kokkos is missing.
extensions/test/config/CMakeLists.txt calls
find_package(yaml-cpp 0.8.0 QUIET) and fetches yaml-cpp with
FetchContent when it is missing; nlohmann_json is fetched from
third_party/ in the same way.
Adding a new extension#
For a header-only extension <myext>:
include/ginkgo/extensions/<myext>.hpp ← umbrella include
include/ginkgo/extensions/<myext>/types.hpp ← per-concern headers
include/ginkgo/extensions/<myext>/spaces.hpp
include/ginkgo/extensions/<myext>/config.hpp.in ← optional, if you need
Ginkgo build-flag knowledge
extensions/test/<myext>/CMakeLists.txt ← links your third-party dep
extensions/test/<myext>/<test1>.cpp ← tests live here
CMake wiring:
If
<myext>needs a generatedconfig.hpp, add aconfigure_fileblock to the top-levelCMakeLists.txtnext to the Kokkos one.Add your test subdirectory to
extensions/test/CMakeLists.txt, behind afind_package(<MyExtDep> QUIET)check as for Kokkos.In
extensions/test/<myext>/CMakeLists.txt, linkGinkgo::ginkgoplus the third-party target throughginkgo_create_test(... ADDITIONAL_LIBRARIES ...), asextensions/test/configdoes.
An extension that needs a compiled library would add its own
extensions/<area>/ directory with a CMake target, link it publicly to
ginkgo, wire it from extensions/CMakeLists.txt and install it. That
layout is a contribution you would design together with the
maintainers.
Design guidance: vendor-library wrappers#
If you add a LinOp that wraps a vendor library, build it like any
other LinOp (see Add a new solver or Add a new
preconditioner for the factory / parse
scaffolding) and choose its home by what it wraps:
In
core/: when the vendor path is one implementation among several for a type that Ginkgo already exposes. Example:solver::LowerTrs/solver::UpperTrstake analgorithmparameter.trisolve_algorithm::sparselib(the default) uses the vendor library (cuSPARSE on CUDA, hipSPARSE on HIP), andtrisolve_algorithm::syncfreeruns Ginkgo’s own kernel on CUDA. The vendor calls live incuda/solver/lower_trs_kernels.cuetc., gated by the executor type.In
extensions/: when the integration is a bridge to a third-party library and not a Ginkgo type, as for the Kokkos and JSON/YAML config headers.
See also
Add a new solver: LinOp + Factory + parse scaffolding that any vendor-backed solver also needs.
Add a new preconditioner: same scaffolding, no workspace.
Configure via JSON: what the JSON config extension unlocks for the runtime registry.