如何在多个核心上运行使用bash传输的进程?

时间:2009-09-09 09:39:23

标签: linux bash process scheduling multicore

我有一个简单的bash脚本,它将一个进程的输出传递给另一个进程。即:

dostuff | filterstuff

碰巧在我的Linux系统上(openSUSE,如果重要,内核2.6.27),这两个进程都在一个核心上运行。但是,在不同的核心上运行不同的进程是一种默认策略,在这种情况下不会触发。

系统的哪个部分负责,以及如何利用多核功能?

注意在2.6.30内核上没有这样的问题。

澄清:按照Dennis Williamson的建议,我使用顶级程序确定,管道进程确实总是在同一个处理器上运行。 Linux调度程序通常做得非常好,这次不会这样做。

我认为bash中的某些内容会阻止操作系统执行此操作。问题是我需要一个用于多核和单核机器的便携式解决方案。 solution提议的taskset Dennis Williamson无法在单核计算机上运行。目前我正在使用:,

dostuff | taskset -c 0 filterstuff 

但这似乎是一个肮脏的黑客。任何人都可以提供更好的解决方案吗?

3 个答案:

答案 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
    
  • 在另一个终端中,从顶部开始 - 确保按%CPU排序
  • 让它稳定几秒钟,然后退出
  • 发出命令ps u
  • 启动top -p,其中列出了最多几个进程的PID,例如其中的8个,来自屏幕上由退出的top加上proctest的列表。由grep列出的1}}和ps - 全部用逗号分隔,就像这样(顺序无关紧要):

    top -p 1234, 1255, 1211, 1212, 1270, 1275, 1261, 1250, 16521, 16522
    
  • 添加处理器字段 - 按 f 然后 j 然后 Space
  • 将排序设置为PID - 按 Shift + F 然后 a 然后空间
  • 可选:按 Shift + H 打开线程视图
  • 可选:按 d 并输入.09并按 Enter 设置短暂的延迟时间
  • 现在看着流程从处理器移动到处理器,您应该看到proctestgrep反弹,有时在同一个处理器上,有时在不同的处理器上

答案 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。