2012-04-24 101 views
0

我的電腦有一個AMD處理器和一個不支持OpenCL的ATI 3200 GPU。剩下的代碼全部由「回退到CPU本身」運行。這個cuda「cudaMallocPitch」代碼的openCL等價物是什麼?

我將其中一個代碼從CUDA轉換爲OpenCL,但卡在OpenCL中沒有確切轉換代碼的某個特定部分。因爲我已經在OpenCL的經驗較少,我可以不出這個,請建議我一些解決方案,如果任何一個你認爲會工作,

的CUDA代碼,

size_t pitch = 0; 
cudaError error = cudaMallocPitch((void**)&gpu_data, (size_t*)&pitch, 
          instances->cols * sizeof(float), instances->rows); 

for(int i = 0; i < instances->rows; i++){ 
    error = cudaMemcpy((void*)(gpu_data + (pitch/sizeof(float))*i), 
         (void*)(instances->data + (instances->cols*i)), 
         instances->cols * sizeof(float) ,cudaMemcpyHostToDevice); 

如果我刪除間距值從上面我結束了一個問題,不寫入設備內存「gpu_data」。

有人請將此代碼轉換爲OpenCL並回復。我已經將它轉換爲OpenCL,但它不工作,數據沒有寫入「gpu_data」。我轉換的OpenCL代碼

gpu_data = clCreateBuffer(context, CL_MEM_READ_WRITE, ((instances->cols)*(instances->rows))*sizeof(float), NULL, &ret); 
for(int i = 0; i < instances->rows; i++){ 
    ret = clEnqueueWriteBuffer(command_queue, gpu_data, CL_TRUE, 0, ((instances->cols)*(instances->rows))*sizeof(float),(void*)(instances->data + (instances->cols*i)) , 0, NULL, NULL); 

有時它運行良好此代碼,並卡在閱讀部分,即

ret = clEnqueueReadBuffer(command_queue, gpu_data, CL_TRUE, 0,sizeof(float) * instances->cols* 1 , instances->data, 0, NULL, NULL); 

overhere。並且它給出如下錯誤:

CL_kmeans.exe中0x10001098處未處理的異常:0xC000001D:非法指令。

壓破時,它給出:

否符號已加載的任何調用堆棧幀。源代碼無法顯示。

while debugging。在調用棧中它顯示:

OCL8CA9.tmp.dll 10001098()
[下面的幀可能是不正確的和/或缺失,沒有加載OCL8CA9.tmp.dll符號]
amdocl!。 dll!5c39de16()

我真的不知道這是什麼意思。有人請幫我解決這個問題。

回答

3

首先,在CUDA代碼中,您正在做一個非常低效的事情來複制數據。 CUDA運行時具有功能cudaMemcpy2D,它可以完成您通過在不同行上循環執行的操作。

cudaMallocPitch所做的是計算最佳間距(=二維數組中行間的字節距離),使得每個新行開始於最佳聚合地址,然後分配一個與間距一樣大的存儲區乘以你指定的行數。您可以在OpenCL中模擬相同的事物,方法是首先計算最佳音調,然後分配正確的大小。

通過以下方式計算最佳音高:(1)獲取卡的基地址對齊偏好(CL_DEVICE_MEM_BASE_ADDR_ALIGN屬性和clGetDeviceInfo:請注意,返回的值是以位爲單位的,所以您必須除以8以字節爲單位) ;我們稱之爲base(2)找到base的最大倍數,它不小於您的自然數據間距(sizeof(type)times列數);這將是你的pitch

然後您分配pitch次行數字節,並將內存傳遞給pitch信息。

另外,將數據從主機複製到設備時,您需要使用專門設計用於複製2D數據的clEnqueue{Read,Write}BufferRect(它們與cudaMemcpy2D對應)。

相關問題