搜索
查看: 5929|回复: 5

高精度计时器HighAccuracyTimer

[复制链接]
发表于 2016-8-22 21:59:34 | 显示全部楼层 |阅读模式
本帖最后由 20011010wo 于 2016-8-22 22:25 编辑

QQ截图20160822220002.png

点击停止后将会计算从上一次点击开始所用的时间,如果没有点击开始……则时间近似为窗口显示的时间 + 校准所用时间(500ms)

32位静态编译 Timer.exe (454.5 KB, 下载次数: 762)

原理:利用某些设备主板上的晶振,开始后将会连续5次校准多核CPU采用QueryPerformanceCounter的问题 QueryPerformanceCounter的运行情况是依赖于CPU的,当CPU是多核时,在某一线程内调用QueryPerformanceCounter,线程会切换于不同的核心之间,这时候QueryPerformanceCounter返回值是不确定的。
多核CPU使用QueryPerformanceCounter 当需要在某一进程中获取时间,需要将该线程绑定在某一固定的核心上,这样获取的高精度计时器才是可靠的。通过SetThreadAffinityMask可以实现这一目的

如:SetThreadAffinityMask(GetCurrentThread(),0x00000001);//绑定当前线程到CPU 1号核心

附赠高精度时间类(C++)
  1. class HighAccuracyTimer:private Noncopyable
  2. {
  3. public:
  4.         HighAccuracyTimer()
  5.         {
  6.                 succeed = QueryPerformanceFrequency(&freq);
  7.                 oldMask = SetThreadAffinityMask(GetCurrentThread(), 0x00000001);
  8.                 QueryPerformanceCounter(&begin);       
  9.         }

  10.         ~HighAccuracyTimer()
  11.         {
  12.                 SetThreadAffinityMask(GetCurrentThread(), oldMask);
  13.         }

  14.         void Start()
  15.         {
  16.                 QueryPerformanceCounter(&begin);
  17.         }
  18.         void End()
  19.         {
  20.                 QueryPerformanceCounter(&end);
  21.         }
  22.         __int64 Correct()
  23.         {
  24.                 QueryPerformanceCounter(&correct_begin);
  25.                 QueryPerformanceCounter(&correct_end);
  26.                 correct = correct_end.QuadPart - correct_begin.QuadPart;
  27.                 return correct;
  28.         }
  29.         unsigned __int64 Count()
  30.         {
  31.                 return (__int64)(end.QuadPart - begin.QuadPart);
  32.         }

  33.         unsigned __int64 Frequency()
  34.         {
  35.                 return freq.QuadPart;
  36.         }
  37.         long double Seconds()
  38.         {
  39.                 return (end.QuadPart - begin.QuadPart - correct) / ((long double)freq.QuadPart);
  40.         }
  41.         long double MillSeconds()
  42.         {
  43.                 return (end.QuadPart - begin.QuadPart - correct) / ((long double)freq.QuadPart) * 1000.0L;
  44.         }
  45.         long double MicroSeconds()
  46.         {
  47.                 return (end.QuadPart - begin.QuadPart - correct) / ((long double)freq.QuadPart) * 1000000.0L;
  48.         }
  49.         BOOL succeed;

  50. private:

  51.         LARGE_INTEGER freq;
  52.         LARGE_INTEGER begin, end, correct_begin, correct_end;
  53.         ULONG_PTR oldMask;
  54.         __int64 correct = 0LL;
  55. };
复制代码


回复

使用道具 举报

发表于 2016-8-24 14:55:59 | 显示全部楼层
校准后的0 1 是什么意思
回复

使用道具 举报

 楼主| 发表于 2016-8-24 14:59:02 来自手机 | 显示全部楼层
nkc3g4 发表于 2016-8-24 14:55
校准后的0 1 是什么意思

执行开始计时然后立刻执行停止计时所用时间/晶振精度.理论上为0
回复

使用道具 举报

发表于 2016-8-24 14:59:55 | 显示全部楼层
20011010wo 发表于 2016-8-24 14:59
执行开始计时然后立刻执行停止计时所用时间/晶振精度.理论上为0

那为什么会有1
回复

使用道具 举报

 楼主| 发表于 2016-8-24 15:00:33 来自手机 | 显示全部楼层
nkc3g4 发表于 2016-8-24 14:59
那为什么会有1

所以要校准
回复

使用道具 举报

 楼主| 发表于 2016-8-24 15:01:28 来自手机 | 显示全部楼层
nkc3g4 发表于 2016-8-24 14:59
那为什么会有1

以后的计数都要减去1
回复

使用道具 举报

联系我们(Contact)|手机版|萝卜头IT论坛 ( 苏ICP备15050961号-1 )

GMT+8, 2024-11-21 22:35 , Processed in 0.094264 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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