2012-01-11 53 views
2
__kernel void CKmix(__global short* MCL, __global short* MPCL,__global short *C, int S, int B) 
{  
    unsigned int i=get_global_id(0); 
    unsigned int ii=get_global_id(1); 
    MCL[i]+=MPCL[B*ii+i+C[ii]+S]; 
} 

內核接縫正常,它編譯成功,並且我已經使用CPU作爲設備獲得了正確的結果,但那是當我有程序發行版並且在每次調用內核時重新創建我的內存對象,這爲我的測試目的是大約16000次。OpenCL:CPU上的正確結果不在GPU上:如何正確管理內存?

我發佈的代碼就是我現在的位置,試圖使用固定內存和映射。

OpenCLProgram = clCreateProgramWithSource(hContext[Plat-1][Dev-1],11, OpenCLSource, NULL ,NULL); 
clBuildProgram(OpenCLProgram, 0,NULL,NULL, NULL,NULL); 
ocKernel = clCreateKernel(OpenCLProgram, "CKmix", NULL); 

這也是成功的。我有一個二維數組的上下文的原因是,我遍歷所有平臺和設備,並允許用戶選擇使用的平臺和設備。

WorkSize[0]=SN; 
WorkSize[1]=NF; 

PinnedCCL = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE| CL_MEM_ALLOC_HOST_PTR, sizeof(short) *NF, NULL, NULL); 
PinnedMCL = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(short) * Z*NF, NULL, NULL); 
PinnedMO = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(short) * Z,NULL, NULL); 
PinnedMTEMP = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(short) * Z,NULL, NULL); 

DevComboCCL = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE, sizeof(short) *NF, NULL, NULL);  
DevMappedMCL = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE , sizeof(short) * Z*NF, NULL,NULL); 
DevMO = clCreateBuffer(hContext[Plat-1][Dev-1], CL_MEM_READ_WRITE , sizeof(short) * Z,NULL, NULL); 

MO = (short*) clEnqueueMapBuffer(hCmdQueue[Plat-1][Dev-1], PinnedMO, CL_TRUE, CL_MAP_READ, 0, sizeof(short)*Z, 0, NULL, NULL, NULL); 
CCL = (short*) clEnqueueMapBuffer(hCmdQueue[Plat-1][Dev-1], PinnedCCL, CL_TRUE, CL_MAP_WRITE, 0, sizeof(short)*NF, 0, NULL, NULL,NULL); 
MCL = (short*) clEnqueueMapBuffer(hCmdQueue[Plat-1][Dev-1], PinnedMCL, CL_TRUE, CL_MAP_WRITE, 0, sizeof(short)*Z*NF, 0, NULL, NULL, NULL); 
MTEMP = (short*) clEnqueueMapBuffer(hCmdQueue[Plat-1][Dev-1], PinnedMTEMP, CL_TRUE, CL_MAP_READ, 0, sizeof(short)*Z, 0, NULL, NULL, NULL); 

for (n=0; n < Z; ++n) { 
    MTEMP[n]=0; 
    } 

clSetKernelArg(ocKernel, 0, sizeof(cl_mem), (void*) &DevMO); 
clSetKernelArg(ocKernel, 1, sizeof(cl_mem), (void*) &DevMCL);  
clSetKernelArg(ocKernel, 2, sizeof(cl_mem), (void*) &DevCCL); 
clSetKernelArg(ocKernel, 3, sizeof(int), (void*) &SH); 
clSetKernelArg(ocKernel, 4, sizeof(int), (void*) &SN); 

以上構成了我的初始化,下面的其餘部分重複發生。

clEnqueueWriteBuffer(hCmdQueue[Plat-1][Dev-1], DevMCL, CL_TRUE, 0, Z*NF*sizeof(short), MCL, 0, NULL, NULL); 
clEnqueueWriteBuffer(hCmdQueue[Plat-1][Dev-1], DevCCL, CL_TRUE, 0, NF*sizeof(short), CCL, 0, NULL, NULL); 
clEnqueueWriteBuffer(hCmdQueue[Plat-1][Dev-1], DevMO, CL_TRUE, 0, Z*sizeof(short), MTEMP, 0, NULL, NULL); 

clEnqueueNDRangeKernel(hCmdQueue[Plat-1][Dev-1], ocKernel, 2, NULL, WorkSize, NULL, 0, NULL, NULL); 
clEnqueueReadBuffer(hCmdQueue[Plat-1][Dev-1],DevMO, CL_TRUE, 0, Z * sizeof(short),(void*) MO , 0, NULL, NULL); 

我檢查了錯誤,我沒有收到任何錯誤。內核多次重新啓動,並有新的數據。我不確定我做錯了什麼。

NVIDIA 550 TI計算能力2.1, 最新開發驅動程序, CUDA軟件開發包4.0,

+0

那到底究竟是怎麼回事? – Grizzly 2012-01-11 17:34:12

+0

@Grizzly我沒有得到正確的結果(MO)。當我使用GPU和CPU時,我也得到了不同的結果。 – MVTC 2012-01-11 17:42:34

+0

那麼你會得到什麼結果,你期望什麼? – Grizzly 2012-01-11 17:44:14

回答

2

我不知道,如果它的代碼是唯一的問題,但這:

unsigned int i=get_global_id(0); 
unsigned int ii=get_global_id(1); 
MCL[i]+=MPCL[B*ii+i+C[ii]+S]; 

是絕對不是一個好主意。您通常會得到多個線程在同一個global_id(0)上工作,因此多個線程可能會嘗試同時更新MCL[i](請注意,+=不是原子的)。我認爲對於CPU而言,在大多數情況下,沒有足夠的線程產生這種行爲,而在GPU上有數千個線程幾乎肯定會導致問題。

最合理的方式做,這是隻具有一維工作集,併爲每個線程積累哪去了一個位置的所有值:

unsigned int i=get_global_id(0); 
short accum = MCL[i]; //or 0, if thats the start 
for(int ii = 0; ii < size; ++ii) 
    accum += MPCL[B*ii+i+C[ii]+S]; 
MCL[i] = accum; 

當然,這可能是也可能不是可行。如果不是解決辦法可能不會那麼簡單。

+0

對於一維工作集,「global_id(0)」是唯一的,但不適用於二維或三維工作集? – 2012-01-11 18:27:49

+1

@SteveBlackwell:對於1維工作集,您有ids 0..N,其中每個線程都會獲得其中的一個。對於2昏暗。你有ids [0..N,0 ..M]每個組合發生一次,所以你得到M線程共享相同的'global_id(0)'(但具有不同的'global_id(1)') – Grizzly 2012-01-11 18:34:07

+0

@Grizzly:你的解決方案工作。我現在在GPU上獲得了正確的結果!我仍然需要弄清楚如何優化它,因爲它只比CPU上的串行快20%,比使用openMP的CPU慢3倍。我將嘗試使用共享內存,並努力理解合併和對齊。謝謝! – MVTC 2012-01-11 21:24:05