CUDA 链接错误(Lib 到 Dll)

Posted

技术标签:

【中文标题】CUDA 链接错误(Lib 到 Dll)【英文标题】:CUDA Link Error (Lib to Dll) 【发布时间】:2015-05-19 08:24:51 【问题描述】:

我正在尝试创建一个能够在多个游戏引擎中使用 CUDA 代码的框架。为了能够与所有需要的引擎进行通信,框架由两个主要部分组成。一个 Lib 和一个 DLL。 Lib 包含所有功能(CUDA 和常规 C++),DLL 用作从 Lib 调用函数的桥梁。

现在,一切正常,直到我包含了一个 .cu 文件。当我正在构建时,我收到以下错误:

Error   3   error LNK2019: unresolved external symbol _Add2And7 referenced in function "public: void __thiscall PerceptorHost::UpdatePerceptorHost(void)" (?UpdatePerceptorHost@PerceptorHost@@QAEXXZ)  D:\_Professional\DAE_Research\2_Projects\PWO_ePerceptor\Source\build\src\Native_ePerceptor_Dll\Native_ePerceptor_Lib.lib(PerceptorHost.obj) Native_ePerceptor_Dll

当我查看构建日志时,Lib 构建良好(Native_ePerceptor_Lib.lib)。是 DLL 失败了。

最后但同样重要的是,必须使用 CMake 创建项目(以便能够处理不同的设置)。您可以在下面找到 .cu、Lib .cpp 和 Dll .cpp 的 sn-ps。我浏览了整个互联网以找到解决方案,但大多数解决方案都与一个项目中的问题有关,而不是与库有关。我现在非常绝望,所以我希望你们中的一些人能指出问题所在,并希望有什么可能的解决方案。 还有一件事,我很确定所有必要的库都包括在内(cudart、cuda)。

Kernel.cu

#include <cuda\cuda_runtime.h>

__global__ void add(int a, int b, int *c) 

    *c += a + b;
    printf("%i + %i = %i \n", a, b, *c);


extern "C" void Add2And7(int *c)

    int *dev_c;

    //Allocate GPU memory
    cudaMalloc((void**)&dev_c, sizeof(int));

    add <<<1, 1>>>(2, 7, dev_c);

    //Copy GPU to CPU
    cudaMemcpy(c, dev_c, sizeof(int),
        cudaMemcpyDeviceToHost);

    //printf("number is %u \n", &c);

    //Free allocated GPU memory
    cudaFree(dev_c);

PerceptorHost.cpp

//Forward declaration
extern "C" void Add2And7(int *c);

void PerceptorHost::UpdatePerceptorHost()

    if (!g_bIsBooted)
        return;

    if (!m_bTestKernel)
    
        int output = 0;
        Add2And7(&output);
        printf("2 + 7 = %i \n", output);
        m_bTestKernel = true;
    

DLL.cpp

extern "C" NATIVEDLL_API void __cdecl UpdatePerceptorHost()

    PERCEPTORHOST->UpdatePerceptorHost(); //Update the PerceptorHost and all it's managers

CMAKE

########################################################################
# Add all source files to variables
# CPU Source Files
FILE(GLOB SRCS *.cpp)
FILE(GLOB HDRS *.h )
FILE(GLOB CUDA_HDRS 
        $CMAKE_SOURCE_DIR/include/cuda/*.h)
FILE(GLOB CALIBRATION_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Calibration/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Calibration/*.h)     
FILE(GLOB CORE_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Core/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Core/*.h)   
FILE(GLOB DATAPROVIDER_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Data/DataProvider/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Data/DataProvider/*.h)
FILE(GLOB RESOURCEMANAGER_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Data/ResourceManager/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Data/ResourceManager/*.h)       
FILE(GLOB DEBUG_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Debug/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Debug/*.h)  
FILE(GLOB EXCEPTION_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Exceptions/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Exceptions/*.h)
FILE(GLOB HELPERS_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/Helpers/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/Helpers/*.h)        
FILE(GLOB VIDEOWRITER_FILES 
        RELATIVE $CMAKE_CURRENT_SOURCE_DIR
        $CMAKE_CURRENT_SOURCE_DIR/VideoWriter/*.cpp
        $CMAKE_CURRENT_SOURCE_DIR/VideoWriter/*.h)
# GPU Source Files      
FILE(GLOB GPU_HELPERS_FILES
        $CMAKE_CURRENT_SOURCE_DIR/Helpers/*.cuh
        $CMAKE_CURRENT_SOURCE_DIR/Helpers/*.cu)       

########################################################################
# Group all source files
SOURCE_GROUP("Calibration" FILES $CALIBRATION_FILES)
SOURCE_GROUP("Core" FILES $CORE_FILES)
SOURCE_GROUP("DataProvider" FILES $DATAPROVIDER_FILES)
SOURCE_GROUP("ResourceManager" FILES $RESOURCEMANAGER_FILES)
SOURCE_GROUP("Debug" FILES $DEBUG_FILES)
SOURCE_GROUP("Exceptions" FILES $EXCEPTION_FILES)
SOURCE_GROUP("Helpers" FILES $HELPERS_FILES)
SOURCE_GROUP("VideoWriter" FILES $VIDEOWRITER_FILES)

########################################################################
# Set this part as static lib
IF (D_ENABLE_LIBRARY_CUDA)
CUDA_ADD_LIBRARY(Native_ePerceptor_Lib
    $CUDA_HDRS
    $CALIBRATION_FILES
    $CORE_FILES
    $DATAPROVIDER_FILES
    $RESOURCEMANAGER_FILES
    $DEBUG_FILES
    $EXCEPTION_FILES
    $HELPERS_FILES
    $VIDEOWRITER_FILES
    $SRCS
    $HDRS
    $GPU_HELPERS_FILES
    )
ELSE()
    ADD_LIBRARY(Native_ePerceptor_Lib
    $CUDA_HDRS
    $CALIBRATION_FILES
    $CORE_FILES
    $DATAPROVIDER_FILES
    $RESOURCEMANAGER_FILES
    $DEBUG_FILES
    $EXCEPTION_FILES
    $HELPERS_FILES
    $VIDEOWRITER_FILES
    $SRCS
    $HDRS
    )
ENDIF()

########################################################################
# Add preprocessor defines
IF (D_ENABLE_LIBRARY_CUDA)
    CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11 FATAL_ERROR)
    FIND_PACKAGE(CUDA REQUIRED)
    INCLUDE_DIRECTORIES(
        $CUDA_INCLUDE_DIRS
    )
    set(CUDA_ENABLED ON)
    add_definitions(-DCUDA_ENABLED=1)
ENDIF (D_ENABLE_LIBRARY_CUDA)
IF (D_ENABLE_LIBRARY_OpenCV)
    add_definitions(-DOPENCV_ENABLED=1)
ENDIF (D_ENABLE_LIBRARY_OpenCV)
IF (D_ENABLE_LIBRARY_Glut)
    add_definitions(-DGLUT_ENABLED=1)
ENDIF (D_ENABLE_LIBRARY_Glut)

########################################################################
# Include Directories   
TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
    $CUDA_LIBRARIES)

TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
    $OpenCV_LIBRARIES)

TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
    $Tobii_LIBRARIES)

TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
    $Glut_LIBRARIES)

【问题讨论】:

我刚刚在 Linux、GCC、CUDA 7 和 CMake 3.0.2 上尝试了仅包含 Kernel.cuPerceptorHost.cpp 的 CMake 文件的简化版本,它编译和链接成功。请将您的代码转换为最小但可编译的示例(即尽可能剥离),以重现错误。提供有关您使用的工具版本的更多详细信息。考虑将 CMake 升级到最新版本。 嗨,谢谢你的提示。我尝试将所有内容转换为更小的设置(仍然使用相同的设置 - Lib -> Dll -> CMD 进行测试)。你可以在这里下载:we.tl/DITxuAm3Dd。如果你能看一看就太好了。我的工具是:Windows 8.1、CMakeGUI 3.2.2、NVCC、CUDA 7.0 您的代码还是太多了,除此之外我无法在 Linux 上构建它,因为您使用的是 Windows 特定的包含等。但是为什么您将 void Add2And7(int *c) 定义为 __device__ 函数?你是从主机调用它,所以它不能被装饰成__device__ 是的,device 定义不正确。我想我需要将它公开为外部函数?它确实必须使用“引导”函数从主机调用,该函数可从 DLL 调用。减少更多代码的问题是我松散了项目的结构,据我所知,问题的原因是什么。因为我可以成功构建所有包含在 CUDA 中的示例。 您可以使用extern "C"(正如您在帖子中的示例中所做的那样),但普通的 C++ 函数也应该可以工作。 【参考方案1】:

好的,我能够在没有前面提到的解决方案的情况下解决问题(将构建自定义 + 设置文件更改为 CUDA C/C++)

问题在于,定义我的 CUDA 函数的头文件的符号确实没有被导出。因此,对于我的项目结构(LIB -> DLL -> CMD),这是一个问题。我能够在 LIB -> CMD 结构中使用它。我通过如下定义标头函数解决了这个问题:

extern "C" __declspec(dllexport) void Add2And7(int *); 

代替:

extern "C" void Add2And7(int *);

我不知道这样做是否有什么问题(它有效:))? 如果我查看 MSDN,我认为使用 export 关键字很好。

使用 _declspec(dllexport)

dllexport 和 dllimport 存储类属性是 对 C 和 C++ 语言的特定于 Microsoft 的扩展。您可以使用 它们可以将函数、数据和对象导出或导入 动态链接库。

【讨论】:

以上是关于CUDA 链接错误(Lib 到 Dll)的主要内容,如果未能解决你的问题,请参考以下文章

构造函数重载类获取链接器错误使用DLL?

Boost Python,Visual Studio链接到错误的boost dll

与 Windows 投影文件系统 DLL/LIB 链接

尽管链接到带有导​​出符号的 .lib 文件,但从托管 C++ 链接到非托管 C++ 时出现链接错误

无法定位程序输入点 _glutCreateWindowWithExit于动态链接库glut32.dll上

vs2013编译错误解决: _declspec(dllimport) 动态链接库