我写了一个测试程序,它只是由一些计算内的无限循环,而没有执行任何I / O操作。 我试图启动该程序的两个实例,一个具有高的nice值值,另一个具有低nice值值:
sudo nice -n 19 taskset 1 ./test
sudo nice -n -20 taskset 1 ./test
在使用taskset命令,确保两个程序在同一内核上执行。 出乎我的意料,上报告说,这两个方案得到的计算时间约50%。 这是为什么? 不漂亮的命令,即使有效果?
我写了一个测试程序,它只是由一些计算内的无限循环,而没有执行任何I / O操作。 我试图启动该程序的两个实例,一个具有高的nice值值,另一个具有低nice值值:
sudo nice -n 19 taskset 1 ./test
sudo nice -n -20 taskset 1 ./test
在使用taskset命令,确保两个程序在同一内核上执行。 出乎我的意料,上报告说,这两个方案得到的计算时间约50%。 这是为什么? 不漂亮的命令,即使有效果?
您所看到的行为,因为这是在Linux的2.6.38增加(2010年)的autogroup功能几乎可以肯定。 据推测,当你描述运行两个命令,他们在不同的终端窗口中运行。 如果你在同一个终端窗口中运行它们,那么你应该已经看到了很好的价值都有影响。 这个答案的其余部分阐述的故事。
内核提供了一种称为自动组合,以提高多进程的脸交互式桌面的性能特征,CPU密集型工作负载,如拥有大量并行构建过程的构建Linux内核(即, make(1) -j
标志)。
当通过创建一个新的会话时,创建新autogroup setsid(2)
; 出现这种情况,例如,当启动一个新的终端窗口。 通过创建一个新的进程fork(2)
继承了其父的autogroup成员。 因此,所有的会话中的处理是相同的autogroup的成员。
如果启用了自动分组,所有的autogroup成员都放在同一个内核调度“任务组”的。 Linux内核调度采用了均衡的CPU周期的整个任务组分配的算法。 这种交互式桌面性能的好处是可以通过下面的例子来说明。
假设有两个autogroups用于相同CPU竞争(即,假设一个单一的CPU系统或使用的taskset(1)
以限制在SMP系统中所有进程的相同CPU)。 第一组包含从内核打造十大CPU密集型进程开始make -j10
。 其他包含单个CPU绑定的过程:一个视频播放器。 自动组合的效果是两组将各自接收的CPU周期的一半。 也就是说,视频播放器将接收到的CPU周期的50%,而非周期,这将可能导致降级的视频播放的只有9%。 在SMP系统上的情况比较复杂,但一般效果是相同的:所述调度跨任务组分配的CPU周期,使得含有大量CPU绑定过程的autogroup不结束牺牲占用CPU周期的系统上的其他工作。
nice值和组调度
当调度非实时处理(例如,那些默认下调度SCHED_OTHER
策略),调度器采用了被称为“组调度”,根据该线程被调度中的“任务组”的技术。 形成在各种情况下工作组,有关情况正在此间自动组合。
如果自动组合被启用,则所有被(隐式地)放置在autogroup螺纹的(即,相同的会话,如创建setsid(2)
形成一个任务组。 因此,每个新autogroup是一个单独的任务组。
在组调度,线程的nice值对只是相对于其他线程在同一任务组中调度决策的影响。 这在UNIX系统上的nice值的传统语义方面的一些令人吃惊的后果。 具体地,如果自动组合被使能(这是在各个Linux发行版的默认值),然后采用nice(1)
上的方法仅具有用于相对于在相同的会话中执行的其它过程的调度的效果(一般为:在同一终端窗口) 。
相反,对于那些(例如)两个进程在不同的会话(的例如,不同的终端窗口,每个他们的工作被绑定到不同autogroups),修改在所述会话中的一个进程的nice值唯一CPU密集型进程在调度的决定相对于其他会话进程方面没有影响。 这大概是你看到的情景,尽管你不明确提到使用两个终端窗口。
如果你想防止自动组合与传统的干扰nice
行为,这里所描述的,您可以禁用该功能
echo 0 > /proc/sys/kernel/sched_autogroup_enabled
要知道,虽然这也将禁止用于该autogroup功能,旨在提供(见上文)桌面交互的利益的影响。
该autogroup nice值
可以通过文件被看作一个进程的autogroup成员/proc/[pid]/autogroup
:
$ cat /proc/1/autogroup
/autogroup-1 nice 0
该文件还可以用来修改分配给autogroup的CPU带宽。 这是通过写在“好”范围内的数字的文件来设置autogroup的nice值来完成。 允许的范围是从19(低优先级)至-20(高优先级)。
所述autogroup好的设置的含义与过程nice值相同,但适用于CPU周期分配给autogroup作为一个整体,基于其他autogroups的相对nice值。 对于一个内部autogroup的方法,它接收的CPU周期将是autogroup的nice值的产物(相对于其他autogroups),并且处理的nice值(相对于在相同的autogroup其它进程)。
我把一个test.c的,只是做:
for(;;)
{
}
然后用你的漂亮的跑了。 我没有运行每一个不同的须藤,而是sudo'd交互的shell两者从那里跑了他们。 我用了两个和的。
我有一个./test打我的CPU硬,和一个几乎没有触及它。
当然,系统仍然觉得非常敏感; 它需要大量的现代处理器的CPU-粗加工过程中获得如此巨大的负荷,你可以“感觉”它。
这鲜明的对比I / O-占用过程和存储器占用过程; 在这些情况下,一个贪婪的过程可以使系统痛苦的使用。
我猜您的系统可能有一个比较独特的优先事项有关的bug(或微妙),或有什么东西与你的方法。
我跑了一个Ubuntu 11.04系统上我的测试。
我假设有一个&
在命令行的末尾失踪。 否则,第二线将不会运行,直到第一个完成。
虽然这两个进程正在运行,使用这样的top
,并确保他们每个人都有,你指定nice值。
如果你只使用启动过程,会发生什么taskset
,然后用调整自己的优先级renice
他们正在运行后?
流程美好的事物(优先级)设置已经在Linux上的效果! (在实践中,但只有当你给它足够的工作呢!)
在我的系统,只要所有的核心都满载,那么漂亮的确实有一定影响。 通过0.807 ** N操作获取在Ubuntu 14.04,过程与漂亮-N运行相比,运行进程不改变nice值(给你的每个核运行一个实例每个好的水平)。
在我来说,我有四核i7支持超线程关闭,所以如果我运行四个或更少的进程,然后它不会不管他们漂亮的值是 - 他们每人得到一个完整的核心。 如果我在不错的水平12运行在漂亮的0级和第4四道工序,然后是那些在12级打通0.807 ^ 12,工作的人,在漂亮的零级做的也就是大约7%。 的比率似乎通过14是从不错的水平0合理预测器,在这之后它波动(几运行有很好的水平18处理多于好的16例如) - 运行测试更长可以平滑结果出来。
(红宝石2.1.2使用)
,CL文件:
uptime
nices='-0 -6 -12 -18'
nices='-0 -18'
nices='-0 -2 -4 -6 -8 -10 -12 -14 -16 -18'
rm -f ,n-*
for i in 1 2 3 4
do
for n in $nices
do
nice $n ruby ,count_loops.rb > ,n${n}-$i &
done
done
ps -l
uptime
wait
uptime
ps -l
c=`cat ,n-0-[1234] | total`
last=$c
for n in $nices
do
echo
c2=`cat ,n${n}-[1234] | total`
echo total of `cat ,n${n}-[1234]` is $c2
echo -n "nice $n count $2, percentage: "
echo "3 k $c2 100 * $c / p" | dc
echo -n " percent of last: "
echo "3 k $c2 100 * $last / p" | dc
last=$c2
done
uptime
echo total count: `cat ,n-*-[1234] | total`
,count_loops.rb文件
#!/usr/bin/env ruby
limit = Time.new + 70
i=0
while Time.new < limit
i += 1
j = 0
while (j += 1) < 10000
t = j
end
end
puts i
的结果sh ,cl
-初始诊断输出:
19:16:25 up 20:55, 2 users, load average: 3.58, 3.59, 2.88
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 4987 4977 0 80 0 - 7297 wait pts/3 00:00:00 bash
0 S 1000 11743 2936 0 80 0 - 2515 wait pts/3 00:00:00 rubymine.sh
0 S 1000 11808 11743 6 80 0 - 834604 futex_ pts/3 00:18:10 java
0 S 1000 11846 11808 0 80 0 - 4061 poll_s pts/3 00:00:02 fsnotifier64
0 S 1000 19613 4987 0 80 0 - 2515 wait pts/3 00:00:00 sh
0 R 1000 19616 19613 0 80 0 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19617 19613 0 82 2 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19618 19613 0 84 4 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19619 19613 0 86 6 - 7416 - pts/3 00:00:00 ruby
0 R 1000 19620 19613 0 88 8 - 6795 - pts/3 00:00:00 ruby
0 R 1000 19621 19613 0 90 10 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19622 19613 0 92 12 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19623 19613 0 94 14 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19624 19613 0 96 16 - 6078 - pts/3 00:00:00 ruby
0 R 1000 19625 19613 0 98 18 - 6012 - pts/3 00:00:00 ruby
0 R 1000 19626 19613 0 80 0 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19627 19613 0 82 2 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19628 19613 0 84 4 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19629 19613 0 86 6 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19630 19613 0 88 8 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19631 19613 0 90 10 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19632 19613 0 92 12 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19633 19613 0 94 14 - 6144 - pts/3 00:00:00 ruby
0 R 1000 19634 19613 0 96 16 - 4971 - pts/3 00:00:00 ruby
0 R 1000 19635 19613 0 98 18 - 4971 - pts/3 00:00:00 ruby
0 R 1000 19636 19613 0 80 0 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19637 19613 0 82 2 - 7449 - pts/3 00:00:00 ruby
0 R 1000 19638 19613 0 84 4 - 7344 - pts/3 00:00:00 ruby
0 R 1000 19639 19613 0 86 6 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19640 19613 0 88 8 - 7416 - pts/3 00:00:00 ruby
0 R 1000 19641 19613 0 90 10 - 6210 - pts/3 00:00:00 ruby
0 R 1000 19642 19613 0 92 12 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19643 19613 0 94 14 - 5976 - pts/3 00:00:00 ruby
0 R 1000 19644 19613 0 96 16 - 6111 - pts/3 00:00:00 ruby
0 R 1000 19645 19613 0 98 18 - 4971 - pts/3 00:00:00 ruby
0 R 1000 19646 19613 0 80 0 - 7582 - pts/3 00:00:00 ruby
0 R 1000 19647 19613 0 82 2 - 7516 - pts/3 00:00:00 ruby
0 R 1000 19648 19613 0 84 4 - 7416 - pts/3 00:00:00 ruby
0 R 1000 19649 19613 0 86 6 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19650 19613 0 88 8 - 6177 - pts/3 00:00:00 ruby
0 R 1000 19651 19613 0 90 10 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19652 19613 0 92 12 - 6078 - pts/3 00:00:00 ruby
0 R 1000 19653 19613 0 94 14 - 6247 - pts/3 00:00:00 ruby
0 R 1000 19654 19613 0 96 16 - 4971 - pts/3 00:00:00 ruby
0 R 1000 19655 19613 0 98 18 - 4971 - pts/3 00:00:00 ruby
0 R 1000 19656 19613 0 80 0 - 3908 - pts/3 00:00:00 ps
19:16:26 up 20:55, 2 users, load average: 3.58, 3.59, 2.88
19:17:37 up 20:56, 3 users, load average: 28.92, 11.25, 5.59
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 4987 4977 0 80 0 - 7297 wait pts/3 00:00:00 bash
0 S 1000 11743 2936 0 80 0 - 2515 wait pts/3 00:00:00 rubymine.sh
0 S 1000 11808 11743 6 80 0 - 834604 futex_ pts/3 00:18:10 java
0 S 1000 11846 11808 0 80 0 - 4061 poll_s pts/3 00:00:02 fsnotifier64
0 S 1000 19613 4987 0 80 0 - 2515 wait pts/3 00:00:00 sh
0 R 1000 19794 19613 0 80 0 - 3908 - pts/3 00:00:00 ps
结果sh ,cl
-统计:(去年比例是这个总额的百分比进行比较的计数进程的最后一组)
total of 99951 101725 100681 104046 is 406403
nice -0 count , percentage: 100.000
percent of last: 100.000
total of 64554 62971 64006 63462 is 254993
nice -2 count , percentage: 62.743
percent of last: 62.743
total of 42997 43041 43197 42717 is 171952
nice -4 count , percentage: 42.310
percent of last: 67.434
total of 26882 28250 27151 27244 is 109527
nice -6 count , percentage: 26.950
percent of last: 63.696
total of 17228 17189 17427 17769 is 69613
nice -8 count , percentage: 17.129
percent of last: 63.557
total of 10815 10792 11021 11307 is 43935
nice -10 count , percentage: 10.810
percent of last: 63.113
total of 7023 6923 7885 7323 is 29154
nice -12 count , percentage: 7.173
percent of last: 66.357
total of 5005 4881 4938 5159 is 19983
nice -14 count , percentage: 4.917
percent of last: 68.542
total of 3517 5537 3555 4092 is 16701
nice -16 count , percentage: 4.109
percent of last: 83.576
total of 4372 4307 5552 4527 is 18758
nice -18 count , percentage: 4.615
percent of last: 112.316
19:17:37 up 20:56, 3 users, load average: 28.92, 11.25, 5.59
total count: 1141019
(纯粹主义者会注意到我在混合宝石,贝壳和直流 - 他们必须原谅我从上世纪显示通过旧习惯;))
我从运行APUE的例子程序和nice
确实有效果。
范例程序主要fork
子和两个父和子执行i++
对于给定的时间(10秒)的增量操作。 通过给孩子不同的nice
值,结果表明,如果nice
有差别。
书中警告说,我应该跑一个单处理器PC的程序,最前一页我试着用我自己的电脑, i5-7500 CPU @ 3.40GHz × 4
(4个核),给予不同的nice
值,几乎没有差别。
然后我登录到我的远程服务器, 1 processor 1 GB
,并得到预想的不同。
1 core processor 1 GB
测试结果:
./a.out
NZERO = 20
current nice value in parent is 0
current nice value in child is 0, adjusting by 0
now child nice value is 0
parent count = 13347219
child count = 13357561
./a.out 20 //child nice set to 20
NZERO = 20
current nice value in parent is 0
current nice value in child is 0, adjusting by 20
now child nice value is 19
parent count = 29770491
ubuntu@VM-0-2-ubuntu:~$ child count = 441330
测试程序(我做了一个小的修改),从第8.16节,APUE:
apue.h
仅仅是一个报头的包装
err_sys()
也是一个错误处理程序的包装,你可以使用printf
暂时。
#include "apue.h"
#include <errno.h>
#include <sys/time.h>
#if defined(MACOS)
#include <sys/syslimits.h>
#elif defined(SOLARIS)
#include <limits.h>
#elif defined(BSD)
#include <sys/param.h>
#endif
unsigned long long count;
struct timeval end;
void
checktime(char *str)
{
struct timeval tv;
gettimeofday(&tv, NULL);
if (tv.tv_sec >= end.tv_sec && tv.tv_usec >= end.tv_usec) {
printf("%s count = %lld\n", str, count);
exit(0);
}
}
int
main(int argc, char *argv[])
{
pid_t pid;
char *s;
int nzero, ret;
int adj = 0;
setbuf(stdout, NULL);
#if defined(NZERO)
nzero = NZERO;
#elif defined(_SC_NZERO)
nzero = sysconf(_SC_NZERO);
#else
#error NZERO undefined
#endif
printf("NZERO = %d\n", nzero);
if (argc == 2)
adj = strtol(argv[1], NULL, 10);
gettimeofday(&end, NULL);
end.tv_sec += 10; /* run for 10 seconds */
if ((pid = fork()) < 0) {
err_sys("fork failed");
} else if (pid == 0) { /* child */
s = "child";
printf("current nice value in child is %d, adjusting by %d\n",
nice(0), adj);
errno = 0;
if ((ret = nice(adj)) == -1 && errno != 0)
err_sys("child set scheduling priority");
printf("now child nice value is %d\n", ret);
} else { /* parent */
s = "parent";
printf("current nice value in parent is %d\n", nice(0));
}
for(;;) {
if (++count == 0)
err_quit("%s counter wrap", s);
checktime(s);
}
}
完整的源代码链接: https://wandbox.org/permlink/8iryAZ48sIbaq27y