我有一个简单的bash脚本,它将一个进程的输出传递给另一个进程。即:
dostuff | filterstuff
碰巧在我的Linux系统上(openSUSE,如果重要,内核2.6.27),这两个进程都在一个核心上运行。但是,在不同的核心上运行不同的进程是一种默认策略,在这种情况下不会触发。
系统的哪个部分负责,以及如何利用多核功能?
注意在2.6.30内核上没有这样的问题。
澄清:按照Dennis Williamson的建议,我使用顶级程序确定,管道进程确实总是在同一个处理器上运行。 Linux调度程序通常做得非常好,这次不会这样做。
我认为bash中的某些内容会阻止操作系统执行此操作。问题是我需要一个用于多核和单核机器的便携式解决方案。 solution提议的taskset
Dennis Williamson无法在单核计算机上运行。目前我正在使用:,
dostuff | taskset -c 0 filterstuff
但这似乎是一个肮脏的黑客。任何人都可以提供更好的解决方案吗?
答案 0 :(得分:7)
尝试设置CPU(处理器)亲和性:
taskset -c 0 dostuff | taskset -c 1 filterstuff
修改强>
尝试此实验:
创建一个名为proctest和chmod +x proctest
的文件,其内容为:
#!/bin/bash
while true
do
ps
sleep 2
done
开始运行:
./proctest | grep bash
ps u
启动top -p
,其中列出了最多几个进程的PID,例如其中的8个,来自屏幕上由退出的top
加上proctest
的列表。由grep
列出的1}}和ps
- 全部用逗号分隔,就像这样(顺序无关紧要):
top -p 1234, 1255, 1211, 1212, 1270, 1275, 1261, 1250, 16521, 16522
.09
并按 Enter 设置短暂的延迟时间proctest
和grep
反弹,有时在同一个处理器上,有时在不同的处理器上答案 1 :(得分:7)
假设dostuff
在一个CPU上运行。它将数据写入管道,并且该数据将位于该CPU的缓存中。因为filterstuff
正在从该管道读取,所以调度程序决定在同一个CPU上运行它,以便其输入数据已经在缓存中。
如果您的内核是使用CONFIG_SCHED_DEBUG=y
构建的,
# echo NO_SYNC_WAKEUPS > /sys/kernel/debug/sched_features
应该禁用此类启发式。 (有关其他调度程序可调参数,请参阅/usr/src/linux/kernel/sched_features.h
和/proc/sys/kernel/sched_*
。)
如果这有帮助,并且问题仍然发生在较新的内核和上,在单独的CPU上运行比单CPU更快,请将问题报告给Linux内核邮件列表以便它们可以调整他们的启发式。
答案 2 :(得分:1)
Linux调度程序旨在提供最大吞吐量,而不是您想象的最佳。如果您正在运行与管道连接的进程,则很可能其中一个阻塞另一个进程,然后它们会进行交换。在不同的核心上运行它们几乎没有任何作用,所以它没有。
如果你有两个真正准备在CPU上运行的任务,我希望看到它们安排在不同的核心上(在某些时候)。
我的猜测是,dostuff会一直运行,直到管道缓冲区变满,此时它不能再运行,所以“filterstuff”进程会运行,但它运行的时间很短,dostuff不会不会重新安排,直到filterstuff完成对整个管道缓冲区的过滤,然后再次调度dostuff。