提升:以秒/毫/微米/纳米为单位计算函数的运行时间

Boost:Take seconds/milli/micro/nano of how long a function runs

本文关键字:计算 为单位 函数 运行时间 以秒 微米 提升      更新时间:2023-10-16

我基本上有一个学校项目,测试不同的排序算法所需的时间,并记录它们用n个数字进行排序所花费的时间。所以我决定使用c++的Boost库来记录时间。我现在不知道该怎么做,我在谷歌上搜索过,发现人们用不同的方式。例如

auto start = boost::chrono::high_resolution_clock::now();
auto end = boost::chrono::high_resolution_clock::now();
auto time = (end-start).count();

boost::chrono::system_clock::now();

boost::chrono::steady_clock::now() 

甚至使用类似的东西

boost::timer::cpu_timer and boost::timer::auto_cpu_time

boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time( );

所以我想确定现在该怎么做这就是我的

typedef boost::chrono::duration<double, boost::nano> boost_nano;
auto start_t = boost::chrono::high_resolution_clock::now();
// call function
auto end_t = boost::chrono::high_resolution_clock::now();
boost_nano time = (end_t - start_t);
cout << t.count();

那么我走对了吗?

您可能想要高分辨率计时器。

您可以使用boost::chronostd::chrono

Boost Chrono对IO内置有一定的支持,因此它可以更容易地以人性化的方式报告时间。

我通常使用类似的包装:

template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
    using namespace boost::chrono;
    struct _ {
        high_resolution_clock::time_point s;
        Caption const& task;
        ~_() { std::cout << " -- (" << task << " completed in " << duration_cast<milliseconds>(high_resolution_clock::now() - s) << ")n"; }
    } timing { high_resolution_clock::now(), task };
    return f();
}

报告所用时间(以毫秒为单位)。

这里好的部分是,你可以时间建设和类似:

std::vector<int> large = timed("generate data", [] {
           return generate_uniform_random_data(); });

但是,通用代码块:

timed("do_step2", [] {
    // step two is foo and bar:
    foo();
    bar();
});

如果例如foo()抛出,它也会起作用。

演示

在Coliru上直播

int main() {
    return timed("demo task", [] {
        sleep(1);
        return 42; 
    });
}

打印

 -- (demo task completed in 1000 milliseconds)
42

我通常使用时间(0)来控制循环的持续时间。时间(0)只是一个时间测量,由于它本身的持续时间很短,它对其他发生的事情的影响最小(你甚至可以运行一个无所事事的循环来捕捉从任何其他循环测量工作中减去多少)。

因此,在一个运行3秒(或10秒)的循环中,该循环可以调用你试图测量的东西多少次?

以下是我的旧代码如何测量"getpid()"持续时间的示例

uint32_t spinPidTillTime0SecChange(volatile int& pid)
{
   uint32_t spinCount = 1; // getpid() invocation count
   // no measurement, just spinning
   ::time_t tStart = ::time(nullptr);
   ::time_t   tEnd = tStart;
   while (0 == (tEnd - tStart)) // (tStart == tEnd)
   {
      pid = ::getpid();
      tEnd = ::time(nullptr);
      spinCount += 1;
   }
   return(spinCount);
}

调用此项3(或10)次,将返回值相加。为了方便起见,放弃第一个测量值(因为它可能是第二个测量值的一部分)。

是的,我确信有一个c++11版本可以访问时间(0)访问的内容。

使用std::chrono::steady_clockstd::chrono::high_resolution_clock(如果它是稳定的,请参见下文)而不是std::chrono::system_clock来测量C++11中的运行时间(或使用其升压等效值)。原因是(引用system_clock的文档):

在大多数系统上,系统时间可以随时调整

而steady_clock是单调的,更适合于测量区间:

类std::chrono::steady_clock表示单调时钟。时间这个时钟的点不能随着物理时间的前进而减少。这款时钟与挂钟时间无关,最适合测量间隔。

这里有一个例子:

auto start = std::chrono::steady_clock::now();
// do something
auto finish = std::chrono::steady_clock::now();
double elapsed_seconds = std::chrono::duration_cast<
  std::chrono::duration<double> >(finish - start).count();

一个实用的小提示:如果您正在测量运行时间并想报告秒数,std::chrono::duration_cast<std::chrono::seconds>很少是您所需要的,因为它会给您整个秒数。要获得double的时间(以秒为单位),请使用上面的示例。

正如Gregor McGregor所建议的,您可以使用high_resolution_clock,它有时可能提供更高的分辨率(尽管它可以是steady_clock的别名),但请注意,它也可能是system_clock的别名,因此您可能需要检查is_steady