【发布时间】:2021-10-31 20:12:54
【问题描述】:
我正在使用 C++ 和 OpenCV 在 while 循环中处理视频中尺寸为 2208x1242 的图像。
为了加快速度,我想在我的 Nvidia Jetson Nano 的 GPU 上执行操作。
对于使用 cv::cuda::cvtColor 而不是 cv::cvtColor 从 BGR 到 HSV 的颜色转换,我实现了 5 倍的加速。
不幸的是,GPU 上的形态运算要慢得多:
int num_frame = 10;
int frame = 0;
cv::Mat img;
cv::cuda::GpuMat img_gpu;
cv::Mat open_kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(11, 11));
cv::Mat close_kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(21, 21));
while (frame < num_frame){
// load image to img
// ...
img_gpu.upload(img);
cv::Ptr<cv::cuda::Filter> morph_filter_open = cv::cuda::createMorphologyFilter(cv::MORPH_OPEN, img_gpu.type(), open_kernel);
cv::Ptr<cv::cuda::Filter> morph_filter_close = cv::cuda::createMorphologyFilter(cv::MORPH_CLOSE, img_gpu.type(), close_kernel);
morph_filter_open->apply(img_gpu, img_gpu);
morph_filter_close->apply(img_gpu, img_gpu);
frame++;
}
仅测量 apply() 调用,GPU 版本在 Jetson Nano 的 CPU 上比 cv::morphologyEx 慢约 20 倍(0.07s vs. 1.5s 对于单帧)。
nvprof 表明,大部分时间都花在了cudaDeviceSynchronize 上(这是为了整个程序比上面的代码示例做更多的事情,但长时间运行的操作可能与形态有关):
API calls: 71.05% 17.2756s 665 25.978ms 25.730us 1.44814s cudaDeviceSynchronize
8.36% 2.03194s 1826 1.1128ms 34.844us 847.66ms cudaLaunchKernel
5.16% 1.25490s 1 1.25490s 1.25490s 1.25490s cuCtxDestroy
4.80% 1.16684s 544 2.1449ms 17.865us 10.378ms cudaMallocPitch
1.89% 460.14ms 616 746.98us 20.469us 346.82ms cudaFree
1.65% 401.38ms 76 5.2813ms 44.533us 19.211ms cudaMemcpy2D
1.45% 352.97ms 51 6.9209ms 18.803us 242.14ms cudaMalloc
1.42% 345.25ms 1 345.25ms 345.25ms 345.25ms cudaFuncGetAttributes
1.23% 299.95ms 1 299.95ms 299.95ms 299.95ms cuCtxCreate
1.03% 251.43ms 20 12.572ms 162.61us 103.74ms cudaMallocManaged
0.92% 224.67ms 13 17.283ms 32.553us 65.173ms cudaMemcpy
0.56% 135.48ms 1 135.48ms 135.48ms 135.48ms cudaDeviceReset
...
希望有人能帮我找出问题所在!
【问题讨论】:
-
我打算发布同样的问题,因为我在评估结果中得到了类似的结果。我希望您能获得有关导致此问题的任何最新信息!
-
不幸的是,我没有。我使用其他类似的函数(cv::cuda::createGaussianFilter)测试了完全相同的代码,我发现它比 cv::GaussianBlur 快很多,所以我怀疑问题出在 cv:: 的实现中cuda::createMorphologyFilter 本身。