alpaka icon indicating copy to clipboard operation
alpaka copied to clipboard

Enabling backends from cmake scripts

Open bernhardmgruber opened this issue 2 years ago • 5 comments

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?

bernhardmgruber avatar Aug 26 '22 13:08 bernhardmgruber

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.

SimeonEhrig avatar Aug 29 '22 06:08 SimeonEhrig

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

psychocoderHPC avatar Aug 29 '22 08:08 psychocoderHPC

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.

bernhardmgruber avatar Aug 29 '22 11:08 bernhardmgruber

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.

SimeonEhrig avatar Aug 29 '22 12:08 SimeonEhrig

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.

psychocoderHPC avatar Aug 30 '22 07:08 psychocoderHPC