簡體   English   中英

Visual Studio鏈接器未處理CUDA * .obj文件

[英]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.cppkernel.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_EXECUTABLECUDA_ADD_LIBRARY宏中調用此宏,它們還指定了已生成的Visual Studio項目中已包括的已生成* .obj文件的所有路徑,從而節省了我上面描述的額外工作。

此外, CUDA_ADD_EXECUTABLECUDA_ADD_LIBRARY還有助於為啟用了可重定位設備代碼的內核生成項目,這意味着必須存在一個預鏈接步驟,該步驟會將所有帶有可重定位設備代碼的CUDA * .obj文件鏈接到中間設備。主機鏈接器可以使用的CUDA * .obj文件(否則主機鏈接器將無法處理包含可重定位設備代碼的* .obj文件)。 前面提到的宏還將包括對該中間生成的CUDA * .obj文件的依賴性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM