RT Linux内核高优先级程序执行时间不一致问题咨询
问题描述
我们需要实现一款按固定周期向机器人发送指令的程序,该程序属于实时应用范畴。我们在PC上部署了打了PREEMPT_RT补丁的抢占式RT Linux内核,通过chrt -f 98或chrt -rr 99命令启动程序以指定调度策略与优先级,内核加载、程序启动流程均运行正常。
我们对程序运行的计算耗时(以CPU ticks为单位)进行测量,预期该耗时应保持恒定、仅存在极小幅波动,但实际测量到的计算时间存在显著偏差。我们最初推测是自研复杂程序存在未定义行为,因此编写了极简基础测试程序开展相同测量,结果仍然存在同样的耗时异常问题。
待解答问题
- 为何即便运行极简基础测试程序,测量得到的计算时间仍无法达到(接近)恒定的效果?
- 该问题应如何解决?
环境说明
我们参考公开安装教程在PC上部署了RT Linux内核,PC核心配置如下:
| PC配置项 | 参数详情 |
|---|---|
| CPU | Intel(R) Atom(TM) Processor E3950 @ 1.60GHz,4核心 |
| 内存RAM | 8 GB |
| 操作系统 | Ubuntu 20.04.1 LTS |
| 内核版本 | Linux 5.9.1-rt20 SMP PREEMPT_RT |
| 系统架构 | x86-64 |
测试方案
我们最初在测量单线程复杂程序执行时间时发现该问题,后续分别针对复杂程序、极简程序开展以下维度测试:
- CPU执行时间
- Wall time(真实世界墙钟时间)
- Wall time与CPU time的差值(Wall time - CPU time)、CPU time/Wall time比值
同时我们在该PC上开展了延迟测试。
延迟测试
延迟测试参考公开RT性能调优教程开展,测试结果如下:
- 通用内核延迟测试结果

- RT内核延迟测试结果

通过htop查看,相关进程优先级显示为RT。
复杂程序测试
我们在程序中多次调用目标函数,测量每次调用的耗时,测试结果如下:

观测到以下现象:
- 首次执行耗时约0.28ms,始终长于第二次执行的约0.18ms,但多数情况下首次执行并非耗时最长的迭代。
- 耗时众数约为0.17ms。
- 耗时达17ms的场景下,Wall time与CPU time差值通常为0、比值为1,该现象并非仅出现在该耗时区间;此类场景下似乎仅1个CPU核心被调用且处于饱和状态(无等待时间)。
- 当差值不为0时通常为负值,参考CPU时间统计相关公开文档与CPU time公开百科说明,该现象是因为程序调用了超过1个CPU核心。
极简程序测试
我们使用如下极简C++程序开展相同测试:
#include <vector> #include <iostream> #include <time.h> int main(int argc, char** argv) { int iterations = 5000; double a = 5.5; double b = 5.5; double c = 4.5; std::vector<double> wallTime(iterations, 0); std::vector<double> cpuTime(iterations, 0); struct timespec beginWallTime, endWallTime, beginCPUTime, endCPUTime; std::cout << "Iteration | WallTime | cpuTime" << std::endl; for (unsigned int i = 0; i < iterations; i++) { // 开始计时 clock_gettime(CLOCK_REALTIME, &beginWallTime); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &beginCPUTime); // 被测计算逻辑 a = b + c + i; // 结束计时并计算耗时 clock_gettime(CLOCK_REALTIME, &endWallTime); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &endCPUTime); wallTime[i] = (endWallTime.tv_sec - beginWallTime.tv_sec) + (endWallTime.tv_nsec - beginWallTime.tv_nsec)*1e-9; cpuTime[i] = (endCPUTime.tv_sec - beginCPUTime.tv_sec) + (endCPUTime.tv_nsec - beginCPUTime.tv_nsec)*1e-9; std::cout << i << " | " << wallTime[i] << " | " << cpuTime[i] << std::endl; } return 0; }

已知结论
- 若CPU time/Wall time比值等于程序调用的CPU核心数,则核心处于饱和状态、无等待时间。
- 若比值小于调用的CPU核心数,则说明存在等待时间(理论上程序仅应使用1个CPU核心,实际运行中会调用多个核心)。
如有需要可提供更多测试细节。
内容的提问来源于stack exchange,提问作者AlejoDiaz49
相关产品推荐
相关产品推荐

