2013-03-18 29 views
0

我想單獨編譯使用CUDA 5.爲此,我將「生成可重定位設備代碼」設置爲「是(-rdc = true)」在Visual Studio 2010.該程序編譯時無錯誤,但是, 當我嘗試使用cudaMemcpyToSymbol初始化設備常量時,出現無效的設備符號錯誤。CUDA 5.0「生成可重定位的設備代碼」導致無效的設備符號錯誤

即我有以下的不斷

__constant__ float gdDomainOrigin[2]; 

,並嘗試與

cudaMemcpyToSymbol(gdDomainOrigin, mDomainOrigin, 2*sizeof(float)); 

從而導致錯誤進行初始化。如果沒有前面提到的選項集,編譯所有內容時都不會發生錯誤。有人可以幫我嗎?

+0

根據您的代碼結構,您[可能需要]使用(http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#code-changes-for-separate-compilation )'extern'或'static'來聲明符號的可見性。您還沒有提供足夠的信息,說明哪些模塊正在聲明符號以及哪些模塊正在引用它們。 – 2013-03-18 02:52:44

+0

感謝您的回覆。上述兩個代碼片段都在相同的.cu文件中。此外,該符號僅在此文件中引用。但是,我想用extern聲明一些曾經是.cu文件一部分的內核,並在不同的.cu文件中定義它們以使我的代碼更易讀。但是,這些內核不能訪問上面提到的符號。 – scttrbrn 2013-03-18 03:39:10

回答

0

我不能重現這一點。如果從兩個.cu文件構建應用程序,一個包含__constant__符號和一個簡單內核,另一個包含運行時API咒語來填充該常量內存並調用內核,則僅在啓用可重定位設備代碼時才能工作,即:

__constant__ float gdDomainOrigin[2]; 

__global__ 
void kernel(float *inout) 
{ 
    inout[0] = gdDomainOrigin[0]; 
    inout[1] = gdDomainOrigin[1]; 
} 

#include <cstdio> 

extern __constant__ float gdDomainOrigin; 
extern __global__ void kernel(float *); 

inline 
void gpuAssert(cudaError_t code, char * file, int line, bool Abort=true) 
{ 
    if (code != 0) { 
     fprintf(stderr, "GPUassert: %s %s %d\n", 
          cudaGetErrorString(code),file,line); 
     if (Abort) exit(code); 
    }  
} 
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 

int main(void) 
{ 
    const float mDomainOrigin[2] = { 1.234f, 5.6789f }; 
    const size_t sz = sizeof(float) * size_t(2); 

    float * dbuf, * hbuf; 

    gpuErrchk(cudaFree(0)); 
    gpuErrchk(cudaMemcpyToSymbol(gdDomainOrigin, mDomainOrigin, sz)); 
    gpuErrchk(cudaMalloc((void **)&dbuf, sz)); 

    kernel<<<1,1>>>(dbuf); 
    gpuErrchk(cudaPeekAtLastError()); 

    hbuf = new float[2]; 
    gpuErrchk(cudaMemcpy(hbuf, dbuf, sz, cudaMemcpyDeviceToHost)); 

    fprintf(stdout, "%f %f\n", hbuf[0], hbuf[1]); 

    return 0; 
} 

編譯和用開普勒GPU 64位Linux系統上在CUDA 5運行這些產生以下:

$ nvcc -arch=sm_30 -o shared shared.cu shared_dev.cu 
$ ./shared 
GPUassert: invalid device symbol shared.cu 23 

$ nvcc -arch=sm_30 -rdc=true -o shared shared.cu shared_dev.cu 
$ ./shared 
1.234000 5.678900 

您可以看到,在第一次編譯時,沒有可重定位的GPU代碼生成,找不到符號。在第二種情況下,重新定位的GPU代碼生成,它被發現,並在目標文件中ELF頭看起來就像你所期望的:

$ nvcc -arch=sm_30 -rdc=true -c shared_dev.cu 
$ cuobjdump -symbols shared_dev.o 

Fatbin elf code: 
================ 
arch = sm_30 
code version = [1,6] 
producer = cuda 
host = linux 
compile_size = 64bit 
identifier = shared_dev.cu 

symbols: 
STT_SECTION  STB_LOCAL .text._Z6kernelPf 
STT_SECTION  STB_LOCAL .nv.constant3 
STT_SECTION  STB_LOCAL .nv.constant0._Z6kernelPf 
STT_CUDA_OBJECT STB_LOCAL _param 
STT_SECTION  STB_LOCAL .nv.callgraph 
STT_FUNC   STB_GLOBAL _Z6kernelPf 
STT_CUDA_OBJECT STB_GLOBAL gdDomainOrigin 

Fatbin ptx code: 
================ 
arch = sm_30 
code version = [3,1] 
producer = cuda 
host = linux 
compile_size = 64bit 
compressed 
identifier = shared_dev.cu 
ptxasOptions = --compile-only 

也許你可以試試我的代碼和編譯/診斷步驟,看看你的Windows工具鏈會發生什麼?

+0

感謝您的努力併發布了這些示例文件,它幫助我解決了這個問題!其實我(愚蠢的)錯誤是編譯計算能力2.0而不是3.0 – scttrbrn 2013-03-24 05:11:09