【问题标题】:How does one write kernels for GpuMat? [duplicate]如何为 GpuMat 编写内核? [复制]
【发布时间】:2017-09-25 14:29:53
【问题描述】:

我正在尝试使用以下代码迭代 cv::cuda::GpuMat:

__global__ void kernel(uchar* src, int rows, int cols, size_t step)
{
    int rowInd = blockIdx.y * blockDim.y + threadIdx.y;
    int colInd = blockIdx.x * blockDim.x + threadIdx.x;

    if ((rowInd < rows) && (colInd < cols))
    {
        uchar * rowptr = src + (rowInd * step);
        rowptr[colInd] = 255;
    }

}

void invoke_kernel(cv::cuda::GpuMat _img)
{
    dim3 tpb(50, 50);
    dim3 bpg(((_img.cols + 49) / 50), ((_img.rows + 49)/ 50));
    kernel<<<bpg, tpb>>> (_img.data, _img.rows, _img.cols, _img.step);

}

int main()
{


    cv::cuda::GpuMat mat;
    mat.create(cv::Size(500, 500), CV_8UC1);
    std::cout << mat.rows << " " << mat.cols << std::endl;
    invoke_kernel(mat);

    cv::Mat img;
    mat.download(img);

    cv::namedWindow("test");
    cv::imshow("test", img);
    cv::waitKey(0);

    return 0;
}

如您所见,它只是应该在内核中将整个(最初是黑色的)图像设置为白色。

图像只是保持黑色,而不是第一列,即白色。感觉好像我在某处做了一些非常愚蠢的事情,但我就是想不通:/

我检查了内核是否以正确的尺寸运行(10x10 块,每个块 50x50 线程)。当我尝试使用 NVIDIA 调试器时,会出现另一个问题。经过一番谷歌搜索后,我发现 NVCC 编译器似乎在优化过程中删除了我的 rowInd 和 colInd 变量,因此调试器不显示它们的值。

感谢您的宝贵时间。

【问题讨论】:

  • 好吧,事实证明内核甚至没有启动,我知道为什么,但即使我在那里得到一个无限循环,也没有任何改变
  • 任何时候遇到 cuda 代码问题时,最好使用 proper cuda error checking 并使用 cuda-memcheck 运行代码。
  • @RobertCrovella 是的,这实际上是我想出来的,cudaGetLastError 返回了我 cudaErrorInvalidConfiguration,我搜索了一些,发现块大小太大

标签: c++ opencv cuda


【解决方案1】:

好吧,事实证明,问题在于块大小 50x50 = 2500 有点太大了。有某种限制,我还没有弄清楚,但是,正如 CUDA 文档中所述,16x16 很好。

所以,澄清一下:

dim3 tpb(16, 16);
dim3 bpg(((_img.cols + 15) / 16), ((_img.rows + 15)/ 16));

invoke_kernel 完成这项工作。

孩子们,请务必阅读文档。

【讨论】:

  • 限制是 CUDA 内核被限制为每个块 1024 个线程,该限制由块尺寸 x,y,z 的乘积组成。这在 CUDA 编程指南和 cuda 示例代码 deviceQuery 中都有记录,它是 CUDA 标签上数十个问题的来源。
猜你喜欢
  • 2018-05-03
  • 1970-01-01
  • 2013-11-12
  • 2014-08-28
  • 2015-11-02
  • 1970-01-01
  • 2012-09-27
  • 2010-10-26
  • 1970-01-01
相关资源
最近更新 更多