2013-02-05 22 views
0

我想實現我的OpenCL內核的原子功能。我創建的多個線程並行地嘗試寫入單個內存位置。我希望他們在特定的代碼行上執行串行執行。我從來沒有使用原子功能。錯誤CL_OUT_OF_RESOURCES而在主機內存中讀回數據,同時用原子功能的OpenCL內核

我發現很多博客和論壇類似的問題,我試圖一個解決方案,即。使用兩個不同的函數'acquire'和'release'來鎖定和解鎖信號量。我已經包含了必要的opencl擴展,這些都得到了我的設備(NVIDIA GeForce GTX 630M)的肯定支持。

我的內核執行配置:

global_item_size = 8; 
ret = clEnqueueNDRangeKernel(command_queue2, kernel2, 1, NULL, &global_item_size2, &local_item_size2, 0, NULL, NULL); 

這裏是我的代碼:reducer.cl

#pragma OPENCL EXTENSION cl_khr_fp64 : enable 
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable 
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable 
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable 
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable 

typedef struct data 
{ 
    double dattr[10]; 
    int d_id; 
    int bestCent; 
}Data; 

typedef struct cent 
{ 
    double cattr[5]; 
    int c_id; 
}Cent; 

__global void acquire(__global int* mutex) 
{ 
    int occupied; 
    do { 
     occupied = atom_xchg(mutex, 1); 
    } while (occupied>0); 
} 

__global void release(__global int* mutex) 
{ 
    atom_xchg(mutex, 0); //the previous value, which is returned, is ignored 
} 

__kernel void reducer(__global int *keyMobj, __global int *valueMobj,__global Data *dataMobj,__global Cent *centMobj,__global int *countMobj,__global double *sumMobj, __global int *mutex) 
{ 
    __local double sum[2][2]; 
    __local int cnt[2]; 

    int i = get_global_id(0); 
    int n,j; 

    if(i<2) 
    cnt[i] = countMobj[i]; 
    barrier(CLK_GLOBAL_MEM_FENCE); 

    n = keyMobj[i]; 
    for(j=0; j<2; j++) 
    { 
    barrier(CLK_GLOBAL_MEM_FENCE); 
      acquire(mutex); 
      sum[n][j] += dataMobj[i].dattr[j]; 
     release(mutex); 
    } 

    if(i<2) 
    { 
    for(j=0; j<2; j++) 
    { 
     sum[i][j] = sum[i][j]/countMobj[i]; 
     centMobj[i].cattr[j] = sum[i][j]; 
    } 
    } 
} 

不幸的是,解決方案似乎並不喜歡爲我工作。當我讀回centMobj到主機的內存,採用

ret = clEnqueueReadBuffer(command_queue2, centMobj, CL_TRUE, 0, (sizeof(Cent) * 2), centNode, 0, NULL, NULL); 
ret = clEnqueueReadBuffer(command_queue2, sumMobj, CL_TRUE, 0, (sizeof(double) * 2 * 2), sum, 0, NULL, NULL); 

它給我的錯誤,錯誤代碼= -5(CL_OUT_OF_RESOURCES)兩個centMobj和sumMobj。

如果在我的原子功能代碼或問題的任何問題,我沒有得到在數據讀取回主機內存。如果我正確使用原子功能,請讓我正確。 預先感謝您。

回答

1

在OpenCL的,工作項之間的同步可以做到只一個工作組內。嘗試跨不同工作組同步工作項的代碼可能適用於某些非常具體(和實現/設備相關)的情況,但在一般情況下將失敗

的解決方案是使用原子學序列化訪問相同的存儲器位置(但不阻塞任何工作項),或不同地重新設計的代碼。

+0

你的意思是說我不能有屬於不同組的工作項之間的同步?即使有原子功能?如果我保留local_work_size = 1,該怎麼辦? –