混合编译.c/.cpp与.cu文件

混合编译.c/.cpp与.cu文件

项目中用到cuda编程,写了kernel函数,需要nvcc编译器来编译。.c/.cpp的文件,假定用gcc编译。

如何混合编译它们,整体思路是:.cu文件编译出的东西,作为最终编译出的可执行程序的链接依赖。

具体说起来又可以有这几种情况:

  • 分别编译各个文件,最后链接
  • 将CUDA程序编译为静态库
  • 将CUDA程序弄成动态库

其中后两种方式更工程化,基于makefile或CMake会更加方便。

假设手头上的文件为:

test1.cu
test2.c

则具体编译指令、编译脚本如下:

方法1:分别编译各个文件

nvcc -c test1.cu
gcc -c test2.c
gcc -o testc test1.o test2.o -lcudart -L/usr/local/cuda/lib64

方法2: 将cuda程序编译为静态库

nvcc -lib test1.cu -o libtestcu.a
gcc test2.c -ltestcu -L. -lcudart -L/usr/local/cuda/lib64

方法3:将CUDA程序弄成动态库

以makefile为例

all: c

c: libtestcu.so
    gcc test2.c -ltestcu -L. -lcudart -L/usr/local/cuda/lib64 -o testc

libtestcu.so: test.cu
    nvcc -o libtestcu.so -shared -Xcompiler -fPIC test1.cu

方法4:基于CMake的一个例子

foo.cuh写kernel函数声明
foo.cu 实现kernel函数
foo.cuhfoo.cu一起,编译成一个库

main.c调用kernel函数

foo.cuh

参见https://blog.csdn.net/fb_help/article/details/79330815

需要注意的是,VS在debug模式下,应该把nvcc的flags中优化选项关闭掉。

技巧:
可以把kernel函数做一层封装,这样一来在其他.c/.cpp文件中,调用这个wrapper函数即可

e.g.

#include <stdio.h>
#include <iostream>

#include "foo.cuh" //注意包含头文件

int main()
{
    std::cout<<"Hello C++"<<std::endl;
    useCUDA(); // 这个函数是kernel函数的wrapper函数
    return 0;
}
posted @ 2019-01-15 15:55  ChrisZZ  阅读(12314)  评论(0编辑  收藏  举报