OI笔记 - STL - 浅谈 chrono 库在计时上的应用

前置

C++ 标准:C++11

头文件:<chrono>

简介

namespace std::chrono 中提供了三(两)种可用的时钟:std::chrono::_V2::steady_clockstd::chrono::_V2::system_clockstd::chrono::_V2::high_resolution_clock

这之中,steady_clock 提供精度较高的稳定时钟,system_clock 提供精度更高但随系统时间变化的时钟。high_resolution_clock “表示实现提供的拥有最小计次周期的时钟;它可以是 system_clocksteady_clock 的别名,或第三个独立时钟。”(来源,有调整)

具体地,在 Intel(R) Core(TM) i5-9500T CPU @ 2.20GHz 的 CPU 环境下使用 Windows 10 Pro 21H2 操作系统的 g++ 11.2.0 编译出的 steady_clock 具有 100 ns 的精度,system_clock 具有 1 ns 的精度。[1]

本文主要讨论如何使用 steady_clock 实现计时。

[1] g++ -v 的输出:

1
2
3
4
5
6
7
8
Using built-in specs.
COLLECT_GCC=E:\qidirj\RedPanda-Cpp\MinGW64\bin\g++.exe
COLLECT_LTO_WRAPPER=E:/qidirj/RedPanda-Cpp/MinGW64/bin/../libexec/gcc/x86_64-w64-mingw32/11.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-11.2.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/d/a/mingw-builds/mingw-builds/buildroot/x86_64-1120-posix-seh-rt_v9-rev1/mingw64 --enable-host-shared --disable-multilib --enable-languages=c,c++,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --enable-libstdcxx-filesystem-ts=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static --with-mpc=/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static --with-isl=/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev1, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/d/a/mingw-builds/mingw-builds/buildroot/x86_64-1120-posix-seh-rt_v9-rev1/mingw64/opt/include -I/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-zlib-static/include -I/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/d/a/mingw-builds/mingw-builds/buildroot/x86_64-1120-posix-seh-rt_v9-rev1/mingw64/opt/include -I/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-zlib-static/include -I/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/d/a/mingw-builds/mingw-builds/buildroot/x86_64-1120-posix-seh-rt_v9-rev1/mingw64/opt/include -I/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-zlib-static/include -I/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/d/a/mingw-builds/mingw-builds/buildroot/x86_64-1120-posix-seh-rt_v9-rev1/mingw64/opt/lib -L/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-zlib-static/lib -L/d/a/mingw-builds/mingw-builds/buildroot/prerequisites/x86_64-w64-mingw32-static/lib ' LD_FOR_TARGET=/d/a/mingw-builds/mingw-builds/buildroot/x86_64-1120-posix-seh-rt_v9-rev1/mingw64/bin/ld.exe --with-boot-ldflags=' -Wl,--disable-dynamicbase -static-libstdc++ -static-libgcc'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.2.0 (x86_64-posix-seh-rev1, Built by MinGW-W64 project)

原型

std::chrono::steady_clock

1
2
3
4
5
6
7
8
9
10
11
12
struct steady_clock
{
typedef chrono::nanoseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef chrono::time_point<steady_clock, duration> time_point;

static constexpr bool is_steady = true;

static time_point
now() noexcept;
};

std::chrono::time_point_cast

1
2
3
4
5
6
7
8
   template<typename _ToDur, typename _Clock, typename _Dur>
constexpr typename enable_if<__is_duration<_ToDur>::value,
time_point<_Clock, _ToDur>>::type
time_point_cast(const time_point<_Clock, _Dur>& __t)
{
typedef time_point<_Clock, _ToDur> __time_point;
return __time_point(duration_cast<_ToDur>(__t.time_since_epoch()));
}

std::chrono::_V2::steady_clock::time_point::time_since_epoch()

1
2
3
constexpr duration
time_since_epoch() const
{ return __d; }

用法

获取当前相对时间

1
chrono::time_point_cast<chrono::nanoseconds>(chrono::steady_clock::now()).time_since_epoch()

chrono::steady_clock::now() 获取相对于一定时间点的当前时间,这个时间点可能是系统启动的时间、UNIX 时间起点等等。

接着,利用 chrono::time_point_cast<chrono::nanoseconds>() 将这个时间转换为纳秒形式,用 time_since_epoch 获取到相对时间。

求时间差

以上的表达式返回 std::chrono::_V2::steady_clock::duration 类型,其有 count() 成员函数,返回时间的整型形式,一般为 long long 类型。这之后,可以利用两个 durationcount 之差算出时间差,注意单位为纳秒。

实现计时

保存一个 std::chrono::_V2::steady_clock::duration start,在开始时将当前时间传入 start,则在任何时刻可以作差取到时间。

上一篇
下一篇