为什么 CUDA 内核会因 CPU 代码而变慢?

问题描述 投票:0回答:1

我使用 CUDA 编写了一个屏蔽模板匹配算法。正如我所测试的,该算法的功能是正确的。然而,当我尝试使用以下代码将算法的 CUDA 实现与 OpenCV 实现进行比较时,出现了一些奇怪的情况。

for (int i = 0; i < 200; i++){
    // ---------------------------------------- GPU --------------------------------------------
    double t1 = (double)cv::getTickCount();
    gpu_img.upload(img);
    matcher->match(gpu_img, gpu_result);    // gpu
    gpu_result.download(result);
    t1 = ((double)cv::getTickCount() - t1) / cv::getTickFrequency();
    std::cout << t1 * 1000 << std::endl;

    double max_val_gpu;
    double min_val_gpu;
    cv::Point max_loc_gpu;
    cv::minMaxLoc(result, &min_val_gpu, &max_val_gpu, 0, &max_loc_gpu);
    std::cout << "min_val_gpu: " << min_val_gpu << "  max_val_gpu: " << max_val_gpu << std::endl;
    std::cout << "max_loc_gpu: " << max_loc_gpu.x << " " << max_loc_gpu.y << std::endl;
    // -------------------------------------------------------------------------------------------

    // ---------------------------------------- CPU -----------------------------------------------
    double t4 = (double)cv::getTickCount();
    cv::matchTemplate(img, temp, result, 5, mask);  // cpu
    t4 = ((double)cv::getTickCount() - t4) / cv::getTickFrequency();
    std::cout << "cpu version: " << t4 * 1000 << " ms" << std::endl;

    double min_val_cpu;
    double max_val_cpu;
    cv::Point max_loc_cpu;
    cv::minMaxLoc(result, &min_val_cpu, &max_val_cpu, 0, &max_loc_cpu);
    std::cout << "min_val_cpu: " << min_val_cpu << " max_val_cpu: " << max_val_cpu << std::endl;
    std::cout << "max_loc_cpu: " << max_loc_cpu.x << " " << max_loc_cpu.y << std::endl;
    // ---------------------------------------------------------------------------------------------
}

经过多次迭代后,CUDA函数的时间消耗突然增加(从4ms到20ms)。

我测试了其他 CUDA 函数,包括简单的向量相加和 OpenCV CUDA API。我发现所有这些功能都可能被 CPU 代码减慢。

如果我在每次迭代中运行CPU函数两次,则CUDA内核的时间消耗在第55次迭代左右突然增加(也从4ms增加到20ms)。即使 CPU 代码被单个语句 waitKey(100) 替换,CUDA 内核仍然会变慢。

代码运行在Win10、cuda 11.1;由 vs2015 & nvcc 11.1 编译。 GPU是RTX 3060。

使用“nsys profile”分析代码的性能。

CPU代码:

没有CPU代码:

似乎所有 CUDA API 和内核都变慢了。

c++ opencv cuda
1个回答
0
投票

当 CUDA 内核缺乏要处理的数据时,NVIDIA GPU 似乎会降低其时钟频率。这个问题可以通过设置 Nvidia 控制面板并使用

nvidia-smi -lgc
修复时钟频率来解决。

© www.soinside.com 2019 - 2024. All rights reserved.