OpenCL Reduce内核仅返回一个值

时间:2018-12-06 17:31:19

标签: c++ opencl

我正在测试OpenCL 2.0精简内核,以获取2d工作组的最大值。

我打电话:

//get global max
float max_v;
max_v = work_group_reduce_max(hsv_fi.z);

if(get_local_id(0) == 0 && get_local_id(1) == 0){
    result[get_group_id(0)] = 1337;// max_v;
}

在我的内核末尾。 1337用于测试目的。我希望一个工作组大小的数组充满1337个值。

但是我不知何故只获得了一个价值。我在内核中做错什么了吗?

我尝试通过以下方式阅读它:

int errcode;
float* resultData = (float*)oclEnvironment._commandQueue.enqueueMapBuffer(resultBuffer, true, CL_MAP_READ, 0, size, 0, 0, &errcode);
std::copy((float*)resultData, (float*)(resultData + size), (float*)dest);

我的*目标指针是:

std::vector<float> resultArray;

我保留工作组的大小,并通过以下方式将指针移交给它(*目标):

resultArray.data()

有什么建议吗?我觉得这是我所想不到的小事。

谢谢!

编辑:

cl::NDRange global(width, height);
//Intel HD 530 can have a max. workgroup size of 256.
int dim1 = 16;
int dim2 = 16;
cl::NDRange local(dim1, dim2);

//Calculate the number of workgroups
int numberOfWorkgroups = ceil((width * height) / (float)(dim1 * dim2));

//each workgroup reduces the data to a single element. This elements are then reduced on host in the final reduction step.
    oclEnvironment._commandQueue.enqueueNDRangeKernel(_kernel, cl::NullRange, global, local);

edit2

我仍然不了解OpenCL在做什么。我有一个480x360的图像,我想作为每个元素3个字节(rgb)的缓冲区。我现在在列表中获得30个有效最大值,但我怀疑不是675个。该图像的分辨率为480 *360。我的最大工作组大小为(16,16,1)。这样我得到了675个工作组。不知何故,我只收到30个值,其他则为零。我尝试将输入填充到480 * 368,以使两个尺寸均为16的倍数。仍然相同。如果那30个值减少了我的整个数据集,而我收到的那个列表的最大值是最大值,那也可以。但是由于我不确定发生了什么,所以我不确定情况是否如此。

1 个答案:

答案 0 :(得分:0)

user10605163的评论将我引到了这个问题。正如他正确地怀疑的那样,我仅从缓冲区读取工作组的大小,而不是工作组的大小乘以sizeof(float)。这让我感到困惑,因为我也忘记了使用sizeof(float)乘数创建缓冲区,因此一开始就认为这是不对的。一旦我调试并尝试了很多代码,这个简单的提示就是解决我的问题的方法,OpenCL可以按我现在期望的那样工作。

我想放在这里的一件事是因为它也让我头疼,那就是如果您尝试避免在数据中使用填充,请不要在内核中写一些东西

if(get_global_linear_id() >= bufferSize)
{
    return;
}else{
    ... work + blocking call (barrier or work_group_reduce_*) ...
}

这将使您的系统崩溃或占用您的GPU,直到您重新启动系统。如果尝试调试,请使用CPU平台,以免冻结系统。但是,请更改上述行为,并使用填充(例如零)或其他填充方式,以免您的工作项像我的那样卡住。

这与实际的解决方案无关,但花了我一些时间来弄清楚,并可能在将来帮助某个人。