【问题标题】:Linking error while separating CUDA function into declaration and definition将 CUDA 函数分离为声明和定义时出现链接错误
【发布时间】:2019-06-12 06:58:41
【问题描述】:

我正在关注instructions provided on NVidia blog post,了解如何将从内核调用的函数分离为声明和定义。使用 CUDA 10 版本和 Visual Studio 编译器会产生链接错误。我添加了 -dcnvcc 编译器的选项,如参考帖子中所述。这些文件都位于同一个项目下的同一个文件夹中。

test.cuh

__host__ __device__ float test(float, float);

test.cu

#include "test.cuh"    
__host__ __device__ float test(float a, float b)
{
    return a + b;
}

kernel.cu

#include <stdio.h>
#include "test.cuh"
__global__ void addKernel(int *c, const int *a, const int *b)
{
    int i = threadIdx.x;
    c[i] =  test(a[i], b[i]);
}

链接错误

1>kernel.cu.obj : error LNK2019: unresolved external symbol __cudaRegisterLinkedBinary_41_tmpxft_0000796c_00000000_7_kernel_cpp1_ii_f853efa9 referenced in function "void __cdecl __nv_cudaEntityRegisterCallback(void * *)" (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
1>test.cuh.obj : error LNK2019: unresolved external symbol __cudaRegisterLinkedBinary_39_tmpxft_00006d84_00000000_7_test_cpp1_ii_f2c23be0 referenced in function "void __cdecl __nv_cudaEntityRegisterCallback(void * *)" (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
1>test.cu.obj : error LNK2019: unresolved external symbol __cudaRegisterLinkedBinary_39_tmpxft_00008044_00000000_7_test_cpp1_ii_f2c23be0 referenced in function "void __cdecl __nv_cudaEntityRegisterCallback(void * *)" (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
1>D:\Workspaces\src\sandbox\cuda_dc\x64\Debug\cuda_dc.exe : fatal error LNK1120: 3 unresolved externals

将文件扩展名更改为“.c”、“.cpp”或“.cuh”没有任何区别

【问题讨论】:

  • 您不要将-dc 添加到Windows 的编译选项中。您首先选择relocatable device code project。引用的帖子适用于 linux,而不是 windows,构建可重定位设备代码项目的过程涉及的步骤不仅仅是添加 -dc(即使在 linux 上,如果主机链接器用于最终链接阶段)。
  • 另外,您为什么要尝试使用 C 链接来实现设备功能?这没有任何意义,即使工具链(意外地)支持它。
  • 删除了“C”链接。还是同样的问题。在VS中我激活了参数-rdc=true,但还是没有运气。
  • 如果您在 VS 项目中添加了 test.cuh 作为编译目标,那几乎肯定是不正确的,尽管我不相信它是这些错误的根源。

标签: c++ cuda linker


【解决方案1】:

这些是我遵循的步骤,使用您显示的代码,加上一个简单的main() 函数,这样我们就可以拥有一个完整的项目。

(在 Visual Studio 中)

  1. 文件..新建..项目
  2. 在左侧,向下滚动到 NVIDIA 并选择它
  3. 选择CUDA X.Y运行时项目,给项目起个名字,点击确定
  4. 在顶部菜单栏的调试旁边,将 x86 更改为 x64
  5. 项目中应该有一个默认文件,kernel.cu。将其内容替换为(修改您的 kernel.cu 以添加主函数):

    #include <stdio.h>
    #include "test.cuh"
    __global__ void addKernel(int *c, const int *a, const int *b)
    {
        int i = threadIdx.x;
        c[i] = test(a[i], b[i]);
    }
    int main() {
        int *c = NULL;
        int *a = NULL;
        int *b = NULL;
        addKernel << <1, 1 >> > (c, a, b);
    }
    

(在 Windows 中,例如使用文件管理器)

  1. 在 kernel.cu 所在的项目文件夹中,放置您的文件 test.cuh 和 test.cu(您发布的没有 C 链接的更新版本)

(在视觉工作室中)

  1. 在解决方案资源管理器窗口中转到项目,右键单击项目名称,然后选择属性
  2. 在对话框的左侧,选择“CUDA C/C++”
  3. 在右侧,将“生成可重定位设备代码”旁边的下拉菜单从“否”更改为“是”
  4. 在左侧,选择“CUDA linker”并确认“Perform device link”已设置为yes
  5. 选择确定关闭对话框

  6. 同样,在解决方案资源管理器窗口中,右键单击项目名称并选择添加...现有项

  7. 应该会打开一个文件选择对话框。您应该会看到 kernel.cu 文件以及添加到文件夹中的 test.cu 和 test.cuh 文件
  8. 选择并添加 test.cu 文件
  9. 现在选择构建...重建解决方案

当我执行这些步骤时,我会得到一个没有错误的干净编译:

1>------ Rebuild All started: Project: test37, Configuration: Debug x64 ------
1>
1>  c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64"  -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include"  -G   --keep-dir x64\Debug -maxrregcount=0  --machine 64 --compile   -g   -DWIN32 -DWIN64 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /FS /Zi /RTC1 /MDd " -o x64\Debug\kernel.cu.obj "c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37\kernel.cu" -clean
1>CUDACOMPILE : nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
1>  kernel.cu
1>
1>  c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64"  -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include"  -G   --keep-dir x64\Debug -maxrregcount=0  --machine 64 --compile   -g   -DWIN32 -DWIN64 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /FS /Zi /RTC1 /MDd " -o x64\Debug\test.cu.obj "c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37\test.cu" -clean
1>CUDACOMPILE : nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
1>  test.cu
1>  Compiling CUDA source file kernel.cu...
1>  Compiling CUDA source file test.cu...
1>
1>  c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -gencode=arch=compute_20,code=\"sm_20,compute_20\" --use-local-env --cl-version 2015 -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64" -rdc=true -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include"  -G   --keep-dir x64\Debug -maxrregcount=0  --machine 64 --compile -cudart static  -g   -DWIN32 -DWIN64 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /FS /Zi /RTC1 /MDd " -o x64\Debug\kernel.cu.obj "c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37\kernel.cu"
1>
1>  c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -gencode=arch=compute_20,code=\"sm_20,compute_20\" --use-local-env --cl-version 2015 -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64" -rdc=true -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include"  -G   --keep-dir x64\Debug -maxrregcount=0  --machine 64 --compile -cudart static  -g   -DWIN32 -DWIN64 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /FS /Zi /RTC1 /MDd " -o x64\Debug\test.cu.obj "c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37\test.cu"
1>CUDACOMPILE : nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
1>  kernel.cu
1>CUDACOMPILE : nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
1>  test.cu
1>
1>  c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\test37>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nvcc.exe" -dlink -o x64\Debug\test37.device-link.obj -Xcompiler "/EHsc /W3 /nologo /Od /Zi /RTC1 /MDd " -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\lib\x64" cudart.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  -gencode=arch=compute_20,code=sm_20 -G --machine 64 x64\Debug\kernel.cu.obj x64\Debug\test.cu.obj
1>CUDALINK : nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
1>  cudart.lib
1>  kernel32.lib
1>  user32.lib
1>  gdi32.lib
1>  winspool.lib
1>  comdlg32.lib
1>  advapi32.lib
1>  shell32.lib
1>  ole32.lib
1>  oleaut32.lib
1>  uuid.lib
1>  odbc32.lib
1>  odbccp32.lib
1>  kernel.cu.obj
1>  test.cu.obj
1>  test37.vcxproj -> c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\x64\Debug\test37.exe
1>  test37.vcxproj -> c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\x64\Debug\test37.pdb (Full PDB)
1>  copy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\cudart*.dll" "c:\Users\bob-tosh\documents\visual studio 2015\Projects\test37\x64\Debug\"
1>  C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\cudart32_80.dll
1>  C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\cudart64_80.dll
1>          2 file(s) copied.
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

我的观点是,如果您可以完全按照上述步骤,从一个新项目开始并使用我指出的文件,并且您得到与我相同的结果,那么您在问题中描述的问题与您的问题有关没有显示或没有描述。然后,您应该提供MCVE,并确保提供与我在回答中给出的相同级别的细节。用于创建、构建和编译项目的每个步骤,以及控制台构建输出和使用的所有文件。

我使用过 CUDA 8 和 Visual Studio 2015,但我认为我在这里描述的内容与较新的 VS 和较新的 CUDA 版本应该没有实质性差异。

【讨论】:

  • 我已按照提供的步骤进行操作,但仍然遇到同样的故障。最终,当我将 Windows SDK 版本降级到 10.0.15063.0 并将 Platform Toolset 降级到 v140 时,我可以成功编译和链接应用程序。
猜你喜欢
  • 1970-01-01
  • 2019-09-18
  • 1970-01-01
  • 2018-09-15
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2017-04-12
相关资源
最近更新 更多