我想在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);
以百万次左右的循环运行该操作,并将结果除以该数字。 这样你就可以得到平均执行时间。 由于多任务和其他任务,执行一个(甚至一百)个执行非常快的操作是非常不可靠的。
(男人,我很想下来 – 投这个答案)
不,您可能会得到一个准确的结果,QueryPerformanceCounter()适用于定时短时间间隔。 什么是错误的是你对睡眠()的准确性的期望。 它有1毫秒的分辨率,其准确性更差。 在大多数Windows机器上,最好不要超过15.625毫秒。
为了将它接近1毫秒,你必须先调用timeBeginPeriod(1) 。 这可能会改善匹配,而忽略了Windows作为一个多任务操作系统的抖动。
如果你正在做这个离线分析,一个非常简单的方法是运行1000次函数,测量到最接近的毫秒,然后除以1000。
要获得比1毫秒更好的分辨率,您将不得不咨询您的操作系统文档。 可能有API以微秒的分辨率获得计时器分辨率。 如果是这样,多次运行你的应用程序,并取平均值。
我喜欢Matti Virkkunen的回答。 检查时间,多次调用函数,检查完成时间,除以调用函数的次数。 他提到你可能由于操作系统中断而关闭。 您可能会改变拨打电话的次数,并看到不同之处。 你能提高这个过程的优先级吗? 你可以在一个操作系统时间片内完成所有的调用吗?
既然你不知道什么时候操作系统可能会把你换掉,你可以把它放在一个更大的循环中来完成大量的测量,并且保存最少的操作数,因为这是操作系统最少的中断。 这仍然可能比函数执行的实际时间要长,因为它可能仍然包含一些操作系统中断。
Sanjeet,
它看起来(对我来说)就像你正在做的那样完全正确。 QueryPerformanceCounter是一个非常好的方式来测量短时间内的高精度。 如果你没有看到你预期的结果,那很可能是因为睡眠没有达到预期的时间! 但是,它可能被正确测量。
我想回到最初的问题,关于如何以微秒的精度来测量窗口上的时间。 如您所知,高性能计数器(即QueryPerformanceCounter)以“QueryPerformanceFrequency”报告的频率“打勾”。 这意味着你可以用精确度来衡量时间,等于:
1 /频率秒
在我的机器上, QueryPerformanceFrequency报告2337910(计数/秒)。 这意味着我的计算机的QPC可以精确测量4.277e-7秒或0.427732微秒。 这意味着我可以测量的最小时间是0.427732微秒。 这当然会给你原来要求的精度:)你的机器的频率应该是相似的,但你可以随时做数学和检查。
或者你可以使用gettimeofday(),它给你一个timeval结构,它是一个时间戳(低至μs)