Search code examples
c++cmakecudathrust

Thrust Static Assertion when using in cpp files


I am trying to compile and run a simple Cuda/thrust program, it works when the extension is .cu but it fails when the extension of source is .cpp. I already applied the required changes for cpp file in cmake but I am getting

error: static assertion failed: unimplemented for this system THRUST_STATIC_ASSERT_MSG

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(thrust_test LANGUAGES CXX CUDA)

find_package(CUDA 10.0 REQUIRED)
message(STATUS "CUDA ${CUDA_VERSION_STRING} at ${CUDA_TOOLKIT_ROOT_DIR}")
set(CUDA_LINK_LIBRARIES_KEYWORD PUBLIC)

include_directories(${CUDA_INCLUDE_DIRS})
link_directories(${CUDA_LIBRARY_DIRS})

set(CMAKE_CUDA_STANDARD 14)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CUDA_SEPARABLE_COMPILATION ON)

set_source_files_properties(
        main.cpp
        PROPERTIES
        CUDA_SOURCE_PROPERTY_FORMAT
        OBJ)

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} ${CUDA_LIBRARIES})

and the main.cpp:

__host__
__device__
int foo() {

    // generate random data serially
    thrust::host_vector<int> h_vec(100);
    std::generate(h_vec.begin(), h_vec.end(), rand);

    // transfer to device and compute sum
    thrust::device_vector<int> d_vec = h_vec;
    return thrust::reduce(d_vec.begin(), d_vec.end(), 0, thrust::plus<int>());
}

int main(void) {
    std::cout << "Thrust v" <<  THRUST_MAJOR_VERSION << "." << THRUST_MINOR_VERSION << std::endl;
    std::cout << foo() << std::endl;
    return 0;

}

Solution

  • Using the CUDA first-class language support in cmake (which is what you're doing when you establish that CUDA is a language used by your project) means that cmake is going to use the NVidia compiler for .cu files and some other compiler (such as gcc) on other files. When you use add_executable, cmake is also checking for .cu file extensions to ascertain how to properly link together your application.

    FindCUDA is an older set of tools that does not necessarily override these behaviors. You've gone 90% of the way toward replicating the first-class language features using the macros provided by FindCUDA, but add_executable fails to perform some necessary additional steps so your application bombs. Normally you'd use the CUDA_ADD_EXECUTABLE macro to designate a CUDA executable when using the FindCUDA tools.

    So here's what you should do: if you don't want your main file to have a .cu extension then just move your foo function to a separate .cu file with its own header that you include in main.cpp. You won't need to use set_source_files_properties since your device code will be properly segregated into its own .cu, allowing cmake to take the proper steps.

    Have a look at this article for more details and references: https://shawnliu.me/post/cuda-as-a-language-in-cmake/