TL;DR:使用Linux内核实时地使用NO_HZ_FULL,我需要隔离一个进程才能有确定性的结果,但是/proc/告诉我仍然存在本地定时器中断(除其他外)。怎么让它失效?
长版本:
我想确保我的程序没有被中断,所以我尝试使用一个实时Linux内核。我使用的是实时版本的arch Linux (linux-rt on AUR),并修改了内核的配置,以选择以下选项:
CONFIG_NO_HZ_FULL=y
CONFIG_NO_HZ_FULL_ALL=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_ALL=y然后,我重新启动我的计算机,以便在这个实时内核上启动,并使用以下选项:
nmi_watchdog=0
rcu_nocbs=1
nohz_full=1
isolcpus=1我还在BIOS中禁用了以下选项:
C state
intel speed step
turbo mode
VTx
VTd
hyperthreading我的CPU (i7-6700 3.40GHz)有4个核心(8个逻辑CPU和超线程技术),我可以在/proc/interrupts文件中看到CPU0、CPU1、CPU2、CPU3。
CPU1是由isolcpus内核参数隔离的,我想在这个CPU上禁用本地计时器中断。我认为带有CONFIG_NO_HZ_FULL和CPU隔离的实时内核(isolcpus)就足以做到这一点,我试图通过运行这些命令来检查:
cat /proc/interrupts | grep LOC > ~/tmp/log/overload_cpu1
taskset -c 1 ./overload
cat /proc/interrupts | grep LOC >> ~/tmp/log/overload_cpu1其中过载过程是:
***overload.c:***
int main()
{
for(int i=0;i<100;++i)
for(int j=0;j<100000000;++j);
}文件overload_cpu1包含结果:
LOC: 234328 488 12091 11299 Local timer interrupts
LOC: 239072 651 12215 11323 Local timer interrupts意思是651-488 = 163来自本地计时器的中断,而不是0.
作为比较,我做了同样的实验,但我改变了进程overload运行的核心(我一直在CPU1上观察中断):
taskset -c 0 : 8 interrupts
taskset -c 1 : 163 interrupts
taskset -c 2 : 7 interrupts
taskset -c 3 : 8 interrupts我的问题之一是为什么没有0中断?为什么当我的进程在CPU1上运行时,中断的数量会更多?(我的意思是,如果只有我的进程,NO_HZ_FULL会防止中断:“CONFIG_NO_HZ_FULL=y Kconfig选项会导致内核避免向具有单个可运行任务的CPU发送调度时钟中断”(HZ.txt)
也许可以解释一下,在CPU1上还有其他的进程在运行。我使用ps命令进行检查:
CLS CPUID RTPRIO PRI NI CMD PID
TS 1 - 19 0 [cpuhp/1] 18
FF 1 99 139 - [migration/1] 20
TS 1 - 19 0 [rcuc/1] 21
FF 1 1 41 - [ktimersoftd/1] 22
TS 1 - 19 0 [ksoftirqd/1] 23
TS 1 - 19 0 [kworker/1:0] 24
TS 1 - 39 -20 [kworker/1:0H] 25
FF 1 1 41 - [posixcputmr/1] 28
TS 1 - 19 0 [kworker/1:1] 247
TS 1 - 39 -20 [kworker/1:1H] 501如您所见,CPU1上有线程。这有可能禁用这些进程吗?我想这是因为如果不是这样的话,NO_HZ_FULL就永远不会起作用了吧?
带有TS类的任务不会干扰我,因为它们在SCHED_FIFO中没有优先级,我可以为我的程序设置这个策略。对于类FF和优先级小于99的任务也是一样的。
但是,您可以看到SCHED_FIFO和优先级99中的迁移/1。也许这些进程在运行时会导致中断。这解释了当我的进程在CPU0、CPU2和CPU3 (分别为8、7和8次中断)上运行时出现的几次中断,但这也意味着这些进程并不经常运行,然后也不能解释为什么当我的进程在CPU1上运行(163个中断)时会有很多中断。
我也做了同样的实验,但是使用过载过程的SCHED_FIFO,我得到:
taskset -c 0 : 1
taskset -c 1 : 4063
taskset -c 2 : 1
taskset -c 3 : 0在这种配置中,在我的进程在CPU1上使用CPU1策略,在其他CPU上使用更少的中断时,会出现更多的中断。你知道为什么吗?
发布于 2019-09-15 10:06:07
问题是,一个完全不挠痒痒的CPU。使用nohz_full=配置的自适应滴答(Adaptive)仍然会收到一些滴答。
最值得注意的是,调度程序需要在一个独立的、完全没有滴答的CPU上设置一个计时器,以便每一秒左右更新一次状态。
这是一项记录在案的限制(截至2019年):
一些进程处理操作仍然需要偶尔的调度时钟滴答。这些操作包括计算CPU负载、维护sched平均值、计算CFS实体v运行时、计算avenrun和执行负载平衡。他们目前被安排时钟滴答每一秒左右。正在进行的工作将消除这种需要,即使是这些罕见的调度时钟滴答声。
(资料来源:HZ.txt,参比)LWN文章“(几乎) 3.10中的全无痒操作从2013年开始”作为背景)
一种更精确的测量本地定时器中断(/proc/interrupts中的LOC行)的方法是使用perf。例如:
$ perf stat -a -A -e irq_vectors:local_timer_entry ./my_binary其中,my_binary将线程固定在独立的CPU上,这些CPU不间断地使用CPU,而不调用syscalls --比如2分钟。
还有其他来源的额外本地计时器滴答(当只有一个可运行的任务)。
例如,VM统计数据的集合--默认情况下,它们每秒钟收集一次。因此,我可以通过设置更高的值来减少LOC中断,例如:
# sysctl vm.stat_interval=60另一个来源是定期检查不同CPU上的TSC是否漂移--您可以使用以下内核选项禁用它们:
tsc=reliable(只有当你真正知道你的TSC不会漂移时,才应用这个选项。)
您可以通过使用飞迹记录跟踪(当您的测试二进制文件正在运行时)来找到其他源。
因为它出现在评论中:是的,SMI对内核是完全透明的。不会以NMI的形式出现。您只能间接地检测到SMI。
https://stackoverflow.com/questions/46077582
复制相似问题