我有一个简单的bash脚本,它将一个进程的输出传递给另一个进程。即:。
dostuff | filterstuff
碰巧在我的Linux系统上(openSUSE,如果它很重要,内核2.6.27),这两个进程都在一个核心上运行。但是,跑步不同 流程 在不同的核心上是默认策略,在这种情况下不会触发。
系统的哪个部分负责这个以及我应该怎样做才能利用多核功能?
注意 在2.6.30内核上没有这样的问题。
澄清:跟着 丹尼斯威廉姆森我的建议,我做了 当然 顶级程序,管道进程确实如此 总是 在同一处理器上运行。 Linux调度程序,通常做得非常好,这次不做。
我认为bash中的某些内容会阻止操作系统执行此操作。问题是我需要一个 手提 多核和单核机器的解决方案。该 taskset
解 由...提出 丹尼斯威廉姆森 不适用于单核机器。目前我正在使用:,
dostuff | taskset -c 0 filterstuff
但这似乎是一个肮脏的黑客。谁能提供更好的解决方案?
假设 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内核邮件列表,以便他们可以调整他们的启发式。
尝试设置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
- 在另一个终端,开始顶部 - 确保它按%CPU排序
- 让它稳定几秒钟,然后退出
- 发出命令
ps u
开始 top -p
从退出的屏幕上留下的列表中列出最高几个进程的PID,例如其中的8个 top
加上那些 proctest
和 grep
被列出的 ps
- 所有以逗号分隔,如此(顺序无关紧要):
top -p 1234, 1255, 1211, 1212, 1270, 1275, 1261, 1250, 16521, 16522
- 添加处理器字段 - 按 F 然后 Ĵ 然后 空间
- 将排序设置为PID - 按 转移+F 然后 一个 然后 空间
- 可选:按 转移+H 打开线程视图
- 可选:按 d 和类型
.09
并按 输入 设置一个短的延迟时间
- 现在看着流程从处理器移动到处理器,你应该看到
proctest
和 grep
弹跳,有时在同一个处理器上,有时在不同的处理器上
Linux调度程序旨在提供最大吞吐量,而不是您想象的最佳。如果您正在运行与管道连接的进程,很可能其中一个阻塞另一个进程,那么它们会进行交换。在不同的核心上运行它们将获得很少或没有,所以它没有。
如果你有两个真正准备在CPU上运行的任务,我希望看到它们安排在不同的核心上(在某些时候)。
我的猜测是,发生的是dostuff运行直到管道缓冲区变满,此时它不再运行,所以“filterstuff”进程运行,但它运行的时间很短,dostuff没有得到重新安排,直到filterstuff完成过滤整个管道缓冲区,然后再次调度dostuff。