在Windows上将cuda库与gcc链接

在Windows上将cuda库与gcc链接,windows,visual-studio,gcc,cuda,mingw,Windows,Visual Studio,Gcc,Cuda,Mingw,好的,这一次让我头痛了一段时间,我希望这里的一些专家能帮助我解决这个问题 短版本: 我尝试编译MAGMA,并收到关于缺少符号的投诉: testing_cgemm.o:testing_cgemm.cpp:(.text+0x2e7): undefined reference to `cudaMalloc' testing_cgemm.o:testing_cgemm.cpp:(.text+0xbff): undefined reference to `cudaFree' testing_cgemm

好的,这一次让我头痛了一段时间,我希望这里的一些专家能帮助我解决这个问题

短版本:

我尝试编译MAGMA,并收到关于缺少符号的投诉:

testing_cgemm.o:testing_cgemm.cpp:(.text+0x2e7): undefined reference to `cudaMalloc' 
testing_cgemm.o:testing_cgemm.cpp:(.text+0xbff): undefined reference to `cudaFree'
testing_cgemm.o:testing_cgemm.cpp:(.text+0x2e7): undefined reference to `cudaMalloc' 
testing_cgemm.o:testing_cgemm.cpp:(.text+0xbff): undefined reference to `cudaFree'
在cuda libs中检查32位和64位中的这些符号,我得到以下结果:

$ /C/Coding/Mingw-w64-tdm/bin/nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/x64/cudart.lib | grep cudaMalloc
 0000000000000000 I __imp_cudaMalloc
 0000000000000000 T cudaMalloc

$ nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/Win32/cudart.lib | grep cudaMalloc
 00000000 I __imp__cudaMalloc@8
 00000000 T _cudaMalloc@8
$ /C/Coding/Mingw-w64-tdm/bin/nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/x64/cudart.lib | grep cudaMalloc
 0000000000000000 I __imp_cudaMalloc
 0000000000000000 T cudaMalloc

$ nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/Win32/cudart.lib | grep cudaMalloc
 00000000 I __imp__cudaMalloc@8
 00000000 T _cudaMalloc@8
所以64位lib看起来不错,而且链接正确。但是,32位库(第二个输出)在方法名称处有一些修饰。这就是我被困的地方

问题

那些装饰意味着什么?32位不是普通的C吗?有没有可能把它们联系起来

上下文

我想在Windows7(64位)(最终是32位和64位)上编译,并将其链接到使用gcc编译的程序。问题是Windows上的Cuda不支持我熟悉的Mingw/MSys工具链。在Windows上使用nvcc进行Cuda编译似乎需要Visual Studio C编译器cl.exe。我安装了Cuda 4.0(64位下载),并在32位和64位版本中成功构建了示例(使用VS2008),证明Cuda在这两种版本中都安装了

然而,MAGMA并没有为visualstudio提供解决方案,我也没有足够的经验来生成一个解决方案,因为它还涉及要编译的大部分Fortran代码。因此,我尝试同时使用这两个工具链(MinGW和VS2008)。我将make.inc文件应用于我的路径,并分三步执行构建。首先使用Msys/Mingw编译所有Fortran代码,然后在遇到无法找到cl.exe的nvcc错误后,我切换到VS命令promt(x86或x64,取决于要构建的位)。后面的步骤以一个库归档文件libmagmablas.a结束,该文件看起来是正确的

然而,问题开始了。使用TDM 64位编译器(gcc-4.5)编译和链接MAGMA示例时,一切似乎都正常工作,但调用cuInit()后,.exe文件会立即失败。(我认为这是一个编译器错误/不兼容,因为当我使用这个Mingw-w64工具链编译Cuda示例时也会发生同样的情况)。 因此,我切换到32位Mingw-w64工具链,它能够编译Cuda示例。使用它编译MAGMA,重复上面的所有步骤,直到MAGMA示例的链接步骤。有人抱怨缺少符号:

testing_cgemm.o:testing_cgemm.cpp:(.text+0x2e7): undefined reference to `cudaMalloc' 
testing_cgemm.o:testing_cgemm.cpp:(.text+0xbff): undefined reference to `cudaFree'
testing_cgemm.o:testing_cgemm.cpp:(.text+0x2e7): undefined reference to `cudaMalloc' 
testing_cgemm.o:testing_cgemm.cpp:(.text+0xbff): undefined reference to `cudaFree'
在cuda库中检查这些符号,我得到以下结果:

$ /C/Coding/Mingw-w64-tdm/bin/nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/x64/cudart.lib | grep cudaMalloc
 0000000000000000 I __imp_cudaMalloc
 0000000000000000 T cudaMalloc

$ nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/Win32/cudart.lib | grep cudaMalloc
 00000000 I __imp__cudaMalloc@8
 00000000 T _cudaMalloc@8
$ /C/Coding/Mingw-w64-tdm/bin/nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/x64/cudart.lib | grep cudaMalloc
 0000000000000000 I __imp_cudaMalloc
 0000000000000000 T cudaMalloc

$ nm C:/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v4.0/lib/Win32/cudart.lib | grep cudaMalloc
 00000000 I __imp__cudaMalloc@8
 00000000 T _cudaMalloc@8
所以64位lib看起来不错,而且链接正确。但是,32位库(第二个输出)在方法名称处有一些修饰。这就是我被困的地方


那些装饰意味着什么?32位不是普通的C吗?有没有可能把它们联系起来

32位符号是
\uuu stdcall
函数的标准窗口装饰(在16位的日子里也称为\uu pascal)。考虑到CUDA在Windows上缺乏对GCC的支持(说真的,这不是你想要走的路),我猜测CUDA.h头没有正确定义
CUDAAPI

32位符号是
\uu stdcall
函数(在16位的日子里也称为u pascal)的标准窗口装饰。考虑到CUDA在Windows上缺乏对GCC的支持(说真的,这不是你想要走的路),我猜CUDA.h头没有正确定义
CUDAAPI

你能改为动态链接loadproc吗?我还没有尝试为MAGMA构建共享库。你真的希望从中受益吗?是的,它的处理方式与静态链接完全不同!另外,FFox看起来好像很懂。你能改为动态链接loadproc吗?我还没有尝试为MAGMA构建共享库。你真的希望从中受益吗?是的,它的处理方式与静态链接完全不同!此外,FFox看起来像是懂一些东西。如果CUDAAPI不是由标题正确定义的,为什么它在64位中工作?在64位窗口上只有一个调用约定(因此也只有一个装饰方案)。感谢您的澄清!另外,我认为关于主机定义的API,您是对的。在后一种情况下,在GNUC和WIN32之间包含一个离散的部分,将CUDARTAPI定义为uu stdcall,而对于GNUC则将其保留为空(u cdecl在我的理解中是默认值)。如果CUDAAPI没有正确地由标头定义,为什么它是64位的呢?在64位窗口上只有一个调用约定(因此也只有一个装饰方案)。感谢您的澄清!另外,我认为关于主机定义的API,您是对的。h包括一个在GNUC和WIN32之间离散的部分,在后一种情况下,将CUDARTAPI定义为uu stdcall,而将GNUC保留为空(u cdecl在我的理解中为默认值)。