根据我的previous问题:
我仍在尝试复制图像(没有实际原因,只是从一个简单的开始):
图片包含200 * 300 == 60000像素。
根据CL_DEVICE_MAX_WORK_GROUP_SIZE
,最大工作项数为4100。
kernel1:
std::string kernelCode =
"void kernel copy(global const int* image, global int* result)"
"{"
"result[get_local_id(0) + get_group_id(0) * get_local_size(0)] = image[get_local_id(0) + get_group_id(0) * get_local_size(0)];"
"}";
队列:
for (int offset = 0; offset < 30; ++offset)
queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(offset * 2000), cl::NDRange(60000));
queue.finish();
给出了段错误,出了什么问题?
使用最后一个参数cl::NDRange(20000)
它不会,但只返回部分图像。
另外我不明白,为什么我不能使用这个内核:
kernel2:
std::string kernelCode =
"void kernel copy(global const int* image, global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
查看第31张幻灯片上的this演示文稿:
为什么我不能简单地使用global_id?
EDIT1
平台:AMD加速并行处理
设备:AMD Athlon(tm)II P320双核处理器
EDIT2
结果基于huseyin tugrul buyukisik的回答:
EDIT3
使用最后一个参数cl::NDRange(20000)
:
内核是第一种方式。
EDIT4
std::string kernelCode =
"void kernel copy(global const int* image, global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
//...
cl_int err;
err = queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(0), cl::NDRange(59904), cl::NDRange(128));
if (err == 0)
qDebug() << "success";
else
{
qDebug() << err;
exit(1);
}
打印成功。
也许这是错的?
int size = _originalImage.width() * _originalImage.height();
int* result = new int[size];
//...
cl::Buffer resultBuffer(context, CL_MEM_READ_WRITE, size);
//...
queue.enqueueReadBuffer(resultBuffer, CL_TRUE, 0, size, result);
有罪的是:
cl::Buffer imageBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(int) * size, _originalImage.bits());
cl::Buffer resultBuffer(context, CL_MEM_READ_ONLY, sizeof(int) * size);
queue.enqueueReadBuffer(resultBuffer, CL_TRUE, 0, sizeof(int) * size, result);
我使用size
代替sizeof(int) * size
。
答案 0 :(得分:2)
编辑2:
请尝试非常量内存说明符(可能与您的cpu不兼容):
std::string kernelCode =
"__kernel void copy(__global int* image, __global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
您也可能需要更改缓冲区选项。
修改强>
您在“全局”和“内核”说明符之前忘记了三'__,请尝试:
std::string kernelCode =
"__kernel void copy(__global const int* image, __global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
总元素是60000,但是你正在做一个偏移量+ 60000,它会溢出并读取/写入未被利用的区域。
opencl 1.2 c ++绑定的ndrange的通常用法必须是:
cl_int err;
err=cq.enqueueNDRangeKernel(kernelFunction,referenceRange,globalRange,localRange);
然后检查错误以查找您寻找的真实错误代码。 0表示成功。**
如果您想将工作分成较小的部分,则应将每个单位的范围限制为60000 / N
如果除以30份,则
for (int offset = 0; offset < 30; ++offset)
queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(offset * 2000), cl::NDRange(60000/30));
queue.finish();
并仔细检查每个缓冲区的大小,例如的sizeof(cl_int)* arrElementNumber 强>
对于设备整数,整数的大小可能不相同。你需要60000个元素?然后在创建缓冲区时需要240000个字节作为大小传递。
为了兼容性,如果要在另一台机器上运行此代码,则应在创建缓冲区之前检查整数的大小。
你可能已经知道了,但无论如何我会告诉你:
CL_DEVICE_MAX_WORK_GROUP_SIZE
是可以在计算单元中共享本地/共享内存的线程数。你不需要为此分工。 Opencl自动执行此操作,并为整个工作中的每个线程提供唯一的全局ID,并为计算单元中的每个线程提供唯一的本地ID。如果CL_DEVICE_MAX_WORK_GROUP_SIZE是4100,那么它可以创建在计算单元中共享相同变量的线程。您只需一个adition即可在一次扫描中计算所有60000个变量:为此创建多个工作组,每个组都有一个组ID。
// this should work without a problem
queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(0), cl::NDRange(60000));
如果您有AMD gpu或cpu,并且如果您使用的是msvc,则可以从amd站点安装codexl并从下拉菜单中选择系统信息以查看相关数字。
哪种设备属于您的设备?我找不到任何最大工作组大小为4100的设备!我的cpu有1024,gpu有256.那是xeon-phi吗?
例如,总工作项可以大到工作组大小的256 * 256倍。
Codexl还有其他不错的功能,例如性能分析,如果您需要最高性能和错误修正,则可以跟踪代码。