OpenCL Kernel 结构不支持二级指针?

    最近在做一个关于用OpenCL来处理字符串匹配的小程序,

导师给出的题目是这样的,首先生成一个长度尽可能大的随机字符串(由ATCG这四个字符组成),然后设定1000个长度在2-10之间的随机字符串(也是由ATCG四个字符组成,然后将每个字符小字符串与大字符串去匹配,返回匹配项的下标值。

    由于笔者才疏学浅,所以刚开始用于测试的算法是自己写的最笨的穷举法:

由于要和cpu比较运行时间,所以在主程序中:

 

char* X=(char*)malloc(10000*seizeof(char));  //动态分配大字符串的空间

char**Y=(char**)malloc(1000*seizeof(clar*));//动态分配指向小字符串指针的空间

for(int i=0;i<1000;i++)

{

    Y[i]=(char*)malloc(11*seizeof(char));            //动态分配每个小字符串的空间

}

 

分配空间后,就给他们随机赋值,这里代码省略,

接下来就是匹配代码(返回匹配项代码省略):

 

void PipeiCPU(char **Y,char *X)

{

    int i=0;

    for(int j=0;j<1000;j++)

    {

        int k=0;

        while(X[i]!='/0')

        {

            while(Y[j][k]!='/0')

            {

                if(Y[j][k]==X[i+k])

                    k++;

                else break;

            }

            i++;

        }

        j++;

    }

}

 

好,在主程序下测试成功了,接下来就是写opencl的内核程序,我心想也不难,我设定了1024个work-items,也就是说gpu能够并行执行1024个相同的__kernel函数,我之所以设定1024个work-items的原因是有1000个小字符串,我希望这1000个小字符并行去匹配,这样一来的话效率的提升不就显而易见了。

好,我照着葫芦画瓢

下面是我的kernel程序:

 

__kernel void PipeiGPU(const __global char *X

                                 const __global char **Y)

{

    uint y=get_global_id(0);

 

    if(y<1000)

      .........

}

其实kernel里的程序相比主程序反而简单了,少了一层对小字符串指针的遍历,因为y取到了当前工作的work-items的ID,也就是说我们知道了这个kernel在哪个work-item下工作,这样我们就知道这是哪个小字符串了。

好,原本以为一切就绪了,一编译,结果出问题了,编译器不认识const __global char **Y,后来网上一查资料,有人说opencl C是不支持二级指针的,那怎么办?我一下子郁闷了。

后来没办法,由于只能传一级指针,我只能先把前面的小字符串存放到一个指针下,我给这个指针分配了

1000*11+1个字符空间

char *T=(char*)malloc((1000*11+1)seizeof(char));

为什么这么分配,我把每个小字符串长度设定为11,统计出来不满11的,我就在后面加空格,至于最后一个一是个结束符。

然后我还得定义一个指针p,当我从T中取每个小字符串的时候,赋给p

char *P=(char*)malloc(11*seizeof(char));

 

然后写kernel:

 

__kernel void PipeiGPU(const __global char* X

                                 const __global char* T

                                 const __global char* P)

{

    uint y=get-global_id(0);

    int p=0;

    for(int i=y*11;i<(y+1)*11;i++)//1:将单个小字符串写到P里

    {

        if(T[i]!=' ')

        {

            P[p]=T[i]; 

            p++;

             }

         else break;

    }

    P[p]='/0';

 

     int j=0;

    while(X[j]!='/0')                    //2:P与X进行匹配

    {

        int p=0;

        while(P[p]!='/0')

        {

            if(X[j]==P[p])

               p++;

            else break;

        }

        j++;

    }  

}

终于!!!!执行成功,最后测试发现gpu的速度是cpu速度执行的1.5倍,效果并不是很理想,重要的一点原因是因为在kenrel里多了个1这个步骤,浪费了很多时间,呵呵。

当然,算法方面也有很大的余地,所以接下来笔者准备改良一下算法,希望能找到更好的解决方法,提高更多的效率,呵呵。

 

你可能感兴趣的:(OpenCL)