优化内核混洗密钥代码 - OpenCL

时间:2013-05-14 15:36:00

标签: opencl

我刚刚开始进入OpenCL并完成编写内核代码的基础知识。我编写了一个内核代码,用于计算点数组的混洗键。因此,对于多个点N,以3位方式计算混洗密钥,其中深度为d的x位(0

xd = 0 if p.x < Cd.x  
xd = 1, otherwise

随机播放的xyz键如下:

x1y1z1x2y2z2...xDyDzD 

下面给出了编写的内核代码。该点以列主格式输入。

__constant float3 boundsOffsetTable[8] = {
              {-0.5,-0.5,-0.5},
              {+0.5,-0.5,-0.5},
              {-0.5,+0.5,-0.5},
              {-0.5,-0.5,+0.5},
              {+0.5,+0.5,-0.5},
              {+0.5,-0.5,+0.5},
              {-0.5,+0.5,+0.5},
              {+0.5,+0.5,+0.5}
};
uint setBit(uint x,unsigned char position)
{
uint mask = 1<<position;
return x|mask;
}

__kernel void morton_code(__global float* point,__global uint*code,int level, float3          center,float radius,int size){
// Get the index of the current element to be processed
int i = get_global_id(0);
float3 pt; 
pt.x = point[i];pt.y = point[size+i]; pt.z = point[2*size+i];
code[i] = 0;
float3 newCenter;
float newRadius;
if(pt.x>center.x) code = setBit(code,0);
if(pt.y>center.y) code = setBit(code,1);
if(pt.z>center.z) code = setBit(code,2);
for(int l = 1;l<level;l++)
{
    for(int i=0;i<8;i++)
    {
        newRadius = radius *0.5;
        newCenter = center + boundOffsetTable[i]*radius;
        if(newCenter.x-newRadius<pt.x && newCenter.x+newRadius>pt.x && newCenter.y-newRadius<pt.y && newCenter.y+newRadius>pt.y && newCenter.z-newRadius<pt.z && newCenter.z+newRadius>pt.z)
        {
            if(pt.x>newCenter.x) code = setBit(code,3*l);
            if(pt.y>newCenter.y) code = setBit(code,3*l+1);
            if(pt.z>newCenter.z) code = setBit(code,3*l+2);
        }
    }
}
}

它可以工作,但我只是想问我是否遗漏了代码中的某些内容以及是否有办法优化代码。

1 个答案:

答案 0 :(得分:1)

试试这个内核:

__kernel void morton_code(__global float* point,__global uint*code,int level, float3          center,float radius,int size){
// Get the index of the current element to be processed
int i = get_global_id(0);
float3 pt; 
pt.x = point[i];pt.y = point[size+i]; pt.z = point[2*size+i];
uint res;
res = 0;
float3 newCenter;
float newRadius;
if(pt.x>center.x) res = setBit(res,0);
if(pt.y>center.y) res = setBit(res,1);
if(pt.z>center.z) res = setBit(res,2);
for(int l = 1;l<level;l++)
{
    for(int i=0;i<8;i++)
    {
        newRadius = radius *0.5;
        newCenter = center + boundOffsetTable[i]*radius;
        if(newCenter.x-newRadius<pt.x && newCenter.x+newRadius>pt.x && newCenter.y-newRadius<pt.y && newCenter.y+newRadius>pt.y && newCenter.z-newRadius<pt.z && newCenter.z+newRadius>pt.z)
        {
            if(pt.x>newCenter.x) res = setBit(res,3*l);
            if(pt.y>newCenter.y) res = setBit(res,3*l+1);
            if(pt.z>newCenter.z) res = setBit(res,3*l+2);
        }
    }
}
//Save the result
code[i] = res;
}

优化规则:

  1. 避免全局内存(你直接从全局内存使用“代码”,我改变了),你现在应该看到性能提高3倍。
  2. 避免使用ifs,如果可能,请使用“select”。 (参见OpenCL文档)
  3. 在内核中使用更多内存。您不需要在位级操作。在int级别的操作会更好,并且可以避免对“setBit”的大量调用。然后你可以在最后构建你的结果。
  4. 另一个有趣的事情。如果您在3D级别操作,则可以使用float3变量并使用OpenCL运算符计算距离。这可以大大提高你的表现。 BUt还需要完全重写内核。