好的水平不能在Linux上工作

我有一些高度浮点密集型进程,I / O很less。 一个叫做“xspec”,它计算一个数字模型,并且每秒钟通过stdout返回一个浮点结果返回一个主进程。 这是在19级。 我有另一个简单的过程“cpufloattest”,只是在一个紧密的循环中进行数值计算。 这不是唠叨。

我有一个禁用超线程的4核i7系统。 我已经开始了每种types的过程。 为什么Linux调度程序(Linux 3.4.2)不能恰当地限制最终进程所占用的CPU时间?

 Cpu:56.2%us,1.0%sy,41.8%ni,0.0%id,0.0%wa,0.9%hi,0.1%si,0.0%st
 Mem:总共12297620k,使用12147472k,使用150148k,使用831564k缓冲
交换次数:总计2104508k,使用71172k,存储2033336k,存储4753956k

   PID用户PR NI VIRT RES SHR S%CPU%MEM时间+命令                                         
 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个是用ncut(即4个用于大部分CPU,4个用于很less)

我发现了这个问题。 这是由于CFS调度程序的“自动分组”function。 如果我做

 echo 0> / proc / sys / kernel / sched_autogroup_enabled 

那么一切都像你所期望的一样。 好的0进程运行时,好的19进程下降到接近零的CPU使用率。

我将尝试find自动分组正在做什么来打破我的用例,并更新这个答案。

编辑…我和IRC上的一些内核人员聊天,他们刚刚说我应该禁用它,如果它不适合我的工作负载,而且这只是Linus喜欢的一个疯狂的补丁。 我不知道为什么autogrouping不喜欢我的工作量,但这个答案是在这里遇到类似问题的人。

为接受的答案添加更多的细节…您看到的行为是由于Linux 2.6.38(2010年)中添加的自动分组function。 据推测,在所描述的情况下,这两个命令运行在不同的terminal窗口。 如果他们已经在同一个terminal窗口中运行,那么你应该已经看到这个好的值有效果。 这个答案的其余部分阐述了这个故事。

内核提供了一种称为自动分组的function,以在面对多进程,CPU密集型工作负载(如构build具有大量并行构build进程的Linux内核(即make(1) -j标志))的情况下提高交互式桌面性能。

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

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

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

好的价值和组安排

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

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

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

相反,对于在不同会话中(例如,不同terminal窗口,其每个作业被绑定到不同的自动分组)的唯一的CPU绑定进程的两个进程,修改其中一个会话中的进程的良好值在调度程序相对于另一个会话中的过程的决定方面没有影响。 这大概是你看到的情况,虽然你没有明确提到使用两个terminal窗口。

如果要防止自动分组干扰这里描述的传统的nice行为,那么正如在接受的答案中所指出的那样,您可以禁用该function

 echo 0 > /proc/sys/kernel/sched_autogroup_enabled 

但是,请注意,这也会导致禁用自动分组function旨在提供的桌面交互function的好处(请参阅上文)。

自动分组好的价值

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

 $ cat /proc/1/autogroup /autogroup-1 nice 0 

这个文件也可以用来修改分配给自动组的CPU带宽。 这是通过在文件的“好”范围内写入一个数字来设置自动组的好值。 允许的范围是从+19(低优先级)到-20(高优先级)。

autogroup nice设置与进程nice值具有相同的含义,但基于其他autogroups的相对nice值,将整个CPU周期分配给自动组。 对于一个自动分组中的进程,它接收到的CPU周期将是自动分组的nice值(与其他自动分组进行比较)和进程的nice值(与同一个自动分组中的其他进程相比)的结果。

可能不完全是你正在寻找,但你有没有尝试命令cpulimit ? 它在Debian / Ubuntu存储库中是最less的。

使用cpulimit您可以调整允许进程的整个CPU时间百分比。 另一种可能性是使用cgroups ,但是cpulimit更简单易用。

只需要将xspec简化为单个进程即可,因此您将拥有4:1或3:1的性能。

我想你的意思是把优先级设置得更高? 在这种情况下,你会想要使用负值 。

在你的输出中,cpufloattest比xspec具有更高的优先级。

编辑:您可以使用taskset设置一个进程使用特定的处理器,但是,在这种情况下,这不是必要的。