旧问题的更新答案:
在 C++11 中,您可以通过以下方式轻松获得最高分辨率的计时器:
#include <iostream>
#include <chrono>
#include "chrono_io"
int main()
{
typedef std::chrono::high_resolution_clock Clock;
auto t1 = Clock::now();
auto t2 = Clock::now();
std::cout << t2-t1 << '\n';
}
示例输出:
74 nanoseconds
“chrono_io”是缓解这些新类型的 I/O 问题的扩展,可免费使用here。
在 boost 中还有一个<chrono> 的实现(可能仍在主干上,不确定它是否已发布)。
更新
这是对 Ben 在下面的评论的回应,即后续调用 std::chrono::high_resolution_clock 在 VS11 中需要几毫秒。以下是<chrono> 兼容的解决方法。但是它只适用于 Intel 硬件,您需要使用内联汇编(执行此操作的语法因编译器而异),并且您必须将机器的时钟速度硬连线到时钟中:
#include <chrono>
struct clock
{
typedef unsigned long long rep;
typedef std::ratio<1, 2800000000> period; // My machine is 2.8 GHz
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<clock> time_point;
static const bool is_steady = true;
static time_point now() noexcept
{
unsigned lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return time_point(duration(static_cast<rep>(hi) << 32 | lo));
}
private:
static
unsigned
get_clock_speed()
{
int mib[] = {CTL_HW, HW_CPU_FREQ};
const std::size_t namelen = sizeof(mib)/sizeof(mib[0]);
unsigned freq;
size_t freq_len = sizeof(freq);
if (sysctl(mib, namelen, &freq, &freq_len, nullptr, 0) != 0)
return 0;
return freq;
}
static
bool
check_invariants()
{
static_assert(1 == period::num, "period must be 1/freq");
assert(get_clock_speed() == period::den);
static_assert(std::is_same<rep, duration::rep>::value,
"rep and duration::rep must be the same type");
static_assert(std::is_same<period, duration::period>::value,
"period and duration::period must be the same type");
static_assert(std::is_same<duration, time_point::duration>::value,
"duration and time_point::duration must be the same type");
return true;
}
static const bool invariants;
};
const bool clock::invariants = clock::check_invariants();
所以它不是便携式的。但是,如果您想在自己的英特尔硬件上试验高分辨率时钟,没有比这更好的了。尽管预先警告,今天的时钟速度可以动态变化(它们并不是真正的编译时间常数)。使用多处理器机器,您甚至可以从不同的处理器获取时间戳。但是,在我的硬件上进行的实验仍然运行良好。如果您被毫秒分辨率困扰,这可能是一种解决方法。
根据您的 cpu 时钟速度(如您报告的那样),此时钟具有持续时间。 IE。对我来说,这个时钟每 1/2,800,000,000 秒滴答一次。如果您愿意,您可以将其转换为纳秒(例如):
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
auto t0 = clock::now();
auto t1 = clock::now();
nanoseconds ns = duration_cast<nanoseconds>(t1-t0);
转换将截断 CPU 周期的一部分以形成纳秒。其他舍入模式也是可能的,但这是另一个主题。
对我来说,这将返回低至 18 个时钟滴答的持续时间,截断为 6 纳秒。
我在上面的时钟中添加了一些“不变检查”,其中最重要的是检查clock::period 是否适用于机器。同样,这不是可移植的代码,但如果你使用这个时钟,你已经承诺了。此处显示的私有 get_clock_speed() 函数获取 OS X 上的最大 cpu 频率,这应该与 clock::period 的常数分母相同。
当您将此代码移植到新机器上而忘记将clock::period 更新为新机器的速度时,添加它可以为您节省一点调试时间。所有检查都在编译时或程序启动时完成。所以至少不会影响clock::now()的性能。