c纳秒级计时器_使用C+提供以纳米秒为单位的时间的计时器功能

本文介绍了如何在C++中使用RDTSC指令创建一个纳秒级计时器,并与C++11的std::chrono::high_resolution_clock和std::chrono::system_clock进行性能对比。示例代码展示了如何测量循环的开销,并将时钟周期转换为实际时间单位。
摘要由CSDN通过智能技术生成

这个新的答案使用C+11的。设施。虽然还有其他的答案可以说明如何使用,它们都没有显示如何使用带着RDTSC其他几个答案中提到的设施。所以我想我应该展示如何使用RDTSC带着..此外,我将演示如何在时钟上临时编写测试代码,以便您可以在RDTSC和你的系统内置的时钟设施(这很可能是基于clock(), clock_gettime()和/或QueryPerformanceCounter.

注意,RDTSC指令是x86特定的。QueryPerformanceCounter只适用于Windows。和clock_gettime()仅限POSIX。下面我介绍两个新的时钟:std::chrono::high_resolution_clock和std::chrono::system_clock,如果您可以假设C+11,则现在是跨平台的。

首先,下面是如何从Intel中创建一个与C+11兼容的时钟。rdtsc装配指令。我就叫它x::clock:#include namespace x{struct clock{

typedef unsigned long long                 rep;

typedef std::ratio<1, 2'800'000'000>       period; // My machine is 2.8 GHz

typedef std::chrono::duration duration;

typedef std::chrono::time_point     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(hi) <

}

};

}  // x

这个时钟所做的就是计算CPU周期,并将其存储在一个无符号64位整数中。您可能需要调整编译器的汇编语言语法。或者您的编译器可能提供一个您可以使用的内部特性(例如:now() {return __rdtsc();}).

要构建一个时钟,您必须给它表示(存储类型)。您还必须提供时钟周期,这必须是一个编译时间常数,即使您的机器可能改变不同的电源模式下的时钟速度。根据这些基本原理,您可以很容易地定义您的时钟的“本地”时间持续时间和时间点。

如果你想要做的只是输出时钟滴答的数量,那么你给出的时钟周期是多少并不重要。只有当您想将时钟滴答的数量转换为一些实时单位(例如纳秒)时,这个常数才会起作用。在这种情况下,你能提供的时钟速度越精确,转换到纳秒(毫秒,随便什么)的精度就越高。

下面是示例代码,演示如何使用x::clock..实际上,我已经对时钟上的代码进行了模板化,因为我想向您展示如何用完全相同的语法使用许多不同的时钟。这个特殊的测试显示了在循环下运行所需时间时的循环开销是什么:#include template voidtest_empty_loop(){

// Define real time units

typedef std::chrono::duration picoseconds;

// or:

// typedef std::chrono::nanoseconds nanoseconds;

// Define double-based unit of clock tick

typedef std::chrono::duration Cycle;

using std::chrono::duration_cast;

const int N = 100000000;

// Do it

auto t0 = clock::now();

for (int j = 0; j 

asm volatile("");

auto t1 = clock::now();

// Get the clock ticks per iteration

auto ticks_per_iter = Cycle(t1-t0)/N;

std::cout <

// Convert to real time units

std::cout <(ticks_per_iter).count()

<

这段代码所做的第一件事就是创建一个“实时”单元来显示结果。我选择了皮秒,但是你可以选择任何你喜欢的单位,无论是积分还是基于浮点。举个例子,有一个预先制作的std::chrono::nanoseconds我可以用的单位。

作为另一个例子,我希望以浮点数的形式打印出每次迭代的平均时钟周期数,因此我创建了另一个基于Double的持续时间,它具有与时钟的刻度相同的单位(称为Cycle在代码中)。

循环是通过调用clock::now()两边都有。如果要命名此函数返回的类型,则如下所示:typename clock::time_point t0 = clock::now();

(如x::clock例如,也适用于系统提供的时钟)。

要获得以浮点时钟为单位的持续时间,只需减去两个时间点,而要获得每一个迭代值,则将持续时间除以迭代次数。

属性可以在任何时间内获取计数。count()成员函数这将返回内部表示。最后我用std::chrono::duration_cast若要转换持续时间,请执行以下操作Cycle持续时间picoseconds打印出来。

使用此代码很简单:int main(){

std::cout <

test_empty_loop<:clock>();

std::cout <

test_empty_loop<:chrono::high_resolution_clock>();

std::cout <

test_empty_loop<:chrono::system_clock>();}

以上我是用我们自制的测试来练习的。x::clock,并将这些结果与使用两个系统提供的时钟的结果进行比较:std::chrono::high_resolution_clock和std::chrono::system_clock..对我来说这是打印出来的:Using rdtsc:

1.72632 clock ticks per iteration

616ps per iteration

Using std::chrono::high_resolution_clock:

0.620105 clock ticks per iteration

620ps per iteration

Using std::chrono::system_clock:

0.00062457 clock ticks per iteration

624ps per iteration

这表明每个时钟都有一个不同的刻度周期,因为每个时钟的每一次迭代的滴答数都有很大的不同。然而,当转换为一个已知的时间单位(例如,皮秒),我得到了大约相同的结果,每个时钟(您的里程可能有所不同)。

请注意,我的代码完全没有“神奇的转换常量”。实际上,整个示例中只有两个神奇的数字:我的机器的时钟速度来定义

x::clock.

要测试的迭代次数。如果更改这个数目会使结果有很大差异,那么您可能应该提高迭代次数,或者在测试时清空计算机上的竞争进程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值