不错的水平在 linux 上不起作用

xio*_*xox 5 linux scheduler nice

我有一些高度浮点密集型进程做很少的 I/O。一个叫做“xspec”,它计算一个数值模型并每秒将一个浮点结果返回给主进程(通过标准输出)。它在 19 级时很好。我有另一个简单的过程“cpufloattest”,它只是在一个紧密的循环中进行数值计算。它不是很好。

我有一个禁用超线程的 4 核 i7 系统。我已经开始了每种类型的过程中的 4 个。为什么 Linux 调度程序 (Linux 3.4.2) 没有正确限制 niced 进程占用的 CPU 时间?

Cpu(s): 56.2%us, 1.0%sy, 41.8%ni, 0.0%id, 0.0%wa, 0.9%hi, 0.1%si, 0.0%st
内存:总共 12297620k,已使用 12147472k,150148k 空闲,831564k 缓冲区
交换:总共 2104508k,已使用 71172k,空闲 2033336k,缓存 4753956k

  PID 用户 PR NI VIRT RES SHR S %CPU %MEM TIME+ 命令                                         
32399 jss 20 0 44728 32m 772 R 62.7 0.3 4:17.93 cpufloattest                                    
32400 jss 20 0 44728 32m 744 R 53.1 0.3 4:14.17 cpufloattest                                    
32402 jss 20 0 44728 32m 744 R 51.1 0.3 4:14.09 cpufloattest                                    
32398 jss 20 0 44728 32m 744 R 48.8 0.3 4:15.44 cpufloattest                                    
 3989 jss 39 19 1725m 690m 7744 R 44.1 5.8 1459:59 xspec                                           
 3981 jss 39 19 1725m 689m 7744 R 42.1 5.7 1459:34 xspec                                           
 3985 jss 39 19 1725m 689m 7744 R 42.1 5.7 1460:51 xspec                                           
 3993 jss 39 19 1725m 691m 7744 R 38.8 5.8 1458:24 xspec                                           

如果我启动 8 个 cpufloattest 进程,调度程序会按照我的预期执行,其中 4 个进程被处理(即 4 个 CPU 占用大部分,4 个 CPU 占用很少)

xio*_*xox 9

我发现了导致这个问题的原因。这是由于 CFS 调度程序的“自动分组”功能。如果我做

回声 0 > /proc/sys/kernel/sched_autogroup_enabled 

然后一切都如您所愿。当 nice 0 进程运行时, nice 19 进程的 CPU 使用率下降到接近零。

我将尝试准确找出自动分组正在做什么以打破我的用例并更新此答案。

编辑...我和 IRC 上的一些内核人员聊天,他们只是说如果它不能满足我的工作量,我应该禁用它,而且这只是一个 Linus 喜欢的疯狂补丁。我不确定为什么自动分组不喜欢我的工作量,但这个答案是为遇到类似问题的人准备的。


小智 6

为已接受的答案添加一些进一步的细节......您看到的行为是因为在 Linux 2.6.38(2010 年)中添加了自动分组功能。大概在描述的场景中,这两个命令是在不同的终端窗口中运行的。如果它们在同一个终端窗口中运行,那么您应该已经看到 nice 值产生了影响。这个答案的其余部分详细阐述了这个故事。

内核提供了一种称为自动分组的功能,以在面对多进程、CPU 密集型工作负载时提高交互式桌面性能,例如使用大量并行构建进程(即make(1) -j标志)构建 Linux 内核。

通过创建新会话时会创建一个新的自动组setsid(2);例如,当一个新的终端窗口启动时,就会发生这种情况。创建的新进程fork(2)继承其父级的自动组成员资格。因此,会话中的所有进程都是同一个自动组的成员。

当启用自动分组(这是许多发行版的默认设置)时,自动分组的所有成员都被放置在同一个内核调度程序“任务组”中。Linux 内核调度程序采用一种算法来均衡跨任务组的 CPU 周期分布​​。可以通过以下示例描述这对交互式桌面性能的好处。

假设有两个自动组竞争同一个 CPU(即,假定一个 CPU 系统或使用taskset(1) 将所有进程限制在 SMP 系统上的同一个 CPU)。第一组包含来自内核构建的十个 CPU 绑定进程make -j10. 另一个包含一个受 CPU 限制的进程:视频播放器。自动分组的效果是这两个组将各自接收一半的 CPU 周期。也就是说,视频播放器将接收 50% 的 CPU 周期,而不仅仅是 9% 的周期,这可能会导致视频播放质量下降。SMP 系统上的情况更复杂,但总体效果是相同的:调度程序在任务组之间分配 CPU 周期,这样包含大量 CPU 绑定进程的自动组最终不会以牺牲 CPU 周期为代价系统上的其他作业。

不错的价值和团体安排

在调度非实时进程(例如,在默认SCHED_OTHER策略下调度的进程)时,调度程序采用一种称为“组调度”的技术,在该技术下,线程在“任务组”中进行调度。任务组是在各种情况下形成的,这里的相关案例是自动分组。

如果启用setsid(2)了自动分组,则(隐式)放置在自动分组中的所有线程(即,由 所创建的相同会话)形成一个任务组。因此,每个新的自动组都是一个单独的任务组。

在组调度下,线程的 nice 值仅对与同一任务组中的其他线程相关的调度决策有影响。就 UNIX 系统上 nice 值的传统语义而言,这会产生一些令人惊讶的后果。特别是,如果启用了自动分组,那么nice(1)在进程上使用仅对相对于在同一会话中执行的其他进程(通常:同一终端窗口)的调度有影响。

相反,对于(例如)不同会话中唯一受 CPU 限制的进程的两个进程(例如,不同的终端窗口,其每个作业都绑定到不同的自动组),在其中一个会话中修改进程的 nice 值对调度程序相对于另一个会话中的进程的决定没有影响。这大概是您看到的场景,尽管您没有明确提到使用两个终端窗口。

如果您想防止自动分组干扰nice此处描述的传统行为,那么,如已接受的答案中所述,您可以禁用该功能

echo 0 > /proc/sys/kernel/sched_autogroup_enabled
Run Code Online (Sandbox Code Playgroud)

但请注意,这也会导致禁用自动分组功能旨在提供的桌面交互优势(见上文)。

自动分组好值

可以通过文件查看进程的自动组成员身份/proc/[pid]/autogroup

$ cat /proc/1/autogroup
/autogroup-1 nice 0
Run Code Online (Sandbox Code Playgroud)

此文件还可用于修改分配给自动组的 CPU 带宽。这是通过将“nice”范围内的数字写入文件来设置自动组的 nice 值来完成的。允许的范围是从 +19(低优先级)到 -20(高优先级)。

autogroup nice 设置与 process nice 值具有相同的含义,但适用于根据其他 autogroup 的相对 nice 值将 CPU 周期分配给整个 autogroup。对于自动组内的进程,它接收的 CPU 周期将是自动组的 nice 值(与其他自动组相比)和进程的 nice 值(与同一自动组中的其他进程相比)的乘积。