【问题标题】:How to run processes piped with bash on multiple cores?如何在多个核心上运行使用 bash 管道传输的进程?
【发布时间】:2010-11-26 18:46:47
【问题描述】:

我有一个简单的 bash 脚本,可以将一个进程的输出通过管道传输到另一个进程。即:。

dostuff | filterstuff

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

系统的哪个组件对此负责,我应该怎么做才能利用多核功能?

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

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

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

dostuff | taskset -c 0 filterstuff 

但这似乎是一个肮脏的黑客。谁能提供更好的解决方案?

【问题讨论】:

  • 尝试多次使用top 重复您的测试(不使用taskset)。当我这样做时,有时这两个进程在同一个 CPU 上,有时在不同的 CPU 上。
  • 它们总是在同一个上,只使用了 50% 的系统 :(
  • 试试( dostuff ) | ( filterstuff ) 看看他们出现在哪个内核上。一个区别(如果重要的话)是您使用的是多核系统,而我使用的是多处理器(每个单核)系统。你为什么要分离这些进程呢?它们是您编写的程序吗?您可以更改它们以影响调度程序本身吗?
  • 如果它们是串行的(unix 管道的性质),如果它们位于不同的内核上,您真的会获得性能提升吗?
  • @Jeremy:是的,它在不同内核上的运行速度提高了 2-3 倍:我在 bzcat file.bz2 | gzip >file.gz 上测量了这个。在原始情况下,dostuff 执行昂贵的计算并产生大量输出,filterstuff 将其即时存档。就我而言,数据传输不是瓶颈。

标签: linux bash process scheduling multicore


【解决方案1】:

尝试设置 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加上proctestgrep留下的列表由ps 列出 - 全部用逗号分隔,就像这样(顺序无关紧要):

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

【讨论】:

  • 太棒了!有用。但是,嗯,为什么我不能避免手动分配给核心?
  • 请参阅man sched_setschedulerman cpuset 了解更多信息。 Linux 在调度方面做得很好。尝试运行 top 并按 fj 添加处理器 (P) 字段,您会看到不同的进程在不同的 CPU 上运行。
  • 您也可以在top 中按1(一)在顶部分别查看每个CPU 的CPU 负载。
【解决方案2】:

假设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 内核邮件列表,以便他们可以调整他们的启发式。

【讨论】:

  • NO_SYNC_WAKEUPS 工作。但是,内核是 2.6.27,而在 2.6.30 系统上似乎没有出现问题。我会进一步调查。
  • 无法在 2.6.30 上重现它。进程在有和没有 SYNC_WAKEUPS 的情况下在内核之间反弹。
  • 好的,我知道了,这解决了问题。由于我的产品没有很多用户,并且他们的内核编译得很好,我可以要求他们按照您提供的方式调整它们。谢谢。
【解决方案3】:

Linux 调度程序旨在提供最大吞吐量,而不是按照您的想象去做。如果您正在运行与管道连接的进程,则很可能其中一个正在阻塞另一个,然后它们会交换。在单独的内核上运行它们几乎没有或什么也没有,所以它不会。

如果您有两个真正准备好在 CPU 上运行的任务,我希望看到它们被安排在不同的内核上(在某个时候)。

我的猜测是,dostuff 会一直运行,直到管道缓冲区变满,此时它不能再运行,所以“filterstuff”进程运行,但它运行的时间很短,以至于 dostuff 没有'直到 filterstuff 完成对整个管道缓冲区的过滤后才会重新安排,此时 dostuff 会再次安排。

【讨论】:

  • 你的猜测是错误的。进程运行如下:dostuff 占用内核 CPU 时间的 60%,filterstuff 占用剩余的 40%。而且它们不会在运行几分钟后重新安排到不同的核心。
  • 那么公平,只是一个想法。
猜你喜欢
  • 2011-04-11
  • 1970-01-01
  • 2017-01-17
  • 2015-01-07
  • 2019-07-30
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多