【问题标题】:Stopwatch.GetTimestamp() alternative that is safe on multiple processors在多个处理器上安全的 Stopwatch.GetTimestamp() 替代方案
【发布时间】:2014-07-24 21:34:10
【问题描述】:

我需要一个像 Stopwatch.GetTimestamp() 这样的时钟

  1. 获取值时开销很小
  2. 至少精确到 1 毫秒(不减少 os 宽计时器间隔)
  3. 不必与一天中的实际时间挂钩(例如 DateTime.Now 是)
  4. 单调增加,但不一定严格(在同一毫秒内以 1 毫秒的精度多次调用它会产生相同的值)
  5. 保持上述所有内容在多个内核和处理器上同时运行

Stopwatch 好像是fail to provide the last of these properties

在多处理器计算机上,哪个处理器无关紧要 线程继续运行。但是,由于 BIOS 或硬件中的错误 抽象层(HAL),你可以得到不同的时序结果 不同的处理器。要指定线程的处理器亲和性,请使用 ProcessThread.ProcessorAffinity 方法。

为了实现真正的并发,出于显而易见的原因,我无法将所有线程固定到单个处理器。

我可以在 .net 中使用任何替代方法吗?还是上述警告已过时/仅限于一些稀有模型(我的生产环境不太可能容纳)?

编辑:

这是我主要关心的问题:我不介意不同处理器上的值相差一(例如毫秒)左右,但无论从哪个处理器检索它们,它们都需要始终或多或少相同。

【问题讨论】:

  • 如果是由于 BIOS 或 HAL 中的错误,我怀疑你会找到一个可以做得更好的软件。
  • Environment.TickCount64 够吗?不过,不确定它有 1 毫秒的分辨率。
  • @usr 你打算为我实现它 - 或者它只是从 the docs 中丢失?
  • @EugeneBeresovksy 呵呵,我很确定我在框架的最新版本中看到了 64 位版本的 TickCount。还是只是一个功能请求?!
  • 好的,所以有一个可以使用的本机函数 GetTickCount64。您可能必须将其精度设置为 1 毫秒。请参阅blogs.msdn.com/b/sloh/archive/2005/04/05/405724.aspx 了解如何使用 32 位版本。

标签: .net multiprocessing clock multicore


【解决方案1】:

MS 实际上有一篇关于 Stopwatch 底层计数器的深入文章。 Acquiring high-resolution time stamps

相关摘录:


一般来说,性能计数器结果在多核和多处理器系统中的所有处理器上都是一致的,即使是在不同线程或进程上测量时也是如此。以下是此规则的一些例外情况:

  • 在某些处理器上运行的 Windows Vista 之前的操作系统可能会违反这种一致性,原因之一是:
    • 硬件处理器有一个非不变的 TSC,而 BIOS 没有正确指示这种情况。
    • 使用的 TSC 同步算法不适用于具有大量处理器的系统。
  • 当您比较从不同线程获取的性能计数器结果时,请考虑相差 ± 1 个刻度的值具有不明确的顺序。如果时间戳取自同一线程,则此 ± 1 滴答不确定性不适用。在此上下文中,tick 一词是指等于 1 ÷(从 QueryPerformanceFrequency 获得的性能计数器的频率)的时间段。

【讨论】:

    【解决方案2】:

    The way it is even on buggy systems 实际上已经足够好了(对我来说):

    • GetTimestamp() - stampTakenEarlierOnADifferentProcessor 的结果可能会变成负数 - 对某些应用程序来说是个问题,但对我的用例来说不是
    • 我们说的是微秒 - 顶级
    • 不同的处理器不会随时间漂移:很好

    【讨论】:

      【解决方案3】:

      由于您只需要间隔测量的秒表,但您无法从运行在不同处理器上的不同线程访问同一实例(如果我理解正确,如果我错了,请纠正我),您可以创建一个新实例对于您的每个线程:

      ThreadLocal<Stopwatch> watch = new ThreadLocal<Stopwatch>(() => new Stopwatch());
      

      每个实例都应正确计算从其启动开始的时间间隔。

      作为替代方案,您可以获取DateTime.Now 属性并根据需要发送文本。它与.GetTimeStamp() 具有相同的语义(对我而言)。

      【讨论】:

      • 线程与处理器内核不对应。它们可以四处移动,导致秒表跳跃。但我相信无论如何,秒表跳跃在最近的 Windows 版本中都已修复。
      • @usr 它并没有解决我在多个处理器上的 *differnt 值”问题。
      猜你喜欢
      • 1970-01-01
      • 2012-05-29
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 2023-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多