在程序执行期间休眠,OpenCV函数cv::remap()的执行时间变长。

4

我正在使用OpenCV库进行一些图像处理,发现处理图像所需的时间取决于在图像处理之间休眠线程的时间量。 我测量了程序的几个部分的执行时间,并发现函数cv::remap()执行速度会比以前慢两倍,如果我使我的线程在图像处理之间休眠的时期超过一定时间。

下面是最小的代码片段,展示了奇怪的行为。 我测量执行cv::remap()函数所需的时间,然后将我的线程休眠一定的毫秒数 sleep_time

#include <opencv2/imgproc.hpp>
#include <thread>
#include <iostream>

int main(int argc, char **argv) {
  cv::Mat src = ... // Init
  cv::Mat dst = ... // Init

  cv::Mat1f map_x = ... // Init;
  cv::Mat1f map_y = ... // Init;

  for (int i = 0; i < 5; i++) {
    auto t1 = std::chrono::system_clock::now();
    cv::remap(src, dst, map_x, map_y, cv::INTER_NEAREST, cv::BORDER_CONSTANT, 0);
    auto t2 = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_time = t2 - t1;
    std::cout << "elapsed time = " << elapsed_time.count() * 1e3 << " ms" << std::endl;

    int sleep_time = 0;
    // int sleep_time = 20;
    // int sleep_time = 100;
    std::this_thread::sleep_for( std::chrono::milliseconds(sleep_time));
  }

   return 0;
}

如果将sleep_time设置为0,则处理大约需要5毫秒。以下是输出结果。
elapsed time = 5.94945 ms
elapsed time = 5.7458 ms
elapsed time = 5.69947 ms
elapsed time = 5.68581 ms
elapsed time = 5.7218 ms

但是如果我将sleep_time设为100,处理速度会变慢超过两倍。

elapsed time = 6.09076 ms
elapsed time = 13.2568 ms
elapsed time = 13.4524 ms
elapsed time = 13.3631 ms
elapsed time = 13.3581 ms

我尝试了许多不同的sleep_time值,似乎当sleep_time大约是elapsed_time的三倍时(sleep_time> 3 * elapsed_time),执行时间会加倍。如果我增加cv::remap()函数内部计算的复杂度(例如增加处理图像的大小),那么在执行开始加倍之前,sleep_time也可以设置为更高的值。

我正在嵌入式设备上运行我的程序,该设备配有ARM处理器iMX6和Linux操作系统,但我也能够在运行Ubuntu 16.04的桌面电脑上复现这个问题。我使用编译器arm-angstrom-linux-gnueabi-gcc (GCC) 7.3.0 和Opencv版本3.3.0。

有人有什么想法吗?


如果增加循环迭代次数,计算速度会更快吗? - Micka
不,它没有改变。时间保持不变。 - Matej Jeglič
1个回答

6

这可能是你的CPU频率调节机制在起作用。

Linux上默认的频率调节器通常是“ondemand”,这意味着当CPU负载较低时,时钟速度会降低,当负载增加时则会提高。由于这个过程需要一些时间,你的短暂计算爆发无法使时钟速度提高,因此你的进程实际上运行在比你实际拥有的更慢的CPU上。

我通过执行以下命令在我的机器上测试了这个理论:

sudo cpupower frequency-set -g performance

然而,这种效果立即消失了。要将 governor 设置回去,请执行

sudo cpupower frequency-set -g ondemand

谢谢你的回答。确实是频率调节器引起了问题。我已经被这个问题困扰了几天了。我很高兴它已经解决了。再次感谢! :) - Matej Jeglič

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接