问题描述
我正在尝试用 OpenCL/C++ 编写一个排序函数和一个求和函数。然而,虽然这两个函数在较小的数据集上都可以正常工作,但它们都不适用于任何显着长度的数据集。我尝试使用的数据集大约有 200 万个条目,但函数在大约 500 个时停止工作。任何有关为什么会这样的帮助将不胜感激。 OpenCL 代码如下。
kernel void sum(global const double* A,global double* B) {
int id = get_global_id(0);
int N = get_global_size(0);
B[id] = A[id];
barrier(CLK_GLOBAL_MEM_FENCE);
for (int i = 1; i < N/2; i *= 2) { //i is a stride
if (!(id % (i * 2)) && ((id + i) < N))
B[id] += B[id + i];
barrier(CLK_GLOBAL_MEM_FENCE);
}
}
还有 C++ 代码:
std::vector<double> temps(100000,1);
// Load functions
cl::Kernel kernel_sum = cl::Kernel(program,"sum");
// Set up variables
size_t elements = temps.size();
size_t size = temps.size() * sizeof(double);
size_t workgroup_size = 10;
size_t padding_size = elements % workgroup_size;
// Sum
if (padding_size) {
std::vector<double> temps_padding(workgroup_size - padding_size,0);
temps.insert(temps.end(),temps_padding.begin(),temps_padding.end());
}
std::vector<double> temps_sum(elements);
size_t output_size = temps_sum.size() * sizeof(double);
cl::Buffer sum_buffer_1(context,CL_MEM_READ_ONLY,size);
cl::Buffer sum_buffer_2(context,CL_MEM_READ_WRITE,output_size);
queue.enqueueWriteBuffer(sum_buffer_1,CL_TRUE,size,&temps[0]);
queue.enqueueFillBuffer(sum_buffer_2,output_size);
kernel_sum.setArg(0,sum_buffer_1);
kernel_sum.setArg(1,sum_buffer_2);
queue.enqueueNDRangeKernel(kernel_sum,cl::NullRange,cl::NDRange(elements),cl::NDRange(workgroup_size));
queue.enqueueReadBuffer(sum_buffer_2,output_size,&temps_sum[0]);
double summed = temps_sum[0];
std::cout << "SUMMED: " << summed << std::endl;
我试过四处看看,但我完全被困住了。
解决方法
您正在尝试使用障碍来跨 个工作组进行同步。这行不通。 Barriers are for synchronising within work groups。
工作组彼此之间没有按照明确定义的顺序运行;您只能在工作组中使用这种归约算法。您可能需要使用第二个内核传递来组合来自各个工作组的结果,或者在主机 CPU 上执行此部分。 (或者修改你的算法以某种方式使用原子等)