混合編譯.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.cuh
和foo.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;
}