如何以微秒精度计算操作时间

Posted

技术标签:

【中文标题】如何以微秒精度计算操作时间【英文标题】:How to calculate a operation's time in micro second precision 【发布时间】:2010-05-13 13:03:56 【问题描述】:

我想在 Windows 平台上以微秒精度计算函数的性能。

现在 Windows 本身具有毫秒粒度,那么我该如何实现呢。

我尝试了以下示例,但没有得到正确的结果。

LARGE_INTEGER ticksPerSecond = 0;
LARGE_INTEGER tick_1 = 0;
LARGE_INTEGER tick_2 = 0;
double uSec = 1000000;

// Get the frequency
QueryPerformanceFrequency(&ticksPerSecond);

//Calculate per uSec freq
double uFreq = ticksPerSecond.QuadPart/uSec;

// Get counter b4 start of op
QueryPerformanceCounter(&tick_1);

// The ope itself
Sleep(10);

// Get counter after opfinished
QueryPerformanceCounter(&tick_2);

// And now the op time in uSec
double diff = (tick_2.QuadPart/uFreq) - (tick_1.QuadPart/uFreq);

【问题讨论】:

你得到什么结果?请注意,Sleep 不能保证在指定的时间内完全休眠;使用例如Sleep(1000) 睡一秒钟,这样你就可以自己检查它是否在做或多或少正确的事情。 默默数数自己真的很快。 【参考方案1】:

在循环中运行该操作一百万次左右,然后将结果除以该数字。这样,您将获得那么多执行的平均执行时间。由于多任务和诸如此类的原因,对一个非常快速的操作进行一次(甚至一百次)执行计时是非常不可靠的。

【讨论】:

注意:如果操作足够快,循环本身可能会占用您所关心的部分时间。请记住这一点。 缓存会生效,如果你循环它会加速操作 循环 1M 次与它将运行的秒数相比算不了什么。如果你想测量纳秒,那就另当别论了。哦,只需使用秒表;-)【参考方案2】: 编译它 查看汇编输出 计算函数中每条指令的数量 在目标处理器上应用每条指令的周期 以循环计数结束 乘以您运行的时钟速度 应用任意比例因子来解决缓存未命中和分支错误预测,哈哈

(这个答案我会被否决)

【讨论】:

不反对,我只是注意到最后一行(缓存未命中和分支错误预测)几乎会破坏您迄今为止获得的 cpu 周期的非常仔细的计数:p +1 好笑。但是,如果你是认真的,这是一个糟糕的建议。作为讽刺,这是一个很好的例子,说明了为什么选择马蒂的答案。 投反对票?不是我。事实上,我曾经这样做过。但是,现在缓存它并没有真正起作用。所以我推荐 run-it-a-million-times 方法。 根据您的架构,这是一种完全有效且准确的方法。并非所有处理器都有缓存、分支预测或多任务处理。虽然,我注意到每条指令的周期数可能是可变的,即使取决于参数......【参考方案3】:

不,您可能得到了准确的结果,QueryPerformanceCounter() 适用于短时间间隔。问题是您对 Sleep() 的准确性的期望。它的分辨率为 1 毫秒,但精度要差得多。在大多数 Windows 机器上不超过 15.625 毫秒。

要获得接近 1 毫秒的时间,您必须先致电 timeBeginPeriod(1)。这可能会改善匹配,忽略 Windows 作为多任务操作系统会带来的抖动。

【讨论】:

或将 select 与伪造的 fd 一起使用以获得更准确的“睡眠”【参考方案4】:

如果您这样做是为了离线分析,一个非常简单的方法是运行该函数 1000 次,测量到最接近的毫秒并除以 1000。

【讨论】:

【参考方案5】:

要获得比 1 毫秒更精细的分辨率,您必须查阅操作系统文档。可能有 API 可以获取微秒分辨率的计时器分辨率。如果是这样,请多次运行您的应用程序并取平均值。

【讨论】:

有。它被称为QueryPerformanceCounter。正如 OP 所说的那样。【参考方案6】:

我喜欢 Matti Virkkunen 的回答。检查时间,大量调用函数,完成时检查时间,除以调用函数的次数。他确实提到您可能由于操作系统中断而关闭。您可能会改变拨打电话的次数并看到差异。你能提高进程的优先级吗?你能在一个单一的操作系统时间片内得到所有的调用吗?

由于您不知道操作系统何时将您换出,您可以将所有这些都放在一个更大的循环中以进行大量次整个测量,并保存最小的数字,因为那是具有最少的操作系统中断。这仍然可能大于函数执行的实际时间,因为它可能仍然包含一些操作系统中断。

【讨论】:

【参考方案7】:

桑吉特,

看起来(在我看来)您的做法完全正确。 QueryPerformanceCounter 是一种高精度测量短时间的完美方法。如果您没有看到预期的结果,很可能是因为睡眠时间没有达到您预期的时间!但是,它很可能被正确测量。

我想回到您最初的问题,即如何以微秒精度测量 windows 上的时间。如您所知,高性能计数器(即 QueryPerformanceCounter)以 QueryPerformanceFrequency 报告的频率“滴答”。这意味着您可以测量时间的精度等于:

1/频率秒

在我的机器上,QueryPerformanceFrequency 报告 2337910(计数/秒)。这意味着我的计算机的 QPC 可以以 4.277e-7 秒或 0.427732 微秒的精度进行测量。 这意味着我可以测量的最小时间是 0.427732 微秒。当然,这会为您提供最初要求的精度 :) 您的机器频率应该相似,但您始终可以进行数学计算并检查它。

【讨论】:

【参考方案8】:

或者您可以使用 gettimeofday(),它为您提供一个 timeval 结构,它是一个时间戳(低至 µs)

【讨论】:

以上是关于如何以微秒精度计算操作时间的主要内容,如果未能解决你的问题,请参考以下文章

如何在windows开发环境下得到精确到微秒的系统时间?

以微秒精度获取时间点

以微秒精度压缩 unix 时间戳

有没有办法在 Windows 上测量时间到微秒精度? [复制]

如何增加精度计算的时间?

Protopie进阶教程--动态时钟(中)