【问题标题】:A HR timers precision study case一个 HR 计时器精度研究案例
【发布时间】:2017-06-22 08:08:04
【问题描述】:

有了这个话题,我最好讨论一下 HR 计时器和真正的精度问题。

我研究了很多关于它们的文档,我确信它们是解决 linux 内核模块内延迟执行问题的最佳和最可靠的解决方案,CPU 成本更低,计时精度更高(例如一些时间紧迫的驱动程序也使用它们,例如https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/pwm/gpio-pwm.c?rev=35328)。

你也适合吗?

这是我见过的关于这个主题的最全面、最详细的文档之一:https://www.landley.net/kdocs/ols/2006/ols2006v1-pages-333-346.pdf

HR 计时器承诺采用 jiffies 分辨率,但不幸的是,在我的系统上,延迟低于 6 毫秒时我没有得到预期的结果(稍后我将展示更多细节)。

我的环境是:

  • Windows 10 PRO 64 位/8Gb RAM/CPU Intel 4 核
  • VMWare 播放器 12
  • 虚拟化操作系统 Linux Mint 18.1 64 位

  • 内核配置

    • 版本:4.10.0-24-generic
    • CONFIG_HIGH_RES_TIMERS=y
    • CONFIG_POSIX_TIMERS=y
    • CONFIG_NO_HZ_COMMON=y
    • CONFIG_NO_HZ_IDLE=y
    • CONFIG_NO_HZ=y
    • CONFIG_HZ_250=y
    • CONFIG_HZ=250

    • /sys/devices/system/clocksource/clocksource0/available_clocksource => tsc hpet acpi_pm

    • /sys/devices/system/clocksource/clocksource0/current_clocksource => tsc

为了做一个基准测试,我编写了一个 linux 内核模块,我在 url https://bitbucket.org/DareDevilDev/hr-timers-tester/ 上免费发布了它。 README文件中有自己编译运行的说明。

它执行一系列循环如下:

  • 10 uS .. 90 uS,以 10 uS 递增
  • 100 uS .. 900 uS,以 100 uS 递增
  • 1 毫秒 .. 9 毫秒,以 1 毫秒递增
  • 10 ms .. 90 ms,以 10 ms 递增
  • 100 ms .. 900 ms,以 100 ms 递增
  • 最后是 1 秒

时间由“ktime_get”函数测量并存储在一个预先分配的数组中,以实现更快的性能,并避免在 hr 计时器回调中出现不必要的延迟。

模块采集数据后,打印出采样数据表。

对于我的场景相关数据是:

   10 uS =      41082 nS
   20 uS =      23955 nS
   30 uS =     478361 nS
   40 uS =      27341 nS
   50 uS =     806875 nS
   60 uS =     139721 nS
   70 uS =     963793 nS
   80 uS =      39475 nS
   90 uS =     175736 nS
  100 uS =    1096272 nS
  200 uS =      10099 nS
  300 uS =     967644 nS
  400 uS =     999006 nS
  500 uS =    1025254 nS
  600 uS =    1125488 nS
  700 uS =     982296 nS
  800 uS =    1011911 nS
  900 uS =     978652 nS
 1000 uS =    1985231 nS
 2000 uS =    1984367 nS
 3000 uS =    2068547 nS
 4000 uS =    5000319 nS
 5000 uS =    4144947 nS
 6000 uS =    6047991 nS <= First expected delay!
 7000 uS =    6835180 nS
 8000 uS =    8057504 nS
 9000 uS =    9218573 nS
10000 uS =   10435313 nS

...等等...

正如您在上面的内核日志转储中看到的,6 毫秒是第一个预期的延迟样本。

我在我的 C.H.I.P. 上重复了相同的测试。嵌入式系统 (https://getchip.com/pages/chip),一个基于 ARM 的板 Raspberry,运行频率为 1 GHz,配备 Ubuntu 14.04(内核 4.4.13,HZ = 200)。

在这种情况下我得到了更好的结果:

  30 =      44666 nS
  40 =      24125 nS
  50 =      49208 nS
  60 =      60208 nS
  70 =      70042 nS
  80 =      78334 nS
  90 =      89708 nS
 100 =     126083 nS
 200 =     184917 nS
 300 =     302917 nS <= First expected delay!
 400 =     395000 nS
 500 =     515333 nS
 600 =     591583 nS
 700 =     697458 nS
 800 =     800875 nS
 900 =     900125 nS
1000 =    1013375 nS

...等等...

在便宜的板上,自 300 美元以来就取得了良好的效果。

你有什么意见?有没有更好的方法以独立于平台的方式从 HR 计时器中获得更高的精度? HR 计时器不是精确计时的错误解决方案(当我们必须编写硬件驱动程序时是必需的)?

我们将非常感谢每一个贡献。

谢谢!

【问题讨论】:

    标签: linux timer linux-kernel drivers


    【解决方案1】:

    问题解决了,是虚拟化环境的问题。

    在一台旧笔记本电脑(HP 单核 1.9GHz)上,我得到了 60 uS 以来的良好延迟,而在较新的笔记本电脑(戴尔四核)上,我得到了低于 10 uS 的良好延迟!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-08
      • 2020-10-25
      • 1970-01-01
      • 2010-09-25
      • 2019-07-12
      • 2013-06-02
      • 1970-01-01
      • 2012-01-23
      相关资源
      最近更新 更多