【C++ Boost库】CPU定时器
@TOC
前言
在现代软件开发中,性能优化和代码调优是至关重要的。了解代码执行时间以及系统性能是开发人员必不可少的技能之一。为了实现精准的代码执行时间测量以及跨平台的性能分析,C++ Boost 库提供了 CPU 定时器组件。这些组件旨在提供高精度的计时功能,并通过操作系统特定的API实现了跨平台的一致性。让我们深入了解这些 CPU 定时器组件的特性和用途。
一、auto_cpu_timer类
1.1 介绍
auto_cpu_timer 是 Boost.Timer 库中的一个类,它的作用是在程序执行过程中自动测量代码块的执行时间,并在代码块执行完成后自动输出计时信息。使用 auto_cpu_timer,你无需手动开始计时和结束计时,它会在对象创建和销毁的时候自动记录开始和结束时间,并输出所经过的时间信息,包括挂钟时间、用户CPU处理时间和系统CPU处理时间。
这种自动化的计时器能够帮助开发人员更方便地对程序性能进行评估和优化,而无需在代码中添加额外的计时逻辑。auto_cpu_timer 类的设计使得代码块的计时操作更加简洁和易于理解,提高了开发效率。
1.2 使用
我们只需要在何时的地方构造一个auto_cpu_timer
他在构造函数时会打印出具体的信息
#include <boost/timer/timer.hpp>
#include <cmath>
int main()
{
boost::timer::auto_cpu_timer t;
for (long i = 0; i < 100000000; ++i)
std::sqrt(123.456L); // burn some time
return 0;
}
这些信息是 auto_cpu_timer 自动输出的计时结果,其中包含了不同类型的时间信息以及它们的含义如下:
0.920127s wall
: 表示从代码块开始执行到结束所经过的挂钟时间,即实际的墙钟时间。这包括了程序执行期间所经过的所有时间,包括用户CPU时间和系统CPU时间,以及任何其他可能导致程序停滞的时间(如I/O等待时间)。
0.843750s user
: 表示用户CPU处理时间,即程序在用户态执行所消耗的CPU时间。这包括了执行代码本身所消耗的时间,不包括系统调用等等操作。
0.000000s system
: 表示系统CPU处理时间,即程序在内核态执行所消耗的CPU时间。这包括了执行系统调用等操作所消耗的时间。
0.843750s CPU (91.7%)
: 表示总的CPU处理时间,即用户CPU处理时间和系统CPU处理时间的总和。在这个例子中,用户CPU处理时间和系统CPU处理时间相同,因此总的CPU时间也是 0.843750s。括号中的百分比表示总CPU时间占挂钟时间的比例,即CPU利用率。在这个例子中,CPU利用率为 91.7%。
除了这个默认的构造函数之外,还有其他的一些构造函数:
t(std::cerr, 2)
: 表示创建一个计时器对象,并指定输出流为 std::cerr,同时设置输出精度为 2。这里的输出格式与默认构造函数相同,只是精度不同。
t(1)
: 表示创建一个计时器对象,并指定输出精度为 1。同样,输出格式与默认构造函数相同,只是精度不同。
t(3, "%w seconds\n")
: 表示创建一个计时器对象,并指定输出格式为 “%w seconds\n”,其中 “%w” 会被替换为实际的墙钟时间。这种格式化输出仅包含了挂钟时间。
t("%t sec CPU, %w sec real")
: 表示使用自定义输出格式来创建计时器对象,其中 “%t” 会被替换为实际的CPU时间,"%w" 会被替换为实际的墙钟时间。这里的输出格式指定了 CPU 时间和墙钟时间。
1.3 定时器的精准程度
下面是Boost官网介绍的:
Mac OS X Lion: Intel 处理器(约2007年产)的计时器分辨率大约为 2100 纳秒至 2200 纳秒之间,有一定范围内的变化。
Ubuntu Linux 11.4: Intel 处理器(约2005年产)的计时器分辨率约为 516 纳秒,变化很小,通常少于 5 纳秒。
Windows 7:
使用 Intel Core i7 860 @ 2.9 GHz 处理器的计时器分辨率约为 366 纳秒,有一定变化,通常是 366 纳秒的倍数。
使用 Intel Mobile T7200 @ 2.0 GHz 处理器的计时器分辨率约为 2050 纳秒,变化较大。当处理器速度降低时,分辨率会下降,可能是由于已知的芯片组错误导致的。
使用 Intel Atom N2800 @ 1.0 GHz 处理器的计时器分辨率约为 1437 纳秒,有一定变化。
在现代电脑,这个误差非常小了,但是这里并没有介绍,我们也不好去测量,这里我们参考一下就ok了
二、cpu_timer类
2.1 cpu_timer类代码概况
class cpu_timer
{
public:
// constructor
cpu_timer() noexcept;
// compiler generated; shown for exposition only
~cpu_timer() noexcept = default;
cpu_timer(const cpu_timer&) noexcept = default;
cpu_timer& operator=(const cpu_timer&) noexcept = default;
// observers
bool is_stopped() const noexcept;
cpu_times elapsed() const noexcept;
std::string format(int places, const std::string& format) const;
std::string format(int places = default_places) const;
// actions
void start() noexcept;
void stop() noexcept;
void resume() noexcept;
};
2.2 格式化成string
我们可以使用下面这两个函数把他格式化成字符串
std::string format(int places, const std::string& format) const;
std::string format(int places = default_places) const;
参数 places 用于指定要格式化的数字的小数位数。在这种情况下,format 函数似乎是用于格式化数字的函数。通过指定 places 参数,您可以控制结果中小数点后的位数。
例如,如果您将 places 设置为 2,则格式化的数字将保留两位小数。如果将 places 设置为 0,则结果将是一个整数。
他的格式化字符有下面这些:
%w times.wall
%u times.user
%s times.system
%t times.user + times.system
%p times.wall times.user + times.system
第二个则是使用默认的,不需要填参数
2.3 开启、停止与重置定时器
我们可以通过下面三个函数来实现开启、停止与重置定时器功能
void start() noexcept;
void stop() noexcept;
void resume() noexcept;
2.4 cpu_timer与auto_cpu_timer的区别
cpu_timer: 这是一个手动管理的计时器类。您需要手动创建一个 cpu_timer 对象,然后使用 start() 和 stop() 方法来控制计时的开始和结束。这种方式需要您明确地控制计时器的生命周期和使用。
auto_cpu_timer: 这是一个自动管理的计时器类。您只需在代码中创建一个 auto_cpu_timer 对象,并传递一个标识时间段的字符串作为参数,它将在创建时开始计时,在离开作用域时自动结束计时,并在退出作用域时自动输出计时结果。这种方式更加方便,无需手动管理计时器的启动和停止。
总结
CPU 定时器是 C++ Boost 库中的关键组件之一,它们提供了跨平台的高精度计时功能。通过利用操作系统特定的API,这些定时器能够在不同的操作系统上实现一致的行为,并提供了开发人员所需的性能分析工具。无论是用于测量代码执行时间还是进行系统性能分析,CPU 定时器都是不可或缺的工具。因此,熟练掌握这些定时器组件将有助于开发人员优化其代码并提升应用程序的性能表现。
- 点赞
- 收藏
- 关注作者
评论(0)