2012-04-03 93 views
1

我在設備變量上使用cudaMemset時遇到問題。是否有可能使用參考設備變量cudaMemset,或者是它只是一個缺少編譯器標誌,或庫..我使用CUDA 4.1的事情,cudaMemset在__device__變量上失敗

NVRM版本:NVIDIA UNIX x86_64的內核模塊285.05.33週四年01月19 14時07分02秒PST 2012

這是我的示例代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <cuda_runtime.h> 

// device variable and kernel 
__device__ float d_test; 

int main() { 

    if (cudaMemset(&d_test,0,sizeof(float)) !=cudaSuccess) 
     printf("Error!\n"); 
} 

,其輸出:

Error! 
+0

cudaGetSymbolAddress不會爲我工作。 我需要添加一些編譯器標誌嗎? 我複製上面的代碼,但它說GPUassert:無效的設備符號XXXX.cu 24 – worldterminator 2012-08-29 16:48:18

回答

4

您的問題是d_test(因爲它出現在主機符號表中)不是有效的設備地址,運行時無法直接訪問它。解決方案是使用API​​函數cudaGetSymbolAddress在運行時從上下文中讀取設備符號的地址。這是你的演示情況略有擴大版本,它應能正常工作:

#include <stdio.h> 
#include <stdlib.h> 
#include <cuda_runtime.h> 

// device variable and kernel 
__device__ float d_test; 

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

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 

int main() 
{ 

    float * _d_test; 

    gpuErrchk(cudaFree(0)); 
    gpuErrchk(cudaGetSymbolAddress((void **)&_d_test, "d_test")); 
    gpuErrchk(cudaMemset(_d_test,0,sizeof(float))); 

    gpuErrchk(cudaThreadExit()); 

    return 0; 
} 

在這裏,我們看到從上下文設備符號d_test的地址轉換爲主機指針_d_test。這可以被傳遞到主機像cudaMemsetcudaMemcpy端API函數等

+0

謝謝!這工作..很好的瞭解'cudaGetSymbolAddress'函數從上下文中提取符號地址。 – nganesan 2012-04-17 02:00:26

0

我相信你也可以使用cudaMemcpyFromSymbol: 的函數,如下面的內核,可以改變變量的全局內存公佈值(主要功能之外)

__global__ void kernel1() { d_test = 1.0; } 

裏面你的主,你能獲得使用cudaMemcpyFromSymbol

cudaMemcpyFromSymbol(&h_test,"d_test",sizeof(float),0,cudaMemcpyDeviceToHost); 

當然的價值,也有cudaMe mcpyToSymbol來更改全局變量的值。

的想法來自這裏:Having problem assigning a device variable in CUDA

+0

請注意,此答案中顯示的'cudaMemcpyFromSymbol'調用形式已過時,並且在CUDA 5或CUDA 6中都不受支持 – talonmies 2014-05-18 13:17:12