C++高精度定时器

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // KTimer.h
  3. //
  4. //      Windows Graphics Programming Win32 GDI and DirectDraw®
  5. //      Feng Yuan 
  6. //      Publisher: Prentice Hall PTR 
  7. //      First Edition December 01, 2000
  8. //
  9. //  高精度纳秒计时器, 最后修改:
  10. //      2008-12  by cheungmine@gmail.com
  11. ///////////////////////////////////////////////////////////////////////////////
  12. /* Usage:
  13.     int main()
  14.     {
  15.         KTimer  kt;
  16.         unsigned int cpu_speed = kt.CPUSpeedMHz();
  17.         kt.Start();
  18.         Sleep(1234);
  19.         unsigned int elapsed_cyc = (unsigned int) kt.Stop();
  20.         printf("CPU Speed: %.2f Ghz. Elapsed %ld CPU Cycles ( %ld Nanosecond)/n", 
  21.             cpu_speed/1000.f, 
  22.             elapsed_cyc, 
  23.             KTimer::CyclesToNanos(elapsed_cyc, cpu_speed));
  24.     }
  25. */
  26. #pragma once
  27. #ifndef STRICT
  28. #  define STRICT
  29. #endif
  30. #ifndef WIN32_LEAN_AND_MEAN
  31. #  define WIN32_LEAN_AND_MEAN
  32. #endif
  33. #include <windows.h>
  34. inline unsigned __int64 GetCycleCount(void)
  35. {
  36.     _asm    _emit 0x0F
  37.     _asm    _emit 0x31
  38. }
  39. class KTimer
  40. {
  41.     unsigned __int64  m_startcycle;
  42. public:
  43.     unsigned __int64  m_overhead;   // Clock Cycles
  44.     KTimer(void)
  45.     {
  46.         m_overhead = 0;
  47.         Start();
  48.         m_overhead = Stop();
  49.     }
  50.     // 启动CPU时钟
  51.     void Start(void)
  52.     {
  53.         m_startcycle = GetCycleCount();
  54.     }
  55.     // 停止CPU时钟, 返回自上一次启动的时钟周期数
  56.     unsigned __int64 Stop(void)
  57.     {
  58.         return GetCycleCount()-m_startcycle-m_overhead;
  59.     }
  60.     // 把以CPU周期数转为纳秒
  61.     unsigned __int64 static CyclesToNanos(unsigned __int64 time_cycles, unsigned int speed_mhz)
  62.     {
  63.         return time_cycles*1000 / speed_mhz;
  64.     }
  65.     
  66.     // 把以CPU周期数转为毫秒
  67.     unsigned __int64 static CyclesToMillis(unsigned __int64 time_cycles, unsigned int speed_mhz)
  68.     {
  69.         return time_cycles / speed_mhz / 1000;
  70.     }
  71.     // 1GHz = 1000MHz
  72.     unsigned int CPUSpeedMHz()
  73.     {
  74.         Start();
  75.         Sleep(1000);
  76.         unsigned __int64 cputime = Stop();
  77.         
  78.         return (unsigned int)(cputime/1000000);
  79.     }   
  80. };

 

 

 

转自:http://blog.youkuaiyun.com/cheungmine/archive/2008/12/11/3496676.aspx

<think>好的,用户想知道如何用C++高精度定时器来计算一个函数上一次执行和下一次执行的时间差。我需要先理清楚这个问题的关键点。首先,用户可能希望精确测量函数执行的时间间隔,可能用于性能分析或者任务调度。高精度定时器通常指的是使用C++11及以上的<chrono>库中的高分辨率时钟,比如std::chrono::high_resolution_clock。 接下来,我需要考虑如何记录上一次执行的时间。可能的思路是在函数内部或者外部保存一个静态变量或者全局变量,用来存储上一次调用的时间戳。每次函数执行时,获取当前时间,然后计算与上一次时间的差,再更新这个时间戳为当前时间,用于下一次计算。 然后,关于时间差的获取,用户可能希望得到的是两次调用之间的间隔,也就是上一次结束到下一次开始的时间,或者上一次开始到下一次开始的时间?需要明确。假设用户想要的是相邻两次调用开始时刻的时间差,那么每次调用时记录当前时间,然后计算与上一次记录的差值。 另外,需要考虑多线程环境下的问题,如果函数可能在多个线程中被调用,是否需要加锁?但用户的问题中没有提到多线程,可能暂时不需要考虑,先处理单线程的情况。 具体实现步骤可能包括: 1. 在函数内部使用静态变量保存上一次调用的时间点。 2. 每次函数被调用时,获取当前时间点。 3. 计算当前时间与上一次时间的差值。 4. 更新上一次时间点为当前时间。 5. 将差值返回或者记录下来。 需要检查时间点的类型是否正确,使用std::chrono::time_point和duration的相关操作。例如,使用high_resolution_clock的now()方法获取当前时间,然后使用duration_cast转换为合适的单位,比如毫秒或微秒。 可能的代码示例结构: 函数内部有一个static变量last_time,初始化为当前时间。每次调用时,获取now(),计算差,更新last_time,并输出或返回差值。 另外,用户可能关心如何确保高精度,需要注意high_resolution_clock的实际精度可能因系统而异,但通常足够精确。如果需要更高精度,可能需要平台特定的API,比如Windows的QueryPerformanceCounter,但这样会牺牲跨平台性。在C++标准库中,使用<chrono>是最佳实践。 可能的问题点:第一次调用时,last_time是初始化的时间,此时时间差可能没有意义。可能需要处理第一次调用时的特殊情况,比如在第一次调用时不计算时间差,或者初始化为函数第一次调用的时间。 例如,在第一次调用时,将last_time设置为当前时间,然后第二次调用时才计算差值。或者,在函数外部管理时间记录,比如使用一个类来封装状态,保存上一次的时间。 用户可能希望得到的是一个可重用的方法,所以可能需要提供一个封装好的类或者函数模板,方便在不同函数中使用。 总结步骤: 1. 包含必要的头文件,如<chrono>和<iostream>。 2. 在需要计时的函数中,使用静态变量记录上一次调用的时间点。 3. 每次调用时获取当前时间,计算与上一次的时间差。 4. 更新时间点。 5. 输出或处理时间差。 需要确保代码示例的正确性,比如使用正确的std::chrono语法,正确处理时间点的差值计算,以及单位的转换。 可能的代码示例: #include <iostream> #include <chrono> void myFunction() { using namespace std::chrono; static time_point<high_resolution_clock> last_time = high_resolution_clock::now(); auto now = high_resolution_clock::now(); auto diff = duration_cast<milliseconds>(now - last_time).count(); std::cout << "时间差: " << diff << " 毫秒" << std::endl; last_time = now; } int main() { myFunction(); // 第一次调用,不计算差 // 模拟一些延迟 std::this_thread::sleep_for(std::chrono::seconds(1)); myFunction(); // 第二次调用,计算与第一次的时间差 return 0; } 这里需要注意的是,第一次调用时,last_time被初始化为当前时间,而第一次执行后的输出可能没有意义,或者输出的是0(如果初始化和now()几乎同时)。但实际中,第一次调用后的diff可能接近0,而第二次调用时才会有实际的间隔。 另外,用户可能需要的是上一次执行结束到下一次执行开始的时间差,还是两次开始时间之间的差?如果是前者,需要在函数执行结束后记录时间,但这样就需要在函数结束时更新时间点。例如: void myFunction() { using namespace std::chrono; static time_point<high_resolution_clock> last_end_time; auto start_time = high_resolution_clock::now(); // 函数执行的操作... auto end_time = high_resolution_clock::now(); if (last_end_time.time_since_epoch().count() != 0) { auto diff = duration_cast<milliseconds>(start_time - last_end_time).count(); std::cout << "间隔时间: " << diff << " 毫秒" << std::endl; } last_end_time = end_time; } 这样,间隔时间就是上一次结束到下一次开始的时间。这可能更符合某些场景的需求,比如周期性任务调度。 需要根据用户的具体需求来调整记录的时机。用户的问题描述是“上一次执行的时间和下一次执行的时间差”,可能指的是两次开始时间之间的间隔,或者结束到开始的时间。需要明确这一点。 此外,用户可能需要将时间差用于其他用途,而不仅仅是输出,所以可能需要返回这个值,或者存储起来。 总结,回答时需要分步骤说明如何记录时间点,计算差值,并给出示例代码,解释关键部分,并提醒可能的注意事项,比如第一次调用的处理、精度问题、跨平台性等。</think>以下是使用C++高精度定时器计算函数相邻两次执行时间差的逐步实现方法: 1. **引入头文件** ```cpp #include <chrono> #include <iostream> ``` 2. **定义时间记录结构** ```cpp class FunctionTimer { private: static std::chrono::high_resolution_clock::time_point lastTime; public: static long long measureInterval() { auto now = std::chrono::high_resolution_clock::now(); // 首次调用时初始化时间点 if (lastTime.time_since_epoch().count() == 0) { lastTime = now; return 0; } // 计算时间差(单位:微秒) auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - lastTime).count(); // 更新最后时间点 lastTime = now; return interval; } }; // 静态成员初始化 std::chrono::high_resolution_clock::time_point FunctionTimer::lastTime; ``` 3. **在目标函数中使用** ```cpp void yourFunction() { // 函数逻辑前插入计时 long long interval = FunctionTimer::measureInterval(); if (interval > 0) { std::cout << "距离上次执行间隔: " << interval << " 微秒\n" << "约合 " << interval/1000.0 << " 毫秒\n"; } // 你的实际函数代码... } ``` 4. **调用示例** ```cpp int main() { for(int i = 0; i < 5; ++i) { yourFunction(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } ``` **关键点解析**: 1. 使用`std::chrono::high_resolution_clock`获取高精度时间戳 2. 通过`duration_cast`转换时间单位为微秒(可根据需求改为纳秒/毫秒) 3. 静态变量`lastTime`跨调用保持状态 4. 首次调用自动初始化,后续调用计算有效间隔 **注意事项**: - 精度依赖硬件,Windows通常为~100纳秒,Linux通常为~1纳秒 - 适合单线程场景,多线程需改用线程局部存储(`thread_local`) - 测量间隔包含函数执行时间+后续代码耗时 - 使用`microseconds`可避免浮点运算,需要更高精度可改用`nanoseconds` **扩展应用**: ```cpp // 测量执行时长(函数自身耗时) template<typename Func> void measureDuration(Func&& f) { auto start = std::chrono::high_resolution_clock::now(); f(); auto end = std::chrono::high_resolution_clock::now(); std::cout << "函数执行耗时: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << " 微秒\n"; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值