OpenCL版OpenCV模板匹配慢于CPU及CUDA的问题排查
OpenCL模板匹配性能远低于CPU和CUDA的问题
我正在寻找最快的模板匹配方案,意外发现OpenCL实现的速度远慢于CPU和CUDA版本。原本我会选择CUDA,但因等待新AMD显卡,只能使用OpenCL。最新计时结果:
| 阶段 | 耗时(ms) |
|---|---|
| CPU | 293.00 |
| GPU(CUDA) | 268.00 |
| GPU(OpenCL) | 539.00 |
我疑惑是自身实现存在疏漏,还是当前使用的Nvidia Quadro K620对OpenCL优化不足?以下是相关代码:
cv::Mat img = cv::imread("path-to-source-img"); std::vector<cv::Mat> templates; std::vector<std::string> templatePaths = {"path/template1","path/template2"}; cv::Mat template_img = cv::imread("path/template1"); void loadTemplates() { for (const auto& path : templatePaths) { templates.push_back(cv::imread(path)); } } void cpu() { START_TIMER cv::Mat imgCopy = img.clone(); std::vector<std::future<cv::Point>> futures; auto matchTemplate = [](const cv::Mat& img, const cv::Mat& templ) { cv::Mat result; cv::matchTemplate(img, templ, result, cv::TM_CCOEFF_NORMED); cv::Point maxLocPoint; cv::minMaxLoc(result, 0, 0, 0, &maxLocPoint); return maxLocPoint; }; // Create a future for each template for (const auto& templ : templates) { futures.push_back(std::async(std::launch::async, matchTemplate, img, templ)); } // Collect results and draw rectangles for (size_t i = 0; i < templates.size(); ++i) { cv::Point maxLocPoint = futures[i].get(); cv::Scalar color(0, 255 * (i + 1) / templates.size(), 255 * (templates.size() - i) / templates.size()); cv::rectangle(imgCopy, cv::Rect(maxLocPoint, cv::Point(maxLocPoint.x + templates[i].cols, maxLocPoint.y + templates[i].rows)), color, 2); } END_TIMER(cpuMatching) cv::imshow("Result CPU Optimized", imgCopy); cv::waitKey(0); } void gpu() { START_TIMER cv::cuda::GpuMat srcGpu(img); std::vector<cv::cuda::GpuMat> templatesGpu; std::vector<cv::cuda::GpuMat> resultsGpu(templates.size()); std::vector<cv::cuda::Stream> streams(templates.size()); cv::Ptr<cv::cuda::TemplateMatching> matcher = cv::cuda::createTemplateMatching(img.type(), cv::TM_CCOEFF_NORMED); // Upload templates to GPU and launch matching operations for (size_t i = 0; i < templates.size(); ++i) { templatesGpu.emplace_back(templates[i]); matcher->match(srcGpu, templatesGpu.back(), resultsGpu[i], streams[i]); } // Process results std::vector<cv::Point> maxLocPoints(templates.size()); for (size_t i = 0; i < templates.size(); ++i) { cv::Mat result; resultsGpu[i].download(result, streams[i]); streams[i].waitForCompletion(); cv::minMaxLoc(result, nullptr, nullptr, nullptr, &maxLocPoints[i]); } END_TIMER(gpuMatching) cv::Mat imgCopy = img.clone(); for (size_t i = 0; i < templates.size(); ++i) { cv::Scalar color(0, 255 * (i + 1) / templates.size(), 255 * (templates.size() - i) / templates.size()); cv::rectangle(imgCopy, cv::Rect(maxLocPoints[i], templates[i].size()), color, 2); } cv::imshow("Result GPU Stream Optimized", imgCopy); cv::waitKey(0); } // Not yet implemented to work with several templates like cpu and cuda void gpuOpenCL() { START_TIMER // Enable OpenCL cv::ocl::setUseOpenCL(true); if (!cv::ocl::haveOpenCL()) { std::cout << "OpenCL is not available..." << std::endl; return; } // Get OpenCL device information cv::ocl::Context context; if (!context.create(cv::ocl::Device::TYPE_GPU)) { std::cout << "Failed creating the context..." << std::endl; return; } // Print the detected OpenCL devices std::cout << context.ndevices() << " GPU devices are detected." << std::endl; for (int i = 0; i < context.ndevices(); i++) { cv::ocl::Device device = context.device(i); std::cout << "Device " << i << ": " << device.name() << std::endl; } cv::ocl::Device(context.device(0)); cv::UMat result; result.create(img.rows - template_img.rows + 1, img.cols - template_img.cols + 1, CV_32FC1); cv::matchTemplate(img, template_img, result, cv::TM_CCOEFF_NORMED); END_TIMER(gpuOpenCLMatching) double minVal, maxVal; cv::Point minLoc, maxLoc; cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); cv::rectangle(img, maxLoc, cv::Point(maxLoc.x + template_img.cols, maxLoc.y + template_img.rows), cv::Scalar(0, 255, 0), 2); cv::imshow("OpencCL GPU Result", img); cv::waitKey(0); } int main() { loadTemplates(); cpu(); gpu(); gpuOpenCL(); displayTimingStats(); return 0; }
内容的提问来源于stack exchange,提问作者Jackolix
相关产品推荐
相关产品推荐

