opencv-cuda开发(1):opencv-cuda对比CPU的加速测试

目录

测试环境

测试代码1

测试代码2

总结

首先问问神奇的GPT

 个人总结

优化思路


测试环境

显卡:1050TI,

CPU:I9-13900

CUDA版本11.4

opencv版本4.8.0

测试代码1

每次只进行一次运算,记录时间不包括读取图片和上传GPU的过程

    //cpu code
    cv::Mat verticalProjection;
    cv::Mat horizontalProjection;
    cv::Mat diffImage, diffImage2;
    cv::Mat testImage = imread("test.png", 0);
    cv::Mat backImage = imread("background.png", 0);
    cv::Mat backImage_diff = imread("background_diff.png", 0);

    auto startTime_1 = std::chrono::high_resolution_clock::now();

        cv::absdiff(backImage, testImage, diffImage);
        cv::absdiff(backImage_diff, diffImage, diffImage2);
        cv::reduce(diffImage2, verticalProjection, 0, REDUCE_SUM, CV_32S);
        cv::reduce(diffImage2, horizontalProjection, 1, REDUCE_SUM, CV_32S);

    auto endTime_1 = std::chrono::high_resolution_clock::now();
     Calculate the duration
    auto duration_1 = std::chrono::duration_cast<std::chrono::microseconds>(endTime_1 - startTime_1).count();
    std::cout << "CPU 处理耗时 平均1000次: " << duration_1 / 1000 << " 微秒." << std::endl;

 CUDA部分

    //cuda code

    cv::Mat gpu_verticalProjection;
    cv::Mat gpu_horizontalProjection;
    cv::Mat gpu_diffImage, gpu_diffImage2;
    cv::Mat gpu_testImage = imread("test.png", 0);
    cv::Mat gpu_backImage = imread("background.png", 0);
    cv::Mat gpu_backImage_diff = imread("background_diff.png", 0);
    //cuda code
    cv::cuda::GpuMat cuda_Image,cuda_backImage_1, cuda_backImage_2,cuda_diff_1, cuda_diff_2;
    cv::cuda::GpuMat cuda_horizontalProjection, cuda_verticalProjection;
    cuda_Image.upload(gpu_testImage);
    cuda_backImage_1.upload(gpu_backImage);
    cuda_backImage_2.upload(gpu_backImage_diff);
    auto startTime = std::chrono::high_resolution_clock::now();

        cv::cuda::absdiff(cuda_Image, cuda_backImage_1, cuda_diff_1);
        cv::cuda::absdiff(cuda_diff_1, cuda_backImage_2, cuda_diff_2);
        cv::cuda::reduce(cuda_diff_2, cuda_verticalProjection, 0, cv::REDUCE_SUM, CV_32S);
        cv::cuda::reduce(cuda_diff_2, cuda_verticalProjection, 1, cv::REDUCE_SUM, CV_32S);


    auto endTime = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
    std::cout << "GPU 处理耗时 平均1000次: " << duration/1000 << " 微秒." << std::endl;

 测试结果

可以发现GPU速度上严重慢于GPU

测试代码2

加入循环1000次,求平均时间

    //cpu code
    cv::Mat verticalProjection;
    cv::Mat horizontalProjection;
    cv::Mat diffImage, diffImage2;
    cv::Mat testImage = imread("test.png", 0);
    cv::Mat backImage = imread("background.png", 0);
    cv::Mat backImage_diff = imread("background_diff.png", 0);

    auto startTime_1 = std::chrono::high_resolution_clock::now();
    while ((num++) < 1000)
    {
        cv::absdiff(backImage, testImage, diffImage);
        cv::absdiff(backImage_diff, diffImage, diffImage2);
        cv::reduce(diffImage2, verticalProjection, 0, REDUCE_SUM, CV_32S);
        cv::reduce(diffImage2, horizontalProjection, 1, REDUCE_SUM, CV_32S);
    }
    auto endTime_1 = std::chrono::high_resolution_clock::now();
     Calculate the duration
    auto duration_1 = std::chrono::duration_cast<std::chrono::microseconds>(endTime_1 - startTime_1).count();
    std::cout << "CPU 处理耗时 平均1000次: " << duration_1 / 1000 << " 微秒." << std::endl;

cuda代码

    //cuda code
    cv::Mat gpu_verticalProjection;
    cv::Mat gpu_horizontalProjection;
    cv::Mat gpu_diffImage, gpu_diffImage2;
    cv::Mat gpu_testImage = imread("test.png", 0);
    cv::Mat gpu_backImage = imread("background.png", 0);
    cv::Mat gpu_backImage_diff = imread("background_diff.png", 0);
    //cuda code
    cv::cuda::GpuMat cuda_Image,cuda_backImage_1, cuda_backImage_2,cuda_diff_1, cuda_diff_2;
    cv::cuda::GpuMat cuda_horizontalProjection, cuda_verticalProjection;
    cuda_Image.upload(gpu_testImage);
    cuda_backImage_1.upload(gpu_backImage);
    cuda_backImage_2.upload(gpu_backImage_diff);
    auto startTime = std::chrono::high_resolution_clock::now();
    while ((num++)<1000)
    {


        cv::cuda::absdiff(cuda_Image, cuda_backImage_1, cuda_diff_1);
        cv::cuda::absdiff(cuda_diff_1, cuda_backImage_2, cuda_diff_2);
        cv::cuda::reduce(cuda_diff_2, cuda_verticalProjection, 0, cv::REDUCE_SUM, CV_32S);
        cv::cuda::reduce(cuda_diff_2, cuda_verticalProjection, 1, cv::REDUCE_SUM, CV_32S);




    }
    auto endTime = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
    std::cout << "GPU 处理耗时 平均1000次: " << duration/1000 << " 微秒." << std::endl;

测试结果

 

 

 可以发现GPU处理速度提升明显,已经能和CPU达到一个数量级了

可以看到,GPU并没有多大占用率

总结

首先问问神奇的GPT

问:

为什么会出现使用cv::cuda::absdiff的处理函数,运算速度还比不过CPU版本的cv::absdiff?

答:

使用cv::cuda::absdiff处理函数时,CUDA加速的性能优势并不是绝对的,它取决于很多因素。以下是一些可能导致CUDA版本运算速度较慢的原因:

  1. 数据传输开销:CUDA涉及将数据从主机(CPU)传输到GPU,以及从GPU传输回主机。如果处理的图像大小较小,数据传输的开销可能会导致CUDA版本的运算速度比CPU版本慢。
  2. 启动开销:在CUDA版本中,启动GPU核函数涉及GPU上下文的切换和其他开销,这可能在处理小图像时成为瓶颈。
  3. 硬件限制:如果GPU的计算性能相对较低,或者GPU内存不足以容纳大的图像,那么CUDA加速可能并不会带来明显的性能提升。
  4. 算法复杂性:有些算法在GPU上的并行处理效果不如CPU上的串行处理。CUDA适合处理那些可以被有效地并行化的算法。
  5. 代码优化:CUDA代码需要特定的优化技巧和策略,包括合理使用共享内存、避免线程间冲突等。如果CUDA代码没有经过充分优化,其性能可能不如预期。
  6. 并行度:CUDA加速通常在处理大规模图像或大规模数据集时效果更为明显。对于小规模问题,GPU并行处理的优势可能较小。

如果发现CUDA版本的运算速度比CPU版本慢,可以考虑以下优化措施:

  1. 增加输入图像的大小,以使得CUDA加速的优势更为明显。
  2. 确保在GPU上的数据传输和计算开销不会成为性能瓶颈,可以一次性传输多个图像进行并行处理。
  3. 优化CUDA核函数的实现,避免线程冲突,并利用共享内存等技术提高计算效率。
  4. 调整GPU的计算性能、内存等资源配置,以适合实际处理的任务。

最终,CUDA加速的性能取决于具体问题的特征和硬件环境,因此需要进行实际测试和优化,以找到最佳的实现方式。

 个人总结

尽管是像上面那么简单的4个语句,三个图片的上传,只要是整段代码的第一次调用gpu相关操作,默认执行CUDA的初始化。upload这个过程就会影响到后面的cv::cuda函数执行速度,在其它机器上不一定是我这个测试时间,应该跟具体的PC硬件有关,看看CPU能初始化cuda有多快。

往后的gpu的操作都不会那么慢,但一旦涉及upload、download(显存与内存的数据传递),时间成本都达到ms级别!GPU的并行处理的确很快,但数据传入GPU的开销实在太大,往往影响了代码的整体效率。

优化思路

目前看,需要将图片或者视频大批量传入GPU后进行批量运算才能最大幅度提高cuda处理效率,100帧或者1000帧处理一次性完成,单帧处理速度是不能看的。

需要学会并行处理的思路,这里可以参考一些FPGA上关于图像处理的设计:

图像数据串行进入后转成多个通道并行处理,并行处理完成后再转成串行回到CPU,每个并行通道中的运算过程中,还要考虑计算流水线化(这就要自己设计cuda核函数了)

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要配置OpenCV支持CUDA,你需要按照以下步骤进行操作: 1. 打开OpenCV的源码,并确保你已经勾选了BUILD_opencv_world、WITH_CUDAOPENCV_DNN_CUDA选项。这些选项将允许编译OpenCV支持CUDA和DNN模块。 2. 接下来,你需要配置CUDAOpenCV的环境。你可以参考《vs2017配置cudaopencv环境》这篇博客文章,其中提供了详细的配置步骤和注意事项。 3. 完成环境配置后,你可以在Python平台下测试OpenCV的DNN模块。你可以参考相关文档或教程,了解如何使用OpenCV的DNN模块进行目标检测、图像分类等任务。 总结起来,配置OpenCV支持CUDA需要勾选相应的选项,并按照指南配置CUDAOpenCV的环境。完成配置后,你可以在Python平台下使用OpenCV的DNN模块进行各种图像处理任务。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [01-深度学习-win10系统下配置OpenCV-DNN模块使用CUDA(支持nvidia 显卡加速)](https://blog.csdn.net/qq_41719643/article/details/107902350)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [vs2017+配置opencv+cuda环境](https://blog.csdn.net/m0_54844818/article/details/123246817)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值