组中的opencl本地内存半线程得到正确执行

组中的opencl本地内存半线程得到正确执行,opencl,gpgpu,gpu,Opencl,Gpgpu,Gpu,我已经在opencl中编写了一个内核,它使用本地内存来获得更快的执行速度。这是我第一次使用本地内存。我的全球工作规模=16,本地工作规模=8 Opencl内核:mapper.cl #pragma OPENCL EXTENSION cl_khr_fp64 : enable typedef struct data { double dattr[10]; int d_id; int bestCent; }Data; typedef struct cent { double catt

我已经在opencl中编写了一个内核,它使用本地内存来获得更快的执行速度。这是我第一次使用本地内存。我的全球工作规模=16,本地工作规模=8

Opencl内核:mapper.cl

#pragma OPENCL EXTENSION cl_khr_fp64 : enable
typedef struct data
{
  double dattr[10];
  int d_id;
  int bestCent;
}Data;


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

__kernel void mapper(__global int *keyMobj, __global int *valueMobj, __global Data *dataMobj, __global Cent *centMobj)
{
    int bx   = get_group_id(0);    
    int tx   = get_local_id(0);
    int size = get_local_size(0);

    __local double localData[8][2];
    __local double localCent[2][2];
    __local int local_id[8];

    int index = tx + bx*size;

    int j,k,color=0;
    double dmin=1000000.0, dx;

    for(j=0; j<2; j++)
    {
          if(tx<2)
              localCent[tx][j] = centMobj[tx].cattr[j];

          localData[tx][j] = dataMobj[index].dattr[j];
          local_id[tx] = dataMobj[index].d_id;

    }
barrier(CLK_LOCAL_MEM_FENCE); 


    for(j=0; j<2; j++)     
     {
        dx = 0.0;
        for(k=0; k<2; k++)
            dx+= ((localCent[j][k] - localData[index][k]) * (localCent[j][k] - localData[index][k]));

        if(dx<dmin)            
        {  color = j;   
           dmin = dx;
        }
     }  
    keyMobj[index]   = color;
    valueMobj[index] = local_id[tx];
}
#pragma OPENCL扩展cl_khr_fp64:启用
typedef结构数据
{
双dattr[10];
国际开发署;
智力最好;
}数据;
类型定义结构分
{
双卡特尔[5];
国际货币联盟;
}分;
__内核无效映射器(uu全局int*keyMobj、u全局int*valueMobj、u全局数据*dataMobj、u全局百分比*centMobj)
{
int bx=获取组id(0);
int tx=获取本地id(0);
int size=get\u local\u size(0);
__本地双本地数据[8][2];
__本地双本地分[2][2];
__local int local_id[8];
int index=tx+bx*大小;
int j,k,color=0;
双dmin=1000000.0,dx;

对于(j=0;j而言,此程序的问题在于您超出了数组的范围。这解释了为什么您仅使用8个工作项就可以获得正确的结果,而不使用16个工作项

localData
local
内存空间中的一组双精度数组:

 __local double localData[8][2];
我们还有一个变量
索引
,其定义如下:

int index = tx + bx*size;
//get_local_id(0) + get_group_id(0) * get_local_size(0) = get_global_size(0)
16个工作项的索引范围值[0-15]。在下一行:

dx+= ((localCent[j][k] - localData[index][k])
     * (localCent[j][k] - localData[index][k]));

localData
变量是使用
index
变量引用的,即使本地数组的范围只能是[0-8]。

此程序的问题是您超出了数组的范围。这解释了为什么您只能使用8个工作项而不能使用16个工作项来获得正确的结果

localData
local
内存空间中的一组双精度数组:

 __local double localData[8][2];
我们还有一个变量
索引
,其定义如下:

int index = tx + bx*size;
//get_local_id(0) + get_group_id(0) * get_local_size(0) = get_global_size(0)
16个工作项的索引范围值[0-15]。在下一行:

dx+= ((localCent[j][k] - localData[index][k])
     * (localCent[j][k] - localData[index][k]));

使用
索引
变量引用
localData
变量,即使本地数组的范围只能是[0-8].

此时请清除我的命令。假设我正在编写一个计算前512个数字的平方的程序。我使用的工作组大小=64。假设我正在使用本地内存执行与我的块(工作组)大小相同的操作大小。你的意思是我不需要创建512个工作项??64个线程就足够了吗?因为我使用的是共享内存??另外,你说我的本地数据是使用范围为[0-15]的索引引用的.但由于我一次使用8个工作项来从全局内存获取数据到本地内存,并执行我的计算。因此索引应该从[0-7]计算其范围根据它的公式。我很困惑。任何在共享内存opencl上有一些示例的Web链接都会非常有用。@sandeep.ganage我认为您面临的主要问题是本地寻址和全局寻址之间的差异。您使用的变量
index
将为您提供工作项的全局ID,它将介于0和您拥有的工作项数量之间。在每个工作组中,您创建一个大小为8的本地数组。您只能使用0-7之间的索引寻址该本地数组。即使是线程1024,它也只能使用索引0-7访问此数组。本地数据不能与其他工作组共享。@sandeep.ganage关于您的squ例如,您应该有512个工作组大小为64的工作项。每个工作组将包含64个整数的数组。工作组中的每个工作项可以基于本地ID(0-64)分配给该数组的一个块。要计算的值可以使用全局ID(0-512)拉入例如,工作项129将位于本地ID为1的工作组3中。它将从全局数组中的#129中提取数据,并将其放置在本地#1中。然后它将在本地#1上执行计算。@sandeep.ganage No。在这种情况下不会有性能优势。实际上,在这种情况下,可能会有性能损害额外访问本地内存(比寄存器慢)的原因。这只是一个玩具示例,让您能够理解本地内存和全局内存是如何映射的。在您最初的问题中,我不确定本地内存使用的影响会有多大,但我希望最多是边际影响。此时请澄清我的问题。假设我正在编写一个计算前512个数字平方的程序。我是using work group size=64。假设我在操作中使用本地内存,其磁贴大小与我的块(工作组)大小相同。因此,你的意思是我不必创建512个工作项??64个线程就足够了吗?因为我在使用共享内存??另外,你说我的本地数据是使用范围为[0-15]的索引引用的.但由于我一次使用8个工作项来从全局内存获取数据到本地内存,并执行我的计算。因此索引应该从[0-7]计算其范围根据它的公式。我很困惑。任何在共享内存opencl上有一些示例的Web链接都会非常有用。@sandeep.ganage我认为您面临的主要问题是本地寻址和全局寻址之间的差异。您使用的变量
index
将为您提供工作项的全局ID,它将介于0和您拥有的工作项数量之间。在每个工作组中,您创建一个大小为8的本地数组。您只能使用0-7之间的索引寻址该本地数组。即使是线程1024,它也只能使用索引0-7访问此数组。本地数据不能与其他工作组共享。@sandeep.ganage关于您的squ例如,您应该有512个工作组大小为64的工作项。每个工作组将包含一个由64个整数组成的数组。工作组中的每个工作项可以基于本地ID(0-64)分配给该数组的一个块。要计算的值可以在usi中提取