Linux 如何在多核上运行用bash管道传输的进程?
我有一个简单的bash脚本,它将一个进程的输出传输到另一个进程。即:Linux 如何在多核上运行用bash管道传输的进程?,linux,bash,process,scheduling,multicore,Linux,Bash,Process,Scheduling,Multicore,我有一个简单的bash脚本,它将一个进程的输出传输到另一个进程。即: dostuff | filterstuff 碰巧在我的Linux系统(openSUSE,如果有必要的话,内核2.6.27)上,这两个进程都在一个内核上运行。但是,在不同的内核上运行不同的进程是默认策略,在这种情况下不会触发 系统的哪个组件对此负责,我应该如何利用多核功能 注意在2.6.30内核上没有这样的问题 澄清:遵循了的建议,我使用top program确保管道进程确实总是在同一个处理器上运行。Linux调度程序通常做得
dostuff | filterstuff
碰巧在我的Linux系统(openSUSE,如果有必要的话,内核2.6.27)上,这两个进程都在一个内核上运行。但是,在不同的内核上运行不同的进程是默认策略,在这种情况下不会触发
系统的哪个组件对此负责,我应该如何利用多核功能
注意在2.6.30内核上没有这样的问题
澄清:遵循了的建议,我使用top program确保管道进程确实总是在同一个处理器上运行。Linux调度程序通常做得很好,但这次不行
我认为bash中的某些东西阻止操作系统这么做。问题是,我需要一个适用于多核和单核机器的便携式解决方案。提出的任务集
在单核机器上不起作用。目前我正在使用:
dostuff | taskset -c 0 filterstuff
但这似乎是一个肮脏的黑客。有谁能提供更好的解决方案吗?请尝试设置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
- 在另一个终端中,启动top-确保它按%CPU排序
- 让它稳定几秒钟,然后退出
- 发出命令
ps u
- 从退出的
留下的屏幕上的列表,加上top
和proctest
的列表开始grep
,其中包含最高几个进程的PID列表,比如其中的8个进程,这些进程由p
列出,所有进程都用逗号分隔,如下所示(顺序无关紧要):ps
- 添加处理器字段-按f键,然后按j键,然后按空格键
- 将排序设置为PID-按Shift+F,然后按a,然后按空格
- 可选:按Shift+H打开螺纹视图
- 可选:按d键并键入
,然后按Enter键设置短延迟时间.09
- 现在,当进程从一个处理器移动到另一个处理器时,您应该会看到
和proctest
来回跳转,有时在同一个处理器上,有时在不同的处理器上grep
- 假设
dostuff
在一个CPU上运行。它将数据写入一个管道,并且该数据将在该CPU上的缓存中。由于filterstuff
正在从该管道读取数据,因此调度程序决定在同一CPU上运行它,以便其输入数据已经在缓存中
如果内核是使用CONFIG\u SCHED\u DEBUG=y构建的
# echo NO_SYNC_WAKEUPS > /sys/kernel/debug/sched_features
#echo无同步唤醒>/sys/kernel/debug/sched\u功能
应该禁用这类启发式。(请参见/usr/src/linux/kernel/sched_features.h
和/proc/sys/kernel/sched*
,了解其他调度程序可调参数。)
如果这有帮助,而且问题仍然发生在较新的内核上,和在不同的CPU上运行比在一个CPU上运行要快,请将问题报告给Linux内核邮件列表,以便他们可以调整启发式。Linux调度程序旨在提供最大吞吐量,而不是按照您想象的最佳方式。如果您正在运行与管道连接的进程,很可能其中一个正在阻塞另一个,然后它们交换。在不同的内核上运行它们只能取得很少的效果,或者什么也得不到,所以事实并非如此
如果您有两个任务都真正准备好在CPU上运行,我希望看到它们被安排在不同的内核上(在某个时候)
我的猜测是,dostuff会一直运行到管道缓冲区满为止,此时它无法再运行,因此“filterstuff”进程会运行,但它运行的时间很短,直到filterstuff完成对整个管道缓冲区的过滤后,dostuff才会重新调度,在这一点上,dostuff会再次被安排。太棒了!它起作用了。但是,嗯,为什么我不能避免手动分配到核心呢?有关更多信息,请参阅man sched_setscheduler
和man cpuset
。Linux在调度方面做得很好。尝试运行top
并按fj添加处理器(P)字段,您将看到不同的进程在不同的CPU上运行。您也可以按top
中的1
(一个)以查看顶部每个CPU的CPU负载。尝试使用top
重复测试几次(不使用任务集
)。当我这样做的时候,有时两个进程在同一个CPU上,有时是不同的。它们总是在同一个CPU上,并且只利用了系统的50%:(试试(dostuff)|(filterstuff)
,看看它们出现在哪个内核上。一个区别(如果有关系的话)是,你在多核系统上,我在多处理器上(每个单核)系统。您为什么要分离这些进程?它们是您编写的程序吗?您能否更改它们以使它们影响调度程序本身?如果它们是串行的(unix管道的性质)Jeremy:是的,它在不同的内核上运行速度快了2-3倍:我在bzcat file.bz2 | gzip>file.gz
上测量了这一点。在最初的情况下,dostuff
执行代价高昂的计算,产生大量的输出,并且filterstuff
动态存档。数据在我的情况下,传输不是瓶颈。你的猜测是错误的。进程的运行方式如下:dostuff
占用了内核60%的CPU时间,filterstuff
占用了剩余的40%。而且它们不会在几分钟的运行时间内被重新调度到不同的内核。公平的说来,这只是一个想法。没有同步唤醒工作。但是,没有内核是2.6.27,而在2.6.30系统上,问题似乎没有出现。我将进一步调查。无法报告
# echo NO_SYNC_WAKEUPS > /sys/kernel/debug/sched_features