使用带指针的async_work_group_copy()?

时间:2017-03-16 09:00:32

标签: opencl gpgpu amd

__kernel void kmp(__global char pattern[1*4], __global char* string, __global int failure[1*4], __global int ret[1], int g_length, int l_length, int thread_num){
    int pattern_num = 1;
    int pattern_size = 4;
    int gid = get_group_id(0);
    int glid = get_global_id(0);
    int lid = get_local_id(0);
    int i, j, x = 0;

    __local char *tmp_string;
    event_t event;

    if(l_length < pattern_size){
            return;
    }

    event = async_work_group_copy(tmp_string, string+gid*g_length, g_length, 0);
    wait_group_events(1, &event);

这些是我代码的一部分。

我想在文本中找到匹配的模式。

首先,在CPU端初始化我的所有模式和字符串(我从文本读取字符串并实验性地仅使用一种模式)。

其次,将它们转移到名为kmp的内核。 (参数l_length和g_length是字符串的大小,将被复制到盖子和glid每个。换句话说,字符串)

最后,我想将分割后的字符串复制到本地内存中。

但是有一个问题。当我使用async_work_group_copy()复制它们时,我无法获得任何有效结果。

当我将__local char * tmp_string更改为数组时,问题仍然存在。

我想做的是1)分割字符串2)将它们复制到每个线程3)并计算匹配的数字。

我想知道这段代码有什么问题。谢谢!

1 个答案:

答案 0 :(得分:0)

OpenCL规范有:

  

异步副本由工作组中的所有工作项执行   因此,所有工作项必须遇到内置函数   工作组使用相同的参数值执行内核;   否则结果是不确定的。

所以你不应该提前退回团队中的任何工作项目。无论如何,早期返回更适合CPU。如果这是GPU,只需使用增强/填充输入输出缓冲区计算最后一个溢出部分。

否则,您可以提前返回整个组(这应该可以工作,因为没有工作项点击任何异步复制指令)并在cpu上执行剩余的工作,除非设备不使用任何工作项(但是专用的秘密管道)异步复制操作。

也许你可以将第二个内核(同时在另一个队列中)排队,以使用workgroupsize = remaining_size来计算剩余的最新项目,而不是使用额外的缓冲区大小或控制逻辑。

如果要将某些内容复制到其中,则需要初始化/分配

tmp_string。所以你可能需要它的数组版本。

async_work_group_copy不是同步点,因此需要一个屏障才能获取本地内存的最新位以用于异步复制到全局。

            __kernel void foo(__global int *a, __global int *b)
            {
                int i=get_global_id(0);
                int g=get_group_id(0);
                int l=get_local_id(0);
                int gs=get_local_size(0);
                __local int tmp[256];
                event_t evt=async_work_group_copy(tmp,&a[g*gs],gs,0);
                // compute foobar here in async to copies
                wait_group_events(1,&evt);

                tmp[l]=tmp[l]+3; // compute foobar2 using local memory
                barrier(CLK_LOCAL_MEM_FENCE);

                event_t evt2=async_work_group_copy(&b[g*gs],tmp,gs,0);
                // compute foobar3 here in async to copies
                wait_group_events(1,&evt2);
            }