【发布时间】:2013-11-24 11:40:55
【问题描述】:
我正在尝试确定我可以准确安排在 C/C++ 中发生的任务的粒度。目前我可以可靠地安排任务每 5 微秒发生一次,但我正在尝试看看是否可以进一步降低。
如果可能的话,我们将不胜感激有关如何实现这一目标的任何建议。
因为我知道计时器粒度通常取决于操作系统:我目前在 Linux 上运行,但如果时间粒度更好,我会使用 Windows(虽然我不相信它是基于我发现的查询性能计数器)
我在裸机(无 VM)上执行所有测量。 /proc/timer_info 确认我的 CPU 的纳秒计时器分辨率(但我知道这不会转化为纳秒警报分辨率)
当前
My current code can be found as a Gist here
目前,我能够每 5 微秒(5000 纳秒)执行一次请求,延迟到达率不到 1%。当确实发生延迟到达时,它们通常只落后一个周期(5000 纳秒)。
我现在正在做三件事
将进程设置为实时优先级(@Spudd86 here 指出的一些)
struct sched_param schedparm;
memset(&schedparm, 0, sizeof(schedparm));
schedparm.sched_priority = 99; // highest rt priority
sched_setscheduler(0, SCHED_FIFO, &schedparm);
最大限度地减少计时器的延迟
prctl(PR_SET_TIMERSLACK, 1);
使用 timerfds(2.6 Linux 内核的一部分)
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
struct itimerspec timspec;
bzero(&timspec, sizeof(timspec));
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = nanosecondInterval;
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = 1;
timerfd_settime(timerfd, 0, &timspec, 0);
可能的改进
- 为此进程指定一个处理器?
- 使用非阻塞 timerfd,这样我就可以创建一个紧密循环,而不是阻塞(紧密循环会浪费更多 CPU,但也可以更快地响应警报)
- 使用外部嵌入式设备触发(无法想象为什么会更好)
为什么
我目前正在为基准测试引擎创建工作负载生成器。工作负载生成器使用泊松过程模拟到达率(X 个请求/秒等)。从泊松过程中,我可以确定必须从基准测试引擎发出请求的相对时间。
因此,例如,每秒 10 个请求,我们可能会在以下位置发出请求: t = 0.02, 0.04, 0.05, 0.056, 0.09 秒
这些请求需要提前调度,然后执行。随着每秒请求数量的增加,调度这些请求所需的粒度也会增加(每秒数千个请求需要亚毫秒级的精度)。因此,我试图弄清楚如何进一步扩展这个系统。
【问题讨论】:
-
您是否已在启用 CONFIG_PREEMPT_RT 标志的情况下将内核修补为实时?
-
@Archie 不,我没有——感谢您向我指出这一点。
-
我认为您的问题与 C 或 C++ 没有任何关系。它们只是您的界面语言,不是吗?所以也许删除标签,并在你的问题标题中用 POSIX 替换 C++。
-
@JensGustedt 我认为 C 会让我在这个领域的人有更多的知名度?
-
@BSchlinker,“可见性”不应该是你的目标。标签和标题是为了吸引具有正确技能的专家来解决您的问题,而不是偏离可能不必对特定问题多说的其他人。
标签: c timer posix real-time poisson