我目前正在使用NVIDIA Tesla C1060(驅動程序版本195.17)上的OpenCL項目。不過,我收到了一些我無法解釋的奇怪行爲。這裏是一個困擾我的代碼(減少清晰度和測試目的):在OpenCL中使用本地內存的奇怪行爲
kernel void TestKernel(global const int* groupOffsets, global float* result,
local int* tmpData, const int itemcount)
{
unsigned int groupid = get_group_id(0);
unsigned int globalsize = get_global_size(0);
unsigned int groupcount = get_num_groups(0);
for(unsigned int id = get_global_id(0); id < itemcount; id += globalsize, groupid += groupcount)
{
barrier(CLK_LOCAL_MEM_FENCE);
if(get_local_id(0) == 0)
tmpData[0] = groupOffsets[groupid];
barrier(CLK_LOCAL_MEM_FENCE);
int offset = tmpData[0];
result[id] = (float) offset;
}
}
此代碼應加載每個工作組到本地內存的偏移量,然後讀回,並將其寫入到相應的outputvector條目。對於大多數工作項目而言,這是可行的,但是對於每個工作組而言,本地ID爲1到31的工作項會讀取不正確的值。 我的輸出向量(對於workgroupsize = 128)是如下:
index 0: 0
index 1- 31: 470400
index 32-127: 0
index 128: 640
index 129-159: 471040
index 160-255: 640
index 256: 1280
index 257-287: 471680
index 288-511: 1280
...
我期望的輸出將是
index 0-127: 0
index 128-255: 640
index 256-511: 1280
...
奇怪的是:只有當我使用較少然後ITEMCOUNT工作項出現該問題(因此,當globalsize> = itemcount時,它會按預期工作,這意味着每個工作項只處理一個條目)。所以我猜測它與循環有關。 有誰知道我在做什麼錯,如何解決它?
更新: 我發現,好像如果我改變工作
if(get_local_id(0) == 0)
tmpData[0] = groupOffsets[groupid];
到
if(get_local_id(0) < 32)
tmpData[0] = groupOffsets[groupid];
哪個更使我感到驚訝,所以雖然它可能會解決問題,我不要以這種方式修復它(因爲它可能會打破其他時間)。 除此之外,我寧願避免在Geforce 8xxx類硬件上運行時由於額外的(根據我的理解,未合併)內存訪問而損失性能。 所以問題依然存在。
我爲了簡單而減少的含義是,我真正想要的不是將groupid公佈到每個vektor條目中。我發佈的結果是運行psted內核的結果(至少一次運行,不同運行之間的錯誤條目似乎有所不同)。 我已經確保itemcount是localworksize的倍數,但是從我的測試中,無論哪種方式都沒有關係(因爲無論itemcount是否可以被本地工作大小整除,行爲基本相同) – Grizzly 2010-02-02 16:52:00
您是否嘗試過也把全球記憶的障礙?即「屏障(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE)」 – Tom 2010-02-02 21:15:06