OpenCL中使用本地内存的奇怪行为

OpenCL中使用本地内存的奇怪行为,opencl,Opencl,我目前正在一个项目上工作,该项目在NVIDIA Tesla C1060(驱动程序版本195.17)上起诉OpenCL。然而,我有一些奇怪的行为,我真的无法解释。下面是让我困惑的代码(为了清晰和测试目的而减少): 我期望的结果是 index 0-127: 0 index 128-255: 640 index 256-511: 1280 ... 奇怪的是:只有当我使用的工作项少于itemcount时,问题才会出现(因此,当globalsize>=itemcount时,它会像预期的那样工作,这意

我目前正在一个项目上工作,该项目在NVIDIA Tesla C1060(驱动程序版本195.17)上起诉OpenCL。然而,我有一些奇怪的行为,我真的无法解释。下面是让我困惑的代码(为了清晰和测试目的而减少):

我期望的结果是

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(获取本地id(0)<32)
tmpData[0]=groupoffset[groupid];
这让我更加惊讶,所以虽然它可能会解决问题,但我觉得用这种方式解决它并不舒服(因为它可能会在其他时间中断)。 此外,我更愿意避免在Geforce 8xxx类硬件上运行时由于额外(据我所知,该硬件未校准)内存访问而导致性能损失。
因此问题仍然存在。

首先,而且重要的是,您需要注意,
itemcount
是本地工作大小的倍数,以避免在执行屏障时出现分歧

在处理器上执行内核的工作组中的所有工作项都必须先执行此函数,然后才允许任何工作项继续执行超出该界限。执行内核的工作组中的所有工作项都必须遇到此函数

您可以按如下方式实现此功能:

unsigned int itemcountrounded = get_local_size(0) * ((itemcount + get_local_size(0) - 1) / get_local_size(0));
for(unsigned int id = get_global_id(0); id < itemcountrounded; id += globalsize, groupid += groupcount)
{
    // ...
    if (id < itemcount)
        result[id]   = (float) offset;
}
unsigned int itemcountrounded=get_local_size(0)*(itemcount+get_local_size(0)-1)/get_local_size(0));
for(unsigned int id=get_global_id(0);id

你说代码是为了简单而减少的,如果你运行你发布的东西会怎么样?只是想知道是否也需要在全局内存上设置障碍。

我所说的简化的意思是,我真正尝试的不是将groupid复制到每个vektor条目中。我发布的结果是运行psted内核的结果(至少在一次运行中,不正确的条目似乎因运行而异)。我已经确保itemcount是localworksize的倍数,但是从我的测试来看,这两种方式都无关紧要(因为无论itemcount是否可被本地工作大小整除,行为基本相同),您是否也尝试过在全局内存上设置障碍?i、 e.
barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE)
if(get_local_id(0) == 0)
     tmpData[0] = groupOffsets[groupid]; 
if(get_local_id(0) < 32)
     tmpData[0] = groupOffsets[groupid]; 
unsigned int itemcountrounded = get_local_size(0) * ((itemcount + get_local_size(0) - 1) / get_local_size(0));
for(unsigned int id = get_global_id(0); id < itemcountrounded; id += globalsize, groupid += groupcount)
{
    // ...
    if (id < itemcount)
        result[id]   = (float) offset;
}