找回密码
 加入
搜索
楼主: unique009

[系统综合] 长时间计时不要用TimerDiff,应该用_Date_Time_GetTickCount

 火.. [复制链接]
发表于 2012-11-27 14:00:27 | 显示全部楼层
回复 30# annybaby
论坛搜搜pdh就行了,我就不做重复实验了
发表于 2012-11-27 14:25:08 | 显示全部楼层
回复 31# netegg

P大那个性能统计??
究竟是我表述不清楚呢,还是我没表述清楚呢??

两位大师都不肯给出代码,我只能确信我遗憾地错过了一次学习的机会~~~
发表于 2012-11-27 14:34:55 | 显示全部楼层
回复 32# annybaby
性能计数器(pdh)那个我也没搞太明白
 楼主| 发表于 2012-11-27 14:52:52 | 显示全部楼层
本帖最后由 unique009 于 2012-11-27 15:03 编辑

回复 3# netegg


    这两天在官网狠查了一下,终于找到一个靠谱的说法了
http://www.autoitscript.com/foru ... t-int-versus-float/

In the v3.1.0 download of the AutoIt source code, the function TimerInit is in src/script_misc.cpp. It uses QueryPerformanceCounter on a __int64 and converts that to double. There are no documented changes in the History page for TimerInit/TimerDiff after 2004.


Edited by Manadar, 30 September 2011 - 11:53 AM.



看来的确是用的QueryPerformanceCounter来计数的,这样就明白了,我的笔记本CPU有自动降频节能的功能,在运行那个大运算量的程序之前,笔记本CPU负载小,处于节能模试,此时QueryPerformanceFrequency的值比最大值要小不少,当程序运行起来后,CPU自动升频运行,这就导致TimerDiff 的值比实际要小

看来还是要谨慎使用TimerDiff 啊,特别是现在CPU几乎都有自动降频节能功能
 楼主| 发表于 2012-11-27 15:00:52 | 显示全部楼层
本帖最后由 unique009 于 2012-11-27 15:24 编辑

这是源代码
script_misc.cpp: 

///////////////////////////////////////////////////////////////////////////////
// TimerInit()
// Returns a floating point value that is a baseline system time.
// Starts tracking a high performance counter allowing for accurate timers.
///////////////////////////////////////////////////////////////////////////////

AUT_RESULT AutoIt_Script::F_TimerInit(VectorVariant &vParams, Variant &vResult)
{
        __int64 now;

        if (!QueryPerformanceCounter((LARGE_INTEGER *)&now))
                return AUT_OK;

        vResult = (double)now;

        return AUT_OK;

} // TimerInit()

///////////////////////////////////////////////////////////////////////////////
// TimerDiff(Baseline)
// Takes the time difference between now and Baseline and returns the result.
///////////////////////////////////////////////////////////////////////////////

AUT_RESULT AutoIt_Script::F_TimerDiff(VectorVariant &vParams, Variant &vResult)
{
        __int64 freq, now;

        if (!QueryPerformanceFrequency((LARGE_INTEGER *)&freq))
                return AUT_OK;

        if (!QueryPerformanceCounter((LARGE_INTEGER *)&now))
                return AUT_OK;

        vResult = (((double)now - vParams[0].fValue()) / (double)freq) * 1000.0;

        return AUT_OK;

} // TimerDiff()
发表于 2012-11-27 19:57:05 | 显示全部楼层
回复 1# unique009

GetTickCount 精度是到毫秒級沒錯,但它是「最穩」的計時器。

QueryPerformanceCounter 可以用,但我不知道在 AU 會不會出包,原因是 MSDN 建議用 SetThreadAffinityMask 指定 thread 做計時。QueryPerformanceCount 在低階上之既念,是先取得 CPU freqence,( 所以可以得到 nano 精度 ),再看經過幾個 clock cycle ,相乘就得 到計數時間。

所以整體流程就變成了:
1. 先用 QueryPerformanceFrequency 取得 freq. 是多少 (假設是 2ns)
2. 再做 Beg ~ End 之計數,得到經過多少個 clock cycle (假設是 100 個)
3. 將上面那個數字相乘,得到 200 ns

盲點在於,CPU freq. 事實上是會變動的,所以我的作法是,「頭尾各取一次,做平均」當 freq. 最大的 問題還是在於 SetThreadAffinityMask 。

------------

另樓主有提到

>> 刚想到还有一个asm指令rdtsc也是高精度的,但这个在双核机上应该也是不准的吧

說對了。

rdtsc 使用最早出現於「Windows圖形編程」一書,而且這種計時之精度還與硬體相依,早期由於 CPU 時脈關係,精度只到 micro-sec (現在就不知道了),另也不是所有硬體都支援。這種計時器,在 multi-processor 切換線程時,會被中止打斷,使得計數不準確,還有其他缺點,故現在已是被排斥的計時方式。

------------

普遍性而言,大多以 GetTickCount 做計時,需要高精度計時器時用 QueryPerformanceCounter ,其他的大概不怎考慮。

另外計時器取得時間記時,本身所花費之時間並不短。

一點意見,供參考。

评分

参与人数 1金钱 +20 收起 理由
annybaby + 20 感谢分享~~~

查看全部评分

发表于 2012-11-27 21:14:48 | 显示全部楼层
本帖最后由 annybaby 于 2012-11-27 21:47 编辑

回复 36# edisonx


    指出了很关键的一点:执行取计数器值的过程也是需要时间的,除非可以非常精确的测定这个时间,就可以对结果进行一个修正,又或者是证明这个时间的确足够小,不会影响结果的精度…


PS:上面的论述可能有一点小问题

*******************
所以整體流程就變成了:
1. 先用 QueryPerformanceFrequency 取得 freq. 是多少 (假設是 2ns)
2. 再做 Beg ~ End 之計數,得到經過多少個 clock cycle (假設是 100 個)
3. 將上面那個數字相乘,得到 200 ns
***************************************
1中注意,它是个频率,返回的结果是Hz,比如我的老爷

AMD Athlon(tm) 64 X2 Dual
Core Processor 3600+
1.90 GHz, 960 MB 的内存

返回的有时是
1900070000,有时有小幅变化(自动调频了)
第二个当然是正确的,然后将得到的时钟周期数直接除以第一步的主频~~
发表于 2012-11-27 23:38:13 | 显示全部楼层
回复 37# annybaby


    QueryPerformanceFrequency 的確是傳回 Hz, 這裡可能我沒說清楚,得到後可換回 n secs 無誤 (就直接倒數而已),只是我傳回是倒數做相乘,而您是不做倒數做相除。

不過 Query~ 系列取用是較費時的無誤 (比起 GetTickCount 而言的話)
发表于 2012-11-28 18:46:39 | 显示全部楼层
很经典的讨论
发表于 2012-11-28 22:25:44 | 显示全部楼层
回复 5# unique009


    回个贴看看我啥时候注册的。好像也是08年。。。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-26 12:29 , Processed in 0.303768 second(s), 15 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表