我正在研究如何在后台运行CPU密集型任务时让我的Linux桌面体验保持流畅和交互。下面是我用来模拟CPU负载的示例程序(用Java编写):
public class Spinner {
public static void main(String[] args)
{
for (int i = 0; i < 100; i++) {
(new Thread(new Runnable() {
public void run() {
while (true);
}
})).start();
}
}
}
当我在命令行上运行它时,我注意到我的桌面应用程序(例如文本编辑器)的交互性显着下降。我有一台双核机器,所以我并不为此感到惊讶。
为了解决这个问题,我首先想到的是很好使用renice -p 20 <pid>
的过程。然而,我发现这没有多大影响。相反,我必须使用ls /proc/<pid>/task | xargs renice 20 -p --
等具有更大效果的所有子进程进行重命名。
我对此非常困惑,因为我不希望线程拥有自己的进程ID。即使他们这样做,我也希望renice
能够对整个过程采取行动,而不仅仅是过程的主线。
有没有人清楚地了解这里发生了什么?看来每个线程实际上都是一个单独的进程(至少它有一个有效的PID)。我知道历史上Linux的工作方式与此类似,但我相信几年前NPTL已经修复了。
我正在测试RHEL 5.4(linux内核2.6.18)。
(顺便说一句。如果我尝试使用sched_setscheduler(<pid>, SCHED_BATCH, ..)
来尝试解决这个交互性问题,我会注意到同样的效果。也就是说,我需要对我在{{I}中看到的所有“子”进程进行此调用。 {1}},仅在主程序pid上执行一次是不够的。)
答案 0 :(得分:2)
线程ID来自与PID相同的命名空间。这意味着每个线程都可以通过其TID进行单独寻址 - 一些系统调用确实适用于整个过程(例如,kill
),但其他线程仅适用于单个线程。
调度程序系统调用通常在后一类中,因为这允许您在进程中为不同的调度程序属性提供不同的线程,这通常很有用。
答案 1 :(得分:2)
据我所知,Linux线程和进程几乎是一回事;线程恰好是共享相同内存的进程,而不是执行fork的写时复制操作,而fork(2)和pthread_create(3)可能只是分散到clone(2)的调用上。参数。
调度内容非常令人困惑,因为例如pthreads(7)手册页首先告诉你Posix线程共享一个共同的好的值但是你必须得到
NPTL仍然与POSIX.1有一些不一致:线程没有 分享一个共同的好价值
查看整个图片(我确信有很多甚至不太有用的手册页。)
我编写了GUI应用程序,它从主UI线程生成多个计算线程,并且总是发现让应用程序保持高响应性的关键是在计算线程中调用nice(2)(仅限);增加4左右似乎运作良好。
或者至少那是我记住做的事情。我多年来第一次看了代码,看看我实际上做了什么:
// Note that this code relies on Linux NPTL's non-Posix-compliant
// thread-specific nice value (although without a suitable replacement
// per-thread priority mechanism it's just as well it's that way).
// TODO: Should check some error codes,
// but it's probably pretty harmless if it fails.
const int current_priority=getpriority(PRIO_PROCESS,0);
setpriority(PRIO_PROCESS,0,std::min(19u,current_priority+n));
哪个有趣。我可能尝试了很好(2)并发现它确实适用于整个过程(所有线程),这不是我想要的(但也许你这样做)。但这可以追溯到几年前了;从那时起,行为可能已经发生了变化。
当你玩这种东西时,一个必不可少的工具:如果你在top(1)中点击'H'(NB不是'h'),它会从过程视图变为显示所有线程和个人线程很好的价值观例如,如果我运行[evolvotron][7] -t 4 -n 5
(4个计算线程很好5)我看到(我只是在一个旧的单核非HT机器上,所以这里的多个线程实际上并不多):
Tasks: 249 total, 5 running, 244 sleeping, 0 stopped, 0 zombie
Cpu(s): 17.5%us, 6.3%sy, 76.2%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1025264k total, 984316k used, 40948k free, 96136k buffers
Swap: 1646620k total, 0k used, 1646620k free, 388596k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4911 local 25 5 81096 23m 15m R 19.7 2.4 0:04.03 evolvotron
4912 local 25 5 81096 23m 15m R 19.7 2.4 0:04.20 evolvotron
4913 local 25 5 81096 23m 15m R 19.7 2.4 0:04.08 evolvotron
4914 local 25 5 81096 23m 15m R 19.7 2.4 0:04.19 evolvotron
4910 local 20 0 81096 23m 15m S 9.8 2.4 0:05.83 evolvotron
...