OpenCL 2.0 - CPU和GPU上的work_group操作

时间:2016-11-28 15:44:07

标签: c opencl gpu intel

我正在测试以下代码,以便在OpenCL 2.0中使用work_groups内置函数执行并行数组元素添加。 (在这种情况下为inclusive_add和reduce_add)

kernel void(global const float *input,
            global float *sum,
            local float *scratch)
{
    uint local_id = get_local_id(0);
    scratch[local_id] = work_group_inclusive_add(input[get_global_id(0)]);

    if (local_id == get_local_size(0)-1)
        sum[get_group_id(0)] = work_group_reduce_add(scratch[local_id]);
}

如果我用0到15的浮点数组测试它,步长为1,则global_size = 16,local_size = 4我希望结果为" 6.0 22.0 38.0 54.0"如果我选择CPU作为设备,这可以正常工作。

但是只要我选择GPU并运行相同的代码,我就会得到" 0.0 4.0 8.0 12.0" (这只是每个工作组第一个位置的元素)

我错过了什么吗?

我试图做但却没有影响事情的事情:

  1. 添加"屏障(CLK_LOCAL_MEM_FENCE)"在" if"

  2. 之前
  3. 更改本地大小和/或数组大小/全局大小。

  4. 注意:

    • 我使用clEnqueueWriteBuffer传递输入数组,然后使用clEnqueueReadBuffer读取总和

    • CPU:i5 6200u

    • GPU:英特尔高清显卡520

    (是的,他们支持OpenCL 2.0,我可以成功构建内核,ioc64传递-cl-std = CL2.0,就像我在运行时构建程序一样)

1 个答案:

答案 0 :(得分:2)

由于您使用的是work_group_reduce_add错误的方式,因此会得到不同的结果。

OpenCL 2.0 spec说:

  

a中的所有工作项必须遇到此内置函数   工作组执行内核。

当您致电work_group_reduce_add时,情况并非如此。 您需要从那里删除if语句。通过添加只允许一个工作项访问它的if语句,您只需计算一个值的总和。这将归还给你。

work_group_scan_inclusive_add后,数字应如下:

w1: 0,1,2,3 -> 0,1,3,6
w2: 4,5,6,7 -> 4,9,15,22
w3: 8,9,10,11 -> 8,17,27,38
w4: 12,13,14,15 -> 12,25,39,54

work_group_reduce_add之后:

w1: 10
w2: 50
w3: 90
w4: 130

规范中的第二件事:

  

注意:不保证浮点运算的顺序   work_group_reduce_,work_group_scan_inclusive_和   work_group_scan_exclusive_内置函数   half,float和double数据类型。这些浮点的顺序   对于给定的工作组,操作也是不确定的。

所以我计算的包容性扫描后的结果可能不一定是相同的,这就是你在GPU返回的内容(GPU正在返回0,4,8,12,这恰好是每个缓冲区的最后一个值) )。

总结:在work_group_reduce_add之前删除if语句应该解决问题。