OpenCL托架比CPU版本慢rgb

时间:2017-05-15 11:47:18

标签: performance opencv opencl gpu imx6

我正在尝试使用OpenCL来改进i.mx6平台上的bayer到rgb转换。我正在使用此the OpenCL Shader进行转换。我期待OpenCL版本比OpenCV的cvtColor bayer更快的时间转换为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支持所需的

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

每个线程处理4个像素(2x2拜耳模式)。这避免了fmod和三元条件(c?t:f)。您可以尝试将此向量化为4,以生成每个线程8x2像素。因此red.xyzw等中有4个红色像素,并且在写入时使用.even.odd进行解交织和交错。

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

答案 2 :(得分:0)

我不知道你的特定设备,但如果这是在一个独立的GPU上,有两个优化会产生很大的不同:

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

  2. 确保您使用合并的读写操作。通常,这意味着确保相邻工作项正在读取相邻的内存位置。