[英]CUDA *.obj files are not processed by Visual Studio linker
我使用CMake 3.13來創建帶有單個項目“ cudatest”的Visual Studio(VS 2017)解決方案。 該項目包含兩個文件:
main.cpp
kernel.cu
為了合並對CUDA的支持,我使用了Nvidia提供的腳本,即FindCUDA.cmake
,而不是對基於CUDA的應用程序使用最新的CMake支持(我不使用此最新支持,因為它不允許我做某些事情,因此我需要訴諸FindCUDA)。
CMake成功生成了一個包含上述兩個文件的項目。 無需main.cpp
,文件main.cpp
包含一個函數的聲明:
cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
您可能會將其識別為在使用CUDA運行時類型的項目(對於Visual Studio的NVIDIA CUDA集成)在Visual Studio中創建新項目時默認創建的功能。
而文件kernel.cu
包含上述函數的定義:
__global__ void addKernel(int *c, const int *a, const int *b)
{
int i = threadIdx.x;
c[i] = a[i] + b[i];
}
cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
{
int *dev_a = 0;
int *dev_b = 0;
int *dev_c = 0;
...
addKernel<<<1, size>>>(dev_c, dev_a, dev_b);
...
}
這兩個文件均已成功編譯,並且鏈接器引發了錯誤:
Error LNK2019 unresolved external symbol "enum cudaError __cdecl addWithCuda(int *,int const *,int const *,unsigned int)" ...
應該注意的是,NVCC成功生成了kernel.cu的* .obj文件。
但是* .obj文件放置在不同的目錄中,這使我認為這可能是問題所在,同時也恰恰表明我對Visual Studio鏈接程序在哪里查找* .obj文件以解析符號的理解不足。
main.obj
文件最終位於build\\cudatest.dir\\Debug
,其中build
是包含生成的解決方案的文件夾。
cudatest_generated_kernel.cu.obj
文件最終位於build\\CMakeFiles\\cudatest.dir\\Debug
輸出文件路徑的配置由FindCUDA.cmake
腳本設置。
我試圖把cudatest_generated_kernel.cu.obj
到同一個文件夾中main.obj
,但沒有做任何事情。
將鏈接器的“顯示進度”屬性設置為/VERBOSE
,該鏈接器甚至沒有尋找cudatest_generated_kernel.cu.obj
來嘗試查找各個符號。
=====================
問題是:
假設我使用NVCC將CUDA內核編譯為* .obj文件,並使用CL.exe將* .cpp文件編譯為其自己的* .obj文件,如何告訴鏈接程序檢查cuda內核* .obj文件?
請讓我知道,如果我應該擴展問題以使其更清楚,即指定我使用的NVCC編譯器選項,提供完整的代碼清單等,請向正確的方向提供任何提示和指針!
編輯:每個用戶@talonmies建議( __cdecl addWithCuda
可能表明鏈接器正在尋找C鏈接),我在main.cpp
和kernel.cu
中都用extern "C"
addWithCuda
extern "C"
明確標記了addWithCuda
函數:
extern "C" cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
現在錯誤如下:
Error LNK2019 unresolved external symbol addWithCuda referenced in function main cudatest D:\projects\vs2017\TestCUDA_CMake\build\main.obj
因此,事實證明,除非Visual Studio項目具有CUDA集成(右鍵單擊項目->屬性-> CUDA C ++ / CUDA鏈接器屬性),否則主機鏈接器不會自動考慮編譯為* .obj文件的CUDA內核。
首先,我在鏈接器->其他庫目錄中將路徑添加到已編譯的CUDA * .obj文件中。
其次,我在Linker-> Input-> Additional Dependencies中指定了目標文件的名稱。
那解決了問題。 應該注意的是,最初我使用了本機cmake命令和FindCUDA.cmake
宏的組合:
add_executable(cudatest main.cpp kernel.cu)
CUDA_WRAP_SRCS(cudatest OBJ generated_files kernel.cu ${cmake_options} OPTIONS ${options} )
CUDA_WRAP_SRCS
宏添加了自定義生成步驟,這些步驟使Visual Studio調用nvcc而不是CL來編譯CUDA內核。 還可以從CUDA_ADD_EXECUTABLE
和CUDA_ADD_LIBRARY
宏中調用此宏,它們還指定了已生成的Visual Studio項目中已包括的已生成* .obj文件的所有路徑,從而節省了我上面描述的額外工作。
此外, CUDA_ADD_EXECUTABLE
和CUDA_ADD_LIBRARY
還有助於為啟用了可重定位設備代碼的內核生成項目,這意味着必須存在一個預鏈接步驟,該步驟會將所有帶有可重定位設備代碼的CUDA * .obj文件鏈接到中間設備。主機鏈接器可以使用的CUDA * .obj文件(否則主機鏈接器將無法處理包含可重定位設備代碼的* .obj文件)。 前面提到的宏還將包括對該中間生成的CUDA * .obj文件的依賴性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.