alpaka
alpaka copied to clipboard
Enabling backends from cmake scripts
In a cmake based project that requires e.g. the CUDA backend, I tried to enable it like this:
find_package(alpaka 0.9.0 QUIET)
if(NOT alpaka_FOUND)
message(STATUS "No alpaka install found, disabling example")
else()
set(alpaka_ACC_GPU_CUDA_ENABLE ON CACHE BOOL "Enable the CUDA GPU back-end" FORCE)
alpaka_add_executable(example example.cu)
target_link_libraries(example PUBLIC alpaka::alpaka)
While this turns on the flag alpaka_ACC_GPU_CUDA_ENABLE
, the backend will not be enabled unless the user reconfigures with cmake. This is because backend enabling is handled as part of find_package(alpaka 0.9.0 QUIET)
.
A possible workaround is to turn on the backend before the find_package
call:
set(alpaka_ACC_GPU_CUDA_ENABLE ON CACHE BOOL "Enable the CUDA GPU back-end" FORCE)
find_package(alpaka 0.9.0 QUIET)
if(NOT alpaka_FOUND)
message(STATUS "No alpaka install found, disabling example")
else()
alpaka_add_executable(example example.cu)
target_link_libraries(example PUBLIC alpaka::alpaka)
However, now there is also a cmake variable alpaka_ACC_GPU_CUDA_ENABLE
even if alpaka is not found, which is undesirable.
I wonder whether there is a better solution? Or whether there is a best practice on how to enable backends from within cmake scripts?
You can use unset in the if branch, to remove the alpaka variables.
I'm not sure, if there is a good approach to enable acc's afterwards. At least, I don't believe this was not respected when the CMake was written. Personal, I avoid to reconfigure CMake projects, because CMake is a state automate and if you re run CMake configure again, it is different to the initial configuration because of cached variables. That makes hard to follow, what CMake is really doing.
Maybe we should change the CMake to a stateless implementation to solve this problem.
At the moment I think the second solution from @bernhardmgruber is the correct way to enable/disable backends. IMO the right way would be that alpaka is providing targets for all available backends and a variable to force disable the target creation for backends. see: https://github.com/alpaka-group/alpaka/issues/919#issuecomment-919269026
You can use unset in the if branch, to remove the alpaka variables.
Fair enough :)
IMO the right way would be that alpaka is providing targets for all available backends ...
So IIUC, that should look like this then:
find_package(alpaka 0.9.0 QUIET)
if(NOT alpaka_FOUND)
message(STATUS "No alpaka install found, disabling example")
else()
alpaka_add_executable(example example.cu)
target_link_libraries(example PUBLIC alpaka::alpaka alpaka::cuda) # link also CUDA target
So we would have an additional target per backend that is always there (even if e.g. alpaka_ACC_GPU_CUDA_ENABLE
is OFF
)? And if I link that target, it would turn that backend on? That would work I guess.
Yes, something like this (we would also try to remove the alpaka_add_executable
and use the normal add_executable
).
Actual, I didn't thought about this yet. I'm not sure, if CMake is lazy and you can use a target in a if branch, which is not defined. But if it is not possible, we would through an error, if you use alpaka::cuda
and the backend is not enabled. We would also provide a possibility to check, if a backend is enable, e.g.: if(alpaka_is_enabled(alpaka::cuda))
.
We had also the idea to create an target, which works like the current implementation, means use all activated backends.
So we would have an additional target per backend that is always there (even if e.g. alpaka_ACC_GPU_CUDA_ENABLE is OFF)?
No each variable should have 3 states. ON
, OFF
and, AUTO
. With AUTO
the target will be there if all dependencies are fulfilled. ON
will enforce that the target is there if a dep is not fulfilled CMake will throw an error. OFF
will force disable the target. This is how PIConGPU and openPMD-api is handling optional dependencies and will follow the variable behavior we already use in alpaka e.g. for compiler flags.
@SimeonEhrig the existence of targets can be checked via if(TARGET alpaka::cuda)
. A target will only exists if all dependencies are available, else it would make no sense to have the target.