0

我正在尝试使用 OpenCL 在 i.mx6 平台上改进拜耳到 rgb 的转换。我正在使用这个OpenCL 着色器进行转换。我预计 OpenCL 版本将比 OpenCV 的 cvtColor 拜耳到 rgb 转换(使用 for 循环)更快。但事实证明,OpenCL 版本比 OpenCV 基于 CPU 的转换要慢得多。

OpenCV:1280 * 960 图像为 28.3 fps OpenCL:1280 * 960 图像为 7.15 fps

size_t global[] = {1280, 960};
Mat bayer = Mat(960, 1280, CV_8UC1);
Mat rgb_image = Mat(960, 1280, CV_8UC3);
cl_input = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,  width * height, bayer.data , &ret);
if(ret != CL_SUCCESS){
    cout << "OpenCL Buffer Allocation Error\n" ;
    exit(0);
}

cl_output = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, width * height * 3, rgb_image.data, &ret);
if(ret != CL_SUCCESS){
   cout << "OpenCL OP Buffer Error\n" ;
   exit(0);
  }

while(true){
   capture_image(bayer);
   ret = clEnqueueNDRangeKernel(cq, kernel,  2, NULL, global, NULL, 0, NULL, NULL);
   if(ret != CL_SUCCESS){
    cout << ret << " OpenCL kernel exec Error\n" ;
    exit(0);
   }
   ret = clEnqueueReadBuffer(cq, cl_output, CL_TRUE, 0, width * height * 3,  rgb_image.data, 0, NULL, NULL);
   if(ret != CL_SUCCESS){
    cout << "OpenCL OP Buffer read Error\n" ;
    exit(0);
   }
}

在配置方面我有什么遗漏吗?我是 OpenCL 新手,不知道如何在循环内调用 openCL 内核。平台信息如下:

  • 平台名称:Vivante OpenCL 平台
  • 平台配置文件:EMBEDDED_PROFILE
  • 平台版本:OpenCL 1.1
  • 平台供应商:Vivante Corporation

  • 设备名称:Vivante OpenCL 设备

  • 设备配置文件:EMBEDDED_PROFILE
  • 设备版本:OpenCL 1.1
  • 设备供应商:Vivante Corporation
  • 设备最大工作项尺寸:3-D
  • 设备最大工作组大小:1024

PS:我无法在 OpenCV 中使用 OpenCL 支持,因为 i.mx6 没有 OpenCL 完整配置文件,这是 OpenCV 中的 OpenCL 支持所需的

4

3 回答 3

0

我不知道您的特定设备,但如果这是在离散 GPU 上,则有两个优化会产生很大的不同:

  1. 不要从全局内存中重新读取数据(在您链接到的代码中,每个源像素都被读取多次)。相反,使用共享本地内存在工作组中的工作项之间共享从全局内存读取的值。如果您不准备这样做,请使用图像而不是全局内存。这将利用纹理缓存,这将为您带来很多相同的好处。

  2. 确保您使用的是合并读取和写入。一般来说,这意味着确保相邻的工作项正在读取相邻的内存位置。

于 2017-05-22T03:01:28.243 回答
0

唯一看起来有点奇怪的是使用普通缓冲区而不是图像缓冲区,但我不认为这会对执行速度产生巨大影响https://www.khronos.org/registry/OpenCL/sdk/ 1.2/docs/man/xhtml/clCreateImage.html

于 2017-05-15T12:14:14.860 回答
0

每个线程处理 4 个像素(2x2 拜耳模式)。这避免了fmod三元条件句 ( c?t:f)。您可以尝试将其矢量化 4 以产生每个线程 8x2 像素。所以 4 个红色像素red.xyzw等,并在读取时使用.even.odd进行去交错,在写入时使用交错。

我还看到每个工作组只有一个线程。由于您针对的是单一设备类型,请尝试将工作组大小设置为与最大值匹配。也就是说,如果您正在矢量化,则为 32x32 或 16x64。

于 2017-05-16T17:06:41.463 回答