OpenCL回写缓冲区

时间:2015-12-25 03:44:20

标签: c++ opencl

当我尝试在主机缓冲区上写回opencl代码的输出时,我总是得到一个零/零的数组

这是内核:

void kernel convolution(global const int* A, global const int* B,
        global int* C, const int size_1, const int size_2) {
    float prob_1[256];
    float prob_2[256];
    float cum_prob_1[256];
    float cum_prob_2[256];
    prob_1[get_global_id(0)] = (A[get_global_id(0)]/size_1);
    prob_2[get_global_id(0)] = (B[get_global_id(0)]/size_2);
    cum_prob_1[0] = prob_1[0];
    cum_prob_1[get_global_id(0)+1] = cum_prob_1[get_global_id(0)] + prob_1[get_global_id(0)+1];
    cum_prob_2[0] = prob_2[0];
    cum_prob_2[get_global_id(0)+1] = cum_prob_2[get_global_id(0)] + prob_2[get_global_id(0)+1];
    int j = 0;
    for (int i = 0; i < 256; i++) {
        if (cum_prob_1[i] <= cum_prob_2[j]) {
            C[i] = j;
        }
        else {
            while (cum_prob_1[i] > cum_prob_2[j])
                j++;
            if (cum_prob_2[j] - cum_prob_1[i] > cum_prob_1[i] - cum_prob_2[j - 1]) {
                C[i] = j - 1;
            }
            else {
                C[i] = j;
            }
        }
    }
}

以下是代码的其余部分:

// create buffers on the device
cl::Buffer buffer_A(context, CL_MEM_READ_WRITE, sizeof(int) * 256);
cl::Buffer buffer_B(context, CL_MEM_READ_WRITE, sizeof(int) * 256);
cl::Buffer buffer_C(context, CL_MEM_READ_WRITE, sizeof(int) * 256);

//create queue to which we will push commands for the device.
cl::CommandQueue queue(context, default_device);

//write arrays A and B to the device
queue.enqueueWriteBuffer(buffer_A, CL_TRUE, 0, sizeof(int) * 256, pixls_1);
queue.enqueueWriteBuffer(buffer_B, CL_TRUE, 0, sizeof(int) * 256, pixls_2);

//alternative way to run the kernel
cl::Kernel kernel_add = cl::Kernel(program, "convolution");
kernel_add.setArg(0, buffer_A);
kernel_add.setArg(1, buffer_B);
kernel_add.setArg(2, buffer_C);
kernel_add.setArg(3, size_1);
kernel_add.setArg(4, size_2);

queue.enqueueNDRangeKernel(kernel_add, cl::NullRange, cl::NDRange(sizeof(cl_mem)), cl::NullRange);
queue.finish();

int lookup_table[256];
for (size_t i = 0; i < 256; i++) {
    lookup_table[i] = 10;
}
//read result C from the device to array C
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, sizeof(int) * 256, lookup_table);

//map the new pixel values from the lookup table
for (int i = 0; i < inp_image.total(); i++) {
    myData[i]= lookup_table[myData[i]];
}

system("pause");
return 0;

lookup_table是给我零/空的,但它应该在所有单元格中给我5 ...

1 个答案:

答案 0 :(得分:1)

我在你的代码中看到两件非常可疑的事情:

  1. 致电enqueueNDRangeKernel(),特别是使用cl::NDRange(sizeof(cl_mem))来指定全球工作项维度数组...... AFAICT,这没有任何意义,但是我可能会在这里错过一些东西。

  2. 在内核中使用临时数组:它在我看来非常像你忘了声明它们local。会是这样的吗?如果是这样,您需要在初始化部分之后添加barrier(CLK_LOCAL_MEM_FENCE)

  3. 无论如何,我的感觉是你的代码用于大小为256的工作组,临时数组有local内存。我可能错了,但无论如何,内核的运行方式和逻辑也存在问题。