我试图将进程限制为给定数量的 CPU 核心。根据任务集手册页和本文档,以下应该有效:
[fedora@dfarrell-opendaylight-cbench-devel ~]$ taskset -pc 0 <PID>
pid 24395's current affinity list: 0-3
pid 24395's new affinity list: 0
简单地说——这是行不通的。将进程置于负载下并观察top
,它的 CPU 使用率约为 350%(与没有任务集时相同)。它应该最大为 100%。
我可以在taskset -c 0 <cmd to start process>
进程生成时正确设置亲和力。cpulimit -p <PID> -l 99
还使用有点作品。在这两种情况下,将进程置于相同的负载下会导致 CPU 使用率达到 100%。
这里出了什么问题?
答案1
更新:较新版本的任务集有一个-a
/--all-tasks
选项,“对给定 pid 的所有任务(线程)进行操作”,并且应该解决我下面显示的行为。
我编写了一个 Python 脚本,它只是启动一些线程并消耗 CPU 周期。这个想法是针对它测试任务集,因为它非常简单。
#!/usr/bin/env python
import threading
def cycle_burner():
while True:
meh = 84908230489 % 323422
for i in range(3):
thread = threading.Thread(target=cycle_burner)
print "Starting a thread"
thread.start()
仅运行 Python 脚本就消耗了大约 150% 的 CPU 使用率。
[~/cbench]$ ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread
使用任务集启动我的 Python 脚本可以按预期工作。查看 top 显示 Python 进程的使用率为 100%。
[~/cbench]$ taskset -c 0 ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread
有趣的是,启动 Python 脚本,然后立即使用任务集设置刚刚启动的进程的亲和力会将进程限制为 100%。从输出中请注意,Linux 调度程序在生成 Python 线程之前完成了 Bash 命令的执行。因此,Python 进程启动,然后将其设置为在 CPU 0 上运行,然后生成其线程,该线程继承了正确的关联性。
[~/cbench]$ ./burn_cycles.py &; taskset -pc 0 `pgrep python`
[1] 8561
pid 8561's current affinity list: 0-3
pid 8561's new affinity list: 0
Starting a thread
[~/cbench]$ Starting a thread
Starting a thread
该结果与此方法形成对比,后者完全相同,但允许在设置 Python 进程的关联性之前生成 Python 线程。这复制了我上面描述的“任务集不执行任何操作”结果。
[~/cbench]$ ./burn_cycles.py &
[1] 8996
[~/cbench]$ Starting a thread
Starting a thread
Starting a thread
[~/cbench]$ taskset -pc 0 `pgrep python`
pid 8996's current affinity list: 0-3
pid 8996's new affinity list: 0
这里出了什么问题?
显然,在父进程的亲和力更改之前生成的线程不会继承其父进程的亲和力。如果有人可以编辑解释这一点的文档链接,那将会很有帮助。
答案2
我认为您需要每个线程调用一次任务集,即使用ps -eL
而不是pgrep
并将其通过管道传递给taskset -cp 0
ps -eLo cmd,tid | grep python | perl -pe 's/.* (\d+)$/\1/' | xargs -n 1 taskset -cp 0
这会调用所有线程 ID 的任务集。
答案3
尝试数字用--physcpubind
(或-C
) 代替。手册页说:
...该政策是为命令而制定的,并由其所有子项继承。
(在最近的版本中taskset
还有一个-a
选项,Sets or retrieves the CPU affinity of all the tasks (threads) for a given PID.
但不清楚这是否也适用于启动的任务的子进程,taskset
而不是修改已经运行的进程)
答案4
我成功地使用了taskset
的-a
选项。我有一个名为 videoconverterd 的服务器,它消耗大量 CPU;top
节目
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8991 root 20 0 1299472 346724 47380 S 385.7 4.3 42:41.37 videoconverterd
运行后taskset -apc 0 8991
,CPU负载下降至
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8991 root 20 0 1221832 293344 47380 S 99.7 3.7 49:13.28 videoconverterd
我运行的是 CentOS 7,taskset
版本为 2.23.2。