該問題的關鍵在於理解CUDA項目中C\C++文件需要由c++編譯器進行編譯,而CUDA C的源文件需要由CUDA的編譯器nvcc.exe進行編譯。
發生該語法錯誤的原因是cu文件被C++編譯器所編譯,C++編譯器無法識別 “<<<”,導致報錯。
為什么cu文件會被C++編譯器所編譯呢?原因在於我們使用#include將cu文件包含到了C++文件中。對於#include的用途,更簡單的理解就是把幾個文件合並成一個文件,所以,當編譯C++文件中,包含其中的cu文件也會被編譯,從而導致 “<<<”運算符被C++編譯器編譯,導致語法錯誤。
問題原因:不能直接把cuda程序放入cpp中去調用,即核函數的調用語句add<<<2, 128>>>(dev_a, dev_b, dev_c,size); 不能出現在 .cpp 文件中。
解決辦法:可以在 .cu 文件中封裝一層,就是在 .cu 文件中寫一個傳同樣參數的核函數調用函數addKernel(int *a, int *b, int *c, int size),即在addKernel(int *a, int *b, int *c, int size)函數中調用核函數add<<<2, 128>>>(dev_a, dev_b, dev_c,size),然后在外邊main.cpp文件中用調用普通函數的方法調用addKernel(int *a, int *b, int *c, int size)函數,此外需要在addKernel(int *a, int *b, int *c, int size)函數的定義之處和main.cpp文件頭部將addKernel(int *a, int *b, int *c, int size)聲明為外部函數,即需要用extern "C" 聲明。這也是為什么在調用cu文件中核函數的間接調用函數addKernel(int *a, int *b, int *c, int size)時我們需要使用 extern “C”。
示例如下:
(1)創建一個CUDA 6.5 的項目,新建一個main.cpp文件,添加代碼如下:
#include <stdio.h> #include <stdlib.h> //#include "kernel.cu" #define N 256 extern "C" void addKernel(int *a, int *b, int *c, int size); int main(int argc, char **argv) { int a[N]; int b[N]; int c[N]; for (int i=0; i<N; i++) { a[i]=i; b[i]=2*i; c[i]=0; } addKernel(a, b, c, N); for(int i=0; i<N; i++) { printf("%d is %d.\n", i, c[i]); } return 0; }
(2)將kernel.cu文件清空后寫入下述代碼:
#include "cuda_runtime.h" #include "device_launch_parameters.h" __global__ void add(const int *a, const int *b, int *c, int size) { int tid = threadIdx.x + blockIdx.x * blockDim.x; c[tid] = b[tid] + a[tid]; } extern "C" void addKernel(const int *a, const int *b, int *c, int size) { int *dev_a=0; int *dev_b=0; int *dev_c=0; cudaSetDevice(0); cudaMalloc((void**)&dev_a, sizeof(int)*size); cudaMalloc((void**)&dev_b, sizeof(int)*size); cudaMalloc((void**)&dev_c, sizeof(int)*size); cudaMemcpy(dev_a, a, sizeof(int)*size, cudaMemcpyHostToDevice); cudaMemcpy(dev_b, b, sizeof(int)*size, cudaMemcpyHostToDevice); cudaMemcpy(dev_c, c, sizeof(int)*size, cudaMemcpyHostToDevice); add<<<2, 128>>>(dev_a, dev_b, dev_c,size); cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost); cudaFree(dev_a); cudaFree(dev_b); cudaFree(dev_c); }
(3)編譯執行。結果如下所示
這時顯示是成功的。
(4)把main.cpp中的注釋行取消注釋,重新編譯執行。結果如下所示:
出現文中所述問題。
參考鏈接:
1、關於CUDA C 項目中“ error C2059: 語法錯誤:“<” ”問題的解決方法