0

我第一次开始使用 OpenCL,我正在尝试在这个站点 http://www.karlosp.net/blog/2012/05/03/opencl-opencv-sobel-中做这个示例进行 sobel 边缘检测边缘检测器/ 但是当运行 gpu 编号的内核时 fps 小于 15 并且 gpu 利用率小于 5% 如何运行 gpu 的所有线程,如 openmp 以使利用率低于 95%

编码

核心代码

_ kernel void sobel( _global float *A, __global float *R, uint width, uint height) {

int globalIdx = get_global_id(0);
int globalIdy = get_global_id(1);
int index = width * globalIdy + globalIdx;
float a,b,c,d,e,f,g,h,i;
float sobelX = 0;
float sobelY = 0;
if(index > width && index < (height*width)-width && (index % width-1) > 0 && (index % width-1) < width-1){
    a = A[index-1-width] * -1.0f;
    b = A[index-0-width] *  0.0f;
    c = A[index+1-width] * +1.0f;
    d = A[index-1] * -2.0f;
    e = A[index-0] *  0.0f;
    f = A[index+1] * +2.0f;
    g = A[index-1+width] * -1.0f;
    h = A[index-0+width] *  0.0f;
    i = A[index+1+width] * +1.0f;
    sobelX = a+b+c+d+e+f+g+h+i;

    a = A[index-1-width] * -1.0f;
    b = A[index-0-width] * -2.0f;
    c = A[index+1-width] * -1.0f;
    d = A[index-1] * 0.0f;
    e = A[index-0] * 0.0f;
    f = A[index+1] * 0.0f;
    g = A[index-1+width] * +1.0f;
    h = A[index-0+width] * +2.0f;
    i = A[index+1+width] * +1.0f;
    sobelY = a+b+c+d+e+f+g+h+i;
}


R[index] = sqrt(pow(sobelX,2) + pow(sobelY,2));

}

4

1 回答 1

0

您链接到的代码有一些效率低下(没有特定顺序):

  • 在循环内的每个 OpenCL 调用之后对 clFinish 的调用是不必要的。首先,clEnqueueWriteBuffer 和 clEnqueueReadBuffer 都使用设置为 CL_TRUE 的阻塞,即它们在写入/读取完成之前不会返回(阻塞函数调用的定义)。

  • 在将 unsigned char 图像发送到 GPU 之前,您将其转换为浮点图像。这不是必需的,因为 GPU 能够使用 unsigned char 并且可以在需要时进行类型转换为浮动。在 CPU 上转换为浮点数,然后发送到 GPU 会导致发送 4 倍的数据量(每个通道每个像素 4 字节与 1 字节)。

  • 您调用 cvWaitKey(10),暂停 10 毫秒以等待按键,因此此代码永远不会超过每秒 100 帧(小问题)。

  • RGB 到灰度的转换可以在 GPU 上完成,代价是发送 3 个无符号字符,因此需要进行权衡。

你的计时方法也有缺陷。您的代码测量加载、处理和显示单个帧所花费的时间。处理由 OpenCL 和 OpenCV 组件组成。您应该分别对每一项进行基准测试,以确定每一项需要多长时间,以便您可以准确确定瓶颈所在。

我刚刚想到的是 OpenCV 正在捕获的相机的帧速率是多少?

于 2013-10-05T23:42:51.210 回答