使用CUDA模块构建GPL C程序

12

我尝试修改一段用C语言编写的GPL程序。我的目标是用CUDA实现替换其中的一个方法,这意味着我需要使用nvcc而不是gcc进行编译。我需要帮助构建项目 - 而不是实现它(您不需要了解CUDA C来提供帮助,我认为)。

这是我第一次尝试更改一个涉及.configure和Makefile的中等复杂度的C项目。老实说,这是我很长一段时间以来第一次做任何关于gcc或g++的事情,所以我很迷茫。

我对学习configure和Makefiles不是特别感兴趣 - 这更像是一个实验。在花费时间创建适当的构建脚本之前,我想看看项目实现情况如何。(必要时愿意学习,只是试图给出一个范围的想法)。

那么,我构建此项目的选择有哪些?我有许多问题...

  • 我尝试在AC_PROG_CC后将“CC = nvcc”添加到configure.in文件中。这似乎有效 - 运行configure和make的输出显示nvcc是编译器。但是,make未能使用具有CUDA内核的源文件进行编译,无法识别CUDA特定的语法。我不知道为什么,希望这只是能够正常工作。

  • 是否可以使用nvcc编译源文件,然后在make过程的链接步骤中将其包含进主程序?如果可以,如何实现?(这个问题可能没有意义 - 我真的很生疏)

  • 这么做的正确方法是什么?

  • 是否有一种快速而简单的方法可用于测试目的?

  • 是否有某些秘密工具可供每个人设置和理解这些configure和Makefiles?这比我习惯的Apache Ant脚本还要糟糕(是的,我已经超出了我的领域)


2
你可能忽略了文件扩展名。nvcc使用文件扩展名来确定哪些文件包含设备代码,哪些不包含 - 任何包含设备代码的文件必须具有.cu扩展名才能正确编译。 - talonmies
只是好奇,你在CUDA函数中做了什么? - arrayfire
关于 .cu 文件的观点很好。我会尝试重命名一些源文件。 - emulcahy
我正在尝试将fcrackzip适应于在CUDA内核中执行。这是我选择的学校项目,希望这仍然在范围内,因为它并不完全是作业。 - emulcahy
1个回答

20
你不需要用nvcc编译所有内容。你的猜测是正确的,你可以只用NVCC编译你的CUDA代码并留下其他所有内容(除了链接)。这是我开始的方法:
1. 添加1个新头文件(例如myCudaImplementation.h)和1个新源文件(具有.cu扩展名,例如myCudaImplementation.cu)。源文件包含你的核实现以及一个(主机)C包装函数,该函数使用适当的执行配置(也称为<<< >>>)和参数调用内核。头文件包含C包装函数的原型。我们将称这个包装函数为runCudaImplementation()。
2. 我还会在源文件中提供另一个主机C函数(其原型在头文件中),该函数查询和配置存在的GPU设备,并在成功时返回true,否则返回false。我们将这个函数称为configureCudaDevice()。
3. 现在在你的原始C代码中,在你通常调用CPU实现的地方,你可以这样做。
// must include your new header
#include "myCudaImplementation.h"

// at app initialization
// store this variable somewhere you can access it later
bool deviceConfigured = configureCudaDevice;          
...                             
// then later, at run time
if (deviceConfigured) 
    runCudaImplementation();
else
    runCpuImplementation(); // run the original code
现在,由于您将所有CUDA代码放入一个新的.cu文件中,因此您只需使用nvcc编译该文件。 一切都保持不变,除了您必须链接nvcc输出的目标文件。例如:
nvcc -c -o myCudaImplementation.o myCudaImplementation.cu <other necessary arguments>

接下来将myCudaImplementation.o添加到您的链接行中(类似以下命令):

g++ -o myApp myCudaImplementation.o

如果您要处理的是使用configure和已经存在复杂makefile的复杂应用程序,则可能比上述更复杂,但这是一般方法。重点是您不希望使用nvcc编译所有源文件,只需对.cu文件使用即可。其他所有内容都使用主机编译器。

我对configure不是很熟悉,所以无法提供太多帮助。您可以运行configure生成一个makefile,然后编辑该makefile-这不是通用解决方案,但它可以让您开始。

请注意,在某些情况下,您可能还需要分离编译.cu文件和链接它们。在这种情况下,您需要使用NVCC的分离编译和链接功能,这篇博客文章可能会有所帮助。


非常感谢您抽出时间解释那个。我可以处理这种方法。 - emulcahy
搞定了。其他人可能需要执行的一个额外步骤是在包装方法周围添加 extern "C" { }。虽然这对于链接专家来说可能很明显。 - emulcahy
2
除非您只有C链接(例如从.c文件调用它),否则不应该使用extern "C"。 - harrism
1
@harrism 请问使用g++编译的源代码可以包含cuda运行时API,例如cudaMalloc(&p)和cudaMemcpy(p),但是它不能包含核函数启动,例如foo<<<>>>(p)。 - user1823664
1
针对cuda 5.0及更高版本:https://devblogs.nvidia.com/parallelforall/separate-compilation-linking-cuda-device-code/ - user1823664
2
@user1823664 是的,那是正确的说法。不过,还有一个 cudaLaunch() API 可以在没有 <<<>>> 的情况下启动。 - harrism

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接