如何在OpenCL中使用并行缩减实现求和?

时间:2015-02-26 07:44:56

标签: c parallel-processing opencl

我试图实现一个并行缩减的内核。下面的代码有时会起作用,我无法确定它出现错误的原因。

__kernel void summation(__global float* input, __global float* partialSum, __local float *localSum){
int local_id = get_local_id(0);
int workgroup_size = get_local_size(0);
localSum[local_id] = input[get_global_id(0)];

for(int step = workgroup_size/2; step>0; step/=2){
    barrier(CLK_LOCAL_MEM_FENCE);

    if(local_id < step){
    localSum[local_id] += localSum[local_id + step];
    }
}
if(local_id == 0){
    partialSum[get_group_id(0)] = localSum[0];
}}

基本上,我将每个工作组的值相加并将每个工作组的总数存储到partialSum中,最终求和在主机上完成。下面是设置求和值的代码。

size_t global[1];
size_t local[1];

const int DATA_SIZE = 15000;
float *input = NULL;
float *partialSum = NULL;
int count = DATA_SIZE;

local[0] = 2;
global[0] = count;
input = (float *)malloc(count * sizeof(float));
partialSum = (float *)malloc(global[0]/local[0] * sizeof(float));

int i;
for (i = 0; i < count; i++){
    input[i] = (float)i+1;
}

当输入的大小不是2的幂时,我认为它有事可做?我注意到它开始出现在8000左右的数字。欢迎任何帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

  

我认为当输入的大小不是2的幂时它有事可做?

是。考虑当你试图减少9个元素时会发生什么。假设您启动了1个包含9个工作项的工作组:

for (int step = workgroup_size / 2; step > 0; step /= 2){
    // At iteration 0: step = 9 / 2 = 4
    barrier(CLK_LOCAL_MEM_FENCE);

    if (local_id < step) {
        // Branch taken by threads 0 to 3
        // Only 8 numbers added up together! 
        localSum[local_id] += localSum[local_id + step];
    }
}

你永远不会总结第9个元素,因此减少是不正确的。一个简单的解决方案是用足够的零填充输入数据,使工作组大小成为下一个2的幂。