繁体   English   中英

clock_nanosleep() 的实用抖动

[英]Practical jitter with clock_nanosleep()

我试图通过在循环中使用clock_nanosleep()并通过实验来确定我可以实现的实际抖动,我正在观察一些我不确定我理解的东西。

我正在使用另一个用户在此 SO 问题中发布的代码来对性能进行基准测试,目标是 250 毫秒的间隔。 我观察到,在我的系统上,睡眠 function 非常一致地延迟返回 10us,绝大多数时间只有大约 2us 的抖动(相当狭窄的统计分布)。

注意:我还没有收集数据来展示统计分布的 plot,但随意的定性描述应该就足够了。

我决定从目标唤醒时间中减去 10us 偏移来补偿它,这导致平均误差按预期接近于零,但是抖动急剧增加 - 我估计大多数唤醒早/晚 > 100us,而且很多分布更广。

为什么是这样?

我的理论是,通过 10us 校正,目标唤醒时间与底层硬件时钟的对齐不太好,但有助于确认。 如果这是真的,是否有一种方法可以将目标唤醒时间的相位与硬件时钟同步?

clock_nanosleep(2)的手册页说:“此外,在睡眠完成后,在 CPU 再次空闲以再次执行调用线程之前可能仍有延迟。”

我试图理解你的问题。 为此,我根据您提供的 SO 参考创建了下面的源代码。 我包含源代码,以便您或其他人可以检查、测试和使用它。

调试打印指的是正好 1 秒的睡眠。 调试打印比注释中的打印要短 - 调试打印总是指与 1 秒的偏差,无论定义了哪个唤醒时间。 因此,可以尝试减少唤醒时间 (wakeTime.tv_nsec-= some_value;) 以实现 1 秒的目标。

结论:

  • 我通常会同意你(davegravy)在你的帖子中写下它,除了我看到更高的延迟和偏差。
  • 非负载系统和重负载系统之间的延迟存在细微变化(所有 CPU 100% 负载)。 在重负载系统上,延迟分散减少,平均延迟也减少(在我的系统上 - 但不是很重要)。
  • 正如预期的那样,当我在另一台机器上尝试时,延迟变化很大(正如预期的树莓派更糟:o)。
  • 对于特定的机器和时刻,可以定义纳秒的校正值,以使平均睡眠更接近目标。 无论如何,校正值不一定等于没有校正的延迟误差。 并且不同机器的校正值可能不同。

想法:因为提供的代码可以衡量它的好坏。 代码可能会执行几个循环,从中它可以自己得出优化的延迟校正值。 (仅从理论的角度来看,这种自动校正可能很有趣。嗯,这是一个想法。)

想法 2:或者可以创建一些校正值,以避免在考虑多个间隔时出现长期偏移,一个接一个。

#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>

#define CLOCK CLOCK_MONOTONIC
//#define CLOCK CLOCK_REALTIME
//#define CLOCK CLOCK_TAI
//#define CLOCK CLOCK_BOOTTIME


static long calcTimeDiff(struct timespec const* t1, struct timespec const* t2)
{
  long diff = t1->tv_nsec - t2->tv_nsec;
  diff += 1000000000 * (t1->tv_sec - t2->tv_sec);
  return diff;
}

static void* tickThread()
{
  struct timespec sleepStart;
  struct timespec currentTime;
  struct timespec wakeTime;
  long sleepTime;
  long wakeDelay;


  while(1)
  {
      clock_gettime(CLOCK, &wakeTime);
      wakeTime.tv_sec += 1;
      wakeTime.tv_nsec -= 0; //  Value to play with for delay "correction"
    
    clock_gettime(CLOCK, &sleepStart);
    clock_nanosleep(CLOCK, TIMER_ABSTIME, &wakeTime, NULL);
    clock_gettime(CLOCK, &currentTime);
    sleepTime = calcTimeDiff(&currentTime, &sleepStart);
    wakeDelay = calcTimeDiff(&currentTime, &wakeTime);
    {
      /*printf("sleep req=%-ld.%-ld start=%-ld.%-ld curr=%-ld.%-ld sleep=%-ld delay=%-ld\n",
          (long) wakeTime.tv_sec, (long) wakeTime.tv_nsec,
          (long) sleepStart.tv_sec, (long) sleepStart.tv_nsec,
          (long) currentTime.tv_sec, (long) currentTime.tv_nsec,
          sleepTime, wakeDelay);*/
          
        // Debug Short Print with respect to target sleep = 1 sec. = 1000000000 ns
        long debugTargetDelay=sleepTime-1000000000;
        printf("sleep=%-ld delay=%-ld targetdelay=%-ld\n",    
          sleepTime, wakeDelay, debugTargetDelay);    
    }
  }
}


int main(int argc, char*argv[])
{
  tickThread();
}

一些 output with wakeTime.tv_nsec -= 0;

sleep=1000095788 delay=96104 targetdelay=95788
sleep=1000078989 delay=79155 targetdelay=78989
sleep=1000080717 delay=81023 targetdelay=80717
sleep=1000068001 delay=68251 targetdelay=68001
sleep=1000080475 delay=80519 targetdelay=80475
sleep=1000110925 delay=110977 targetdelay=110925
sleep=1000082415 delay=82561 targetdelay=82415
sleep=1000079572 delay=79713 targetdelay=79572
sleep=1000098609 delay=98664 targetdelay=98609

并使用wakeTime.tv_nsec -= 65000;

sleep=1000031711 delay=96987 targetdelay=31711
sleep=1000009400 delay=74611 targetdelay=9400
sleep=1000015867 delay=80912 targetdelay=15867
sleep=1000015612 delay=80708 targetdelay=15612
sleep=1000030397 delay=95592 targetdelay=30397
sleep=1000015299 delay=80475 targetdelay=15299
sleep=999993542 delay=58614 targetdelay=-6458
sleep=1000031263 delay=96310 targetdelay=31263
sleep=1000002029 delay=67169 targetdelay=2029
sleep=1000031671 delay=96821 targetdelay=31671
sleep=999998462 delay=63608 targetdelay=-1538

无论如何,延迟一直在变化。 我尝试了不同的 CLOCK 定义和不同的编译器选项,但没有任何特殊结果。

进一步测试的一些统计数据,两种情况下的样本量 = 100。
来自wakeTime.tv_nsec 的wakeTime.tv_nsec -= 0;
平均值 = 97503 标准差 = 27536

来自wakeTime.tv_nsec 的wakeTime.tv_nsec -= 97508;
平均值 = -1909 标准差 = 32682

在这两种情况下,都有一些大量的异常值,因此即使是来自 100 个样本的结果也可能不太具有代表性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM