sdgaw erzswer
sdgaw erzswer

Reputation: 2382

Compiling/adding cuda code to existing project (CMake)

I am trying to port parts of an existing project to GPUs via CUDA code. I understand cmake has options (find_cuda...) to deal with .cu files separately, yet I am still trying to figure out how this ecosystem can be used in context of existing projects.

My question is the following. Let's say I have an existing C++ project with a cmake config file (CMakeLists). What is the current practice to eleganly (if possible) include CUDA kernels? Can CMakeLists be constructed in a way, .cu files are compiled only if GPU is present?

My current idea is to create a separate folder, where only CUDA related code exists and then compile this as a static library. Is that the way to do it?

Upvotes: 6

Views: 2133

Answers (1)

dari
dari

Reputation: 2455

Having the CUDA files in separate folders is my recommended way but not required. The basic principle is that you collect all .cu files in a CMake variable (let's call it CUDA_SRC) and all .cpp files in a different variable (call it SRC). Now you compile both files and put them together. The variable CUDA_FOUND provided by find_package(CUDA) can be used to determine if CUDA is installed on your system. The use of a static library for the cuda files is not required, but i'll show you both ways here.

In your top level cmake file you want to have something like this to find CUDA and set some nvcc flags:

find_package(CUDA QUIET)
if(CUDA_FOUND)
    include_directories(${CUDA_INCLUDE_DIRS})
    SET(ALL_CUDA_LIBS ${CUDA_LIBRARIES} ${CUDA_cusparse_LIBRARY} ${CUDA_cublas_LIBRARY})
    SET(LIBS ${LIBS} ${ALL_CUDA_LIBS})
    message(STATUS "CUDA_LIBRARIES: ${CUDA_INCLUDE_DIRS} ${ALL_CUDA_LIBS}")
    set(CUDA_PROPAGATE_HOST_FLAGS ON)
    set(CUDA_SEPARABLE_COMPILATION OFF)
    list( APPEND CUDA_NVCC_FLAGS -gencode=arch=compute_30,code=compute_30 )
    list( APPEND CUDA_NVCC_FLAGS -gencode=arch=compute_52,code=sm_52 )
endif()

With static CUDA library

if(CUDA_FOUND)
     #collect CUDA files
     FILE(GLOB_RECURSE CUDA_SRC  *.cu)
     #build static library
     CUDA_ADD_LIBRARY(my_cuda_lib ${CUDA_SRC} STATIC)
     SET(LIBS ${LIBS} ${my_cuda_lib})
endif()

#collect cpp files
FILE(GLOB_RECURSE SRC  *.cpp)

#compile .cpp files and link it to all libraries
add_executable(${PROG_NAME} ${SRC})
target_link_libraries(${PROG_NAME} ${LIBS} )

Without Static CUDA lib

FILE(GLOB_RECURSE SRC  *.cpp)

if(CUDA_FOUND)
    #compile cuda files and add the compiled object files to your normal source files
    FILE(GLOB_RECURSE CUDA_SRC  *.cu)
    cuda_compile(cuda_objs ${CUDA_SRC})
    SET(SRC ${SRC} ${cuda_objs})
endif()

#compile .cpp files and link it to all libraries
add_executable(${PROG_NAME} ${SRC})
target_link_libraries(${PROG_NAME} ${LIBS} )

Upvotes: 8

Related Questions