【问题标题】:How to call two functions one after another with minimum delay?如何以最小的延迟依次调用两个函数?
【发布时间】:2014-06-22 12:58:10
【问题描述】:

我实现了一个返回时间的快速函数(使用 rdtsc),我们称之为fast_time()。我有一个使用系统调用的原始函数作为参考,我们称之为system_time()。我的程序使用fast_time(),但在一个单独的线程中,我不断地运行一个while循环来检查从我的函数返回的时间与原始函数之间的差异是否大于预定义的阈值。类似的东西

while (true)
{
    if (abs((fast_time() - system_time()).microseconds()) > MICROSECONDS_THRESHOLD)
    {
        report error
    }
}

通常我看不到错误,但有时我确实得到了错误,我想更好地理解这个问题。我的第一个怀疑是对system_time() 的调用不会在fast_time() 返回后立即发生。如何强制程序尽可能“原子地”执行fast_time() - system_time()?

【问题讨论】:

  • 您好,在我回答之前,您的代码是否锁定在单个 CPU 上?如果你不知道那是什么意思也没关系,只要告诉我从哪里开始解释:-)
  • 除非您在实时内核上运行(Linux 不是),否则您无法保证您的软件运行的频率,也无法知道线程是否会运行轮流在同一个核心上运行,或者在不同的核心上运行。通常这完全取决于操作系统。
  • @LtWorf 实际上,如果您选择使用它,Linux 确实有一个实时调度程序,并且在他的多核 CPU 上的特殊情况下,他可以将他的线程锁定到一个 CORE 并获得他正在寻找的结果。
  • 我用sched_setaffinity 将线程锁定到单个核心,是的,我知道我没有得到调度的保证(我不使用实时内核),我的问题是,我能做些什么来解决这个问题?
  • 你想通过测试达到什么目的?它是对您信任的system_time 实现的fast_time 实现的测试吗?

标签: c++ linux time system-calls rdtsc


【解决方案1】:

rdtsc 本质上是不可靠的实时测量方法,原因有以下几点:

1) 每个硬件线程将返回不同的值,因此如果您的线程未锁定到一个硬件线程,您将获得不同的值。所以时间可能会出乎意料地来回跳跃,具体取决于操作系统如何调度线程

更重要的是:

2) CPU 节流会导致 CPU 的频率发生意外变化。因为 rdtsc 测量执行的周期而不是时间,所以您无法通过将周期数除以 CPU 频率来可靠地获得经过的时间(在两次 rdtsc 调用之间,频率可能会随机变化)

此外,在您的特定测试用例中,操作系统可能会安排线程在 fast_time() 和 system_time() 调用之间产生,从而导致测量时间之间的差异,即使 fast_time() 会返回正确的值。因此,要回答您的问题,我认为没有任何方法可以防止这种情况发生。

【讨论】:

  • 你是对的!如果问题不在于调度,那么我的下一个猜测是 CPU 频率正在改变(超频或欠频)。无论如何,我认为我不会轻易放弃或 rdtsc,因为事实证明它比系统调用快 4 倍。因此,正如您所提到的,我怀疑操作系统会在我不希望它安排我的线程时准确地产生我的线程。所以我仍在寻找一些方法来防止这种情况发生
  • 也许您可以将 system_time() 夹在两个 fast_time() 调用之间,如果 fast_time() 调用之间的时间超过某个阈值,则拒绝该案例?我也很好奇,计时调用中的 4 倍差异会产生什么影响?
  • 回答您的第二个问题,该应用程序属于算法交易领域 - 每一微秒都很重要。
  • 我不知道您使用的是什么平台,但我在 win32 上分析了 QueryPerformanceCounter() 与 __rdtsc(),并且对于 10 亿次调用,我分别获得了 10.63 秒和 8.11 秒的时间。所以至少在那种情况下不值得额外的麻烦来使用 rdtsc。
猜你喜欢
  • 2019-11-01
  • 2019-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
相关资源
最近更新 更多