使用 chrono 库计时

Laffey 2022-08-31 17:30:47

前言

C++ 11 为我们提供了 chrono 库,这是一个好用且精准的计时库。

cstdlib 中也并不是没有计时函数,只不过 clock() 只能计算当前进程时间,time() 精度又十分低下。某些平台专用库文件如 windows.hunistd.h 中的函数又不具备很好的跨平台性。因此,在 Boost 系列库中出现了一个优秀的计时库,就是我们今天要讲的 chrono

这个库如果要详解花费的篇幅会特别长,因此这里只介绍利用部分功能实现毫秒至纳秒级计时。

如果想要详细了解可以去看这篇文章

chrono 中的所有函数等都定义在命名空间 std::chrono 中。因此依照竞赛类代码习惯应在头文件后加上以下代码。

using namespace std::chrono;

概念

首先我们需要知道几个概念。

  • duration

duration 是一个模板类,指的是一个时间段。它可以有不同的单位和计时方式,不过在此不必深究,我们只需要知道一些已经封装好的类就行了。

seconds // 以秒为单位
milliseconds // 以毫秒为单位
microseconds // 以微秒为单位
nanoseconds // 以纳秒为单位
  • duration_cast

duration_cast 是一个函数模板,因为 duration 可用的类型非常多,这个函数模板就用来进行不同类型间的转换。

  • time_point

time_point 也是一个模板类,指的是某个时间点。两个 time_point 相减可得到一个 duration

  • std::chrono::steady_clock

std::chrono::steady_clock 是一个结构体,封装了 chrono 中某些计时用的函数和类型方便调用。

应用

最典型的应用当然是给算法计时。

#include <cstdlib>
#include <chrono>
#include <iostream>
using namespace std;
using namespace chrono;

int main()
{
    cout << "Begin counting..." << endl;
    steady_clock::time_point BeginTime = steady_clock::now();

    // do something
    system("./t");

    steady_clock::time_point EndTime = steady_clock::now();

    // calculate the time
    microseconds time_span = duration_cast<microseconds>(EndTime - BeginTime);

    cout << (double) time_span.count() / 1000 << "ms.\n";
}

为了保证精准,我们可以使用微秒计时,但在最后转换为毫秒。

为了方便调用,也可以将这些函数再次封装,如封装成一个结构体。

struct Clock {
    typedef steady_clock::time_point Clock_Type;

    Clock_Type BeginTime, EndTime;
    bool is_counting = false;
    microseconds Clocks;

    void begin()
    {
        if (!is_counting) {
            BeginTime = steady_clock::now();
            is_counting = true;
        }
    }

    void end()
    {
        if (is_counting) {
            EndTime = steady_clock::now();
            is_counting = false;
            Clocks = duration_cast<microseconds> (EndTime - BeginTime);
        }
    }

    double clock()
    {
        return (double) Clocks.count() / 1000;
    }
};

这样在调用的时候,只需要定义好一个变量,然后按顺序调用 begin()end(),最后调用 clock() 就能得到精准的时间。

int main()
{
    Clock count;
    
    count.begin();

    // do something
    
    count.end();

    cout << count.clock() << "ms.\n" << endl;

    return 0;
}