我正在测试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个值减少了我的整个数据集,而我收到的那个列表的最大值是最大值,那也可以。但是由于我不确定发生了什么,所以我不确定情况是否如此。
答案 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平台,以免冻结系统。但是,请更改上述行为,并使用填充(例如零)或其他填充方式,以免您的工作项像我的那样卡住。
这与实际的解决方案无关,但花了我一些时间来弄清楚,并可能在将来帮助某个人。