Cristi
Cristi

Reputation: 718

Using CUDA based library code in C++ project

I used the example create cuda library with cmake to create a small cuda based library. The library contains a class called CudaImage which is supposed to run a Cuda kernel on an image.

CMakeLists is as follows:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(cudaMPbTools LANGUAGES CXX CUDA)

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../common
)

add_library(cudaMPbTools STATIC
cudaimage.cu
cudaimage.h
cvector.h
cvector.cpp
)
target_link_libraries(cudaMPbTools libCommon)
target_compile_features(cudaMPbTools PUBLIC cxx_std_11)
set_target_properties( cudaMPbTools
                   PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

cudaimage.h contains the following code:

class CudaImage {
public:
CudaImage(unsigned char* image_data, int image_width, int image_height, int     scale);

private:
__device__
void addToHistoArray(int val, int i, int j);
};

The libraries compiles fine with cmake, but now I am trying to use the CudaImage class inside a main.cpp outside the library:

CudaImage cudaImg(img1.data, img1.cols, img1.rows, 10);

but this generates a compilation error in the main project because it does not recognize the device keyword in the cudaimage.h.

CMakeLists.txt for the main project is something like:

cmake_minimum_required (VERSION 3.10)
project (mPb)
cmake_policy(SET CMP0020 NEW)

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../common
${CMAKE_CURRENT_SOURCE_DIR}/../cudaMPbTools
${Qt5Core_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS})

set(MPB_SRCS    
main.cpp
pbdetector.cpp
)

set(MPB_HEADR
pbdetector.h)

add_executable(mPb ${MPB_SRCS} ${MPB_HEADR})
target_link_libraries(mPb
libCommon
${OpenCV_LIBS}
cudaMPbTools)

qt5_use_modules(mPb Core)

Can anyone give advice on this matter ? Is the CMakeLists.txt in the main project correct?

Update I extracted the function addToHistoArray from the class CudaImage and declared it as follows:

__device__ void addToHistoArray(struct CVector* dHalfDiscInfluencePoints, int   totalHalfInfluencePoints, unsigned int** dHistograms, int image_width, int image_height, int scale, int arcno, int val, int i, int j);

and I still cannot compile my project. I updated the source code in github as well.

Upvotes: 0

Views: 243

Answers (3)

Cristi
Cristi

Reputation: 718

I have found a solution such that my project compiles. It requires the following:

  • in cudaimage.h include cuda.h and cuda_runtime.h
  • in project mPb add cuda support
  • use the method of including cuda that was used before version 3.9 of cmake
  • in code changed signature of addToHistoArray as indicated by MSalters and L.C.

The CMake files look are for the library:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(cudaMPbTools)
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/../common
)
find_package(CUDA)
cuda_add_library(cudaMPbTools 
    cudaimage.cu
    cudaimage.h
    cvector.h
    cvector.cpp
    STATIC
)
target_link_libraries(cudaMPbTools libCommon ${CUDA_LIBRARIES}) 
target_compile_features(cudaMPbTools PUBLIC cxx_std_11)

and for project:

cmake_minimum_required (VERSION 3.10)
project (mPb)
find_package(CUDA)
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/../common
    ${CMAKE_CURRENT_SOURCE_DIR}/../cudaMPbTools
    ${Qt5Core_INCLUDE_DIRS}
    ${OpenCV_INCLUDE_DIRS}
    ${CUDA_INCLUDE_DIRS})
set(MPB_SRCS    
    main.cpp
    pbdetector.cpp
)
set(MPB_HEADR
pbdetector.h)
cuda_add_executable(mPb ${MPB_SRCS} ${MPB_HEADR})
target_link_libraries(mPb
    libCommon
    ${OpenCV_LIBS}
    cudaMPbTools)
qt5_use_modules(mPb Core)

Upvotes: 0

L.C.
L.C.

Reputation: 1145

As MSalters said, the problem is that device methods are meant to be called from GPU to be executed on GPU. I'm not sure that's what you meant to do. If not, you should read this: Difference between global and device functions

(sorry I can't comment posts yet)

Upvotes: 1

MSalters
MSalters

Reputation: 180305

__device__ void CudaImage::addToHistoArray(int val, int i, int j) is rather suspect. The whole point of a member function is that it has a this pointer, i.e. a CudaImage*. That is of course a host pointer (CudaImage lives on the CPU). So what's your __device__ (GPU) function trying to do with a host pointer?!

That it doesn't compile is a lucky side-effect. Presumably addToHistoArray doesn't need a CudaImage*, so it could have been a free function inside cudaimage.cu

Upvotes: 1

Related Questions