为什么每秒进行一次非自愿上下文切换?

8
操作系统是RHEL 6(2.6.32)。我已经隔离了一个核心并在其上运行了一个计算密集型线程。/proc/{thread-id}/status显示每秒发生一次非自愿的上下文切换。
所讨论的线程是SCHED_NORMAL线程,我不想改变它。
如何减少这种非自愿上下文切换的数量?这是否取决于/proc/sys/kernel中的任何调度参数?
编辑:有几个回复提出了替代方法。在采取那种路线之前,我首先想要了解为什么即使在持续数小时的情况下,我每秒都会得到一次非自愿的上下文切换。例如,这是由CFS引起的吗?如果是,则是哪些参数以及如何进行设置?
编辑2:进一步澄清-我首先想回答的第一个问题是:为什么我每秒会得到一次非自愿的上下文切换,而不是每半秒或两秒钟一次?

1
你为什么要在意呢?即使每秒进行100次上下文切换,在现代系统中也只是噪音而已。 - David Schwartz
2
这是一个金融应用程序,延迟至关重要,每个上下文切换可能会导致一个或多个失去的机会。我想了解哪些系统调整参数决定了孤立核心上计算密集型线程的非自愿上下文切换率。 - Prasoon Tiwari
很可能是由于锁、正常磁盘I/O或页面错误而阻塞。 - David Schwartz
没有那些。在运行数小时期间,速率精确地为每秒一次的非自愿上下文切换。我几乎可以确定是CFS在做这件事情-但基于什么调度参数? - Prasoon Tiwari
就像@DavidSchwartz所说,如果这是一个问题,你需要一个专用的盒子和实时操作系统,而不是一个通用的桌面。上下文切换几乎总是因为良好的I/O性能而获得的机会。每秒钟发生一次非自愿的上下文切换 - 什么?就像David说的,谁在乎呢?优化真正重要的东西... - Martin James
1
@Martin:你明白为什么这个上下文切换会经常发生吗?这个盒子是专用的。在不了解当前问题的原因之前,跳到另一个解决方案是没有意义的。如果还不清楚 - 我想知道为什么我每秒钟都会得到一个上下文切换,而不是每半秒或两秒钟一次。肯定有机器和/或操作系统配置的某种组合 - 是什么呢? - Prasoon Tiwari
4个回答

14
这只是一个猜测,但是是有根据的——因为您使用了隔离的CPU,调度程序不会在其上调度除您自己之外的任何任务,但有一个例外——内核中的vmstat代码具有定时器,每秒钟在每个CPU上调度一个工作队列项以计算内存使用情况统计信息,这就是您看到的每秒钟调度的内容。
工作队列代码足够聪明,可以避免在核心处于100%空闲状态时调度工作队列内核线程,但如果它正在运行单个任务,则不能避免。
您可以使用ftrace进行验证。如果sched_switch跟踪器显示您每秒钟或如此切换到的实体(该值舍入为最近的jiffie事件,并且计时器在CPU空闲时不计数,因此可能会影响时间)是events/CPU_NUMBER任务(对于旧内核为keventd),那么几乎可以肯定,原因确实是vmstat_update函数将其定时器设置为每秒排队一个工作队列项,该工作队列项由events内核线程运行。
请注意,vmstat设置计时器的周期是可配置的 - 您可以通过vm.stat_interval sysctl旋钮将其设置为其他值。增加此值将降低此类中断的频率,但代价是内存使用统计数据不太准确。
我维护了一个维基页面,其中列出了隔离CPU工作负载的所有中断源here。我还正在开发一个补丁,使得vmstat在一次vmstat工作队列运行到下一次之间没有变化时不会安排工作队列项 - 例如,如果您在CPU上的单个任务不使用任何动态内存分配。不确定它是否对您有益,这取决于您的工作负载。

vm.stat_interval - 太棒了。我每10秒钟就有一次非自愿的上下文切换;这正是我需要理解的调节器。 - Mike S

0
我强烈建议您尝试优化代码本身,以便在CPU上运行时获得最大的效益。
无论如何,我不确定这是否有效,但是无论如何都要尝试一下并让我们知道:
我将基本上只是将调度策略设置为FIFO,然后给进程赋予最大可能的优先级。
#include<sched.h>
struct sched_param sp = sched_get_priority_max(SCHED_FIFO);
int ret;

ret = sched_setscheduler(0, SCHED_FIFO, &sp);
if (ret == -1) {
  perror("sched_setscheduler");
  return 1;
}

请记住,您的进程所做的任何阻塞语句很可能会导致调度程序将其从CPU中移除。
手册页面
编辑:
抱歉,刚刚注意到了pthread标签;概念仍然适用,请查看此手册页面: http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_setschedparam.3.html

你能告诉我为什么在没有阻塞语句的代码中,我每秒钟只看到一个非自愿上下文切换吗? - Prasoon Tiwari
我不太确定,但可能是调度程序正在使用RR算法并且您的进程时间片已经用完,因此您被调度后又回到CPU上。 - Fingolfin

0
如果你的专用CPU每秒钟有一个中断仍然太多,那么你真的不需要通过正常的调度程序。我可以建议使用实时和等时优先级级别,这可以比通常的抢占机制更可靠地安排你的进程。

0

现在已经是2023年了,我被谷歌吸引到这个问题上。感谢@gby,我发现了一个小旋钮叫做vm.stat_interval,也可以在/proc/sys/vm/stat_interval中找到。他的答案是最好的,但我想对它进行修改。

原帖发布12年后,如果有人不知道,你可以调整你的操作系统并隔离你的CPU,仍然可以获得中断。我们有一段时间使用了tuned项目(https://github.com/redhat-performance/tuned),它允许你这样做。但操作系统仍然需要进行内存清理,而默认值是1 Hz。这是通过sysstat控制的stat_interval设置。

https://www.suse.com/c/cpu-isolation-introduction-part-1/上有一篇很好的文章,讨论了CPU隔离,包括消除中断。正如文章所说,“一些更专业的需求可能会明显受到它们道路上的干扰。这对于需要整个CPU时间并且不能容忍任何周期窃取的处理是一个例子。”其中引用的一个例子是由Solarflare网络卡驱动程序和Onload使用的DPDK。

无论如何,在其他情况下隔离的CPU上,使用在Red Hat系统中找到的cpu-partitioning调优配置文件,将vm.stat_interval设置为10,应用程序将每10秒中断一次。这是隔离的CPU上周期性非自愿上下文切换的来源。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接