2012-03-12 140 views
4

問題CUDA的cudaMemcpyToSymbol()拋出「無效的參數」錯誤

我想一個int陣列拷貝到設備中的常量內存,但我不斷收到以下錯誤:

[ERROR] 'invalid argument' (11) in 'main.cu' at line '386'

該代碼

有很多的代碼開發,所以我要簡化我有什麼。

我聲明瞭一個設備__constant__變量在我的main.cu文件的頂部,在任何函數之外。

__device__ __constant__ int* dic; 

我也有一個主機變量,flatDic,這是malloc分配方式如下,裏面main()

int* flatDic = (int *)malloc(num_codewords*(bSizeY*bSizeX)*sizeof(int)); 

然後我嘗試這樣做給flatDic的內容複製到dic,也在main()

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int)); 

cudaMemcpyToSymbol()調用它的線main.cu的386,它是在哪裏上述錯誤被拋出。

我已經試過

這是我到目前爲止已經試過要解決的問題:

我已經試過所有的以下的,總是返回相同的錯誤:

cudaMemcpyToSymbol(dic, &flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int)); 

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int)); 

cudaMemcpyToSymbol(dic, &flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int), 0, cudaMemcpyHostToDevice); 

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int), 0, cudaMemcpyHostToDevice); 

我也試過cudaMalloc()的變量之前調用cudaMemcpyToSymbol()cudaMalloc()沒有錯誤,但cudaMemcpyToSymbol()錯誤仍然存​​在。

cudaMalloc((void **) &dic, num_codewords*(bSizeY*bSizeX)*sizeof(int)); 

我也搜索廣泛深入的網頁,文檔,論壇,實例等,都無濟於事。

有人看到我的代碼有什麼問題嗎?提前致謝。

+1

「我也仔細搜索過網絡,文檔,論壇,例子等,都無濟於事。」 ...對於基本呼叫始終從CUDA C編程指南開始 - 1.按下「Ctrl + S」並鍵入您正在瀏覽您的瀏覽器/ PDF閱讀器的呼叫。 2.閱讀任何適用的內容並查看指南的代碼示例。 3.如果#2失敗,那麼只能去論壇跳水。在這種情況下,信息在指南中是正確的,直接形式NVIDIA - 只是關於如何解決CUDA API調用問題的一些未來建議。 – 2012-03-13 04:09:24

+1

我通常從HTML格式的參考指南開始。 [這裏是CUDA 4.1參考](http://developer.download.nvidia.com/compute/cuda/4_1/rel/toolkit/docs/online/modules.html)谷歌的通話名稱通常會變成這樣。檢查參考後,檢查編程指南。 – harrism 2012-03-13 11:19:12

回答

3

cudaMemcpyToSymbol拷貝到一個常量變量,在這裏您試圖將類型爲int(分配的ARRAY)的多個字節複製到int *類型的指針。這些類型是不一樣的,因此invalid type。爲了使這項工作,你需要的int(分配)數組複製到設備(靜態長度)的int(恆定)陣列,例如:

__device__ __constant__ int dic[LEN]; 

例如,從CUDA C Programming Guide(我建議你閱讀 - 這是相當不錯!):

__constant__ float constData[256]; 
float data[256]; 
cudaMemcpyToSymbol(constData, data, sizeof(data)); 
cudaMemcpyFromSymbol(data, constData, sizeof(data)); 

據我所知,你也可以cudaMemcpyToSymbol一個指針的指針(不像你的榜樣,在那裏你複製一個數組的指針),但要注意只有指針將是恆定的,不它指向您設備上的內存。如果你要去這條路線,你需要添加一個cudaMalloc,然後cudaMemcpyToSymbol產生的ptr到設備內存到你的__constant__設備變種。再次,在這種情況下,數組值不會是常數 - 只有指向內存的指針。

您的通話對於這種情況會是這樣的:

int * d_dic; 
cudaMalloc((void **) &d_dic, num_codewords*(bSizeY*bSizeX)*sizeof(int)); 
cudaMemcpyToSymbol(c_dic_ptr, &d_Dic, sizeof(int *)); 

你也應該調試內部錯誤檢查的邏輯過程中包裝你的CUDA電話。我從talonmies藉以下邏輯:

__inline __host__ 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__); } 

要調用簡單包裝您的CUDA調用它像這樣:

gpuErrchk(cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int))); 

編程將與如果你有分配的錯誤消息退出問題或其他常見錯誤。

要檢查你的內核,這樣做:

MyKernel<<<BLK,THRD>>>(vars...); 

//Make sure nothing went wrong. 
gpuErrchk(cudaPeekAtLastError()); 
gpuErrchk(cudaDeviceSynchronize()); 

感謝talonmies的錯誤校驗碼!

注:
即使你正在做一個香草cudaMemcpy,您的代碼會因爲你還沒有爲你的陣列cudaMalloc版內存失敗 - 詮釋這種情況下,雖然,失敗很可能是GPU相當於的段錯誤(可能爲Unspecified launch failure),因爲指針會在其中存在某種垃圾值,並且您將嘗試使用該垃圾值給出的地址寫入內存。