如何在多核上运行通过 bash 管道传输的进程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1398588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 21:11:28  来源:igfitidea点击:

How to run processes piped with bash on multiple cores?

linuxbashprocessschedulingmulticore

提问by P Shved

I have a simple bash script that pipes output of one process to another. Namely:.

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

dostuff | filterstuff

It happens that on my Linux system (openSUSE if it matters, kernel 2.6.27) these both processes run on a single core. However, running different processeson different cores is a default policy that doesn't happen to trigger in this case.

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

What component of the system is responsible for that and what should I do to utilize multicore feature?

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

Notethat there's no such problem on 2.6.30 kernel.

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

Clarification: Having followed Dennis Williamson's advice, I made surewith top program, that piped processes are indeed alwaysrun on the same processor. Linux scheduler, which usually does a really good job, this time doesn't do it.

澄清:按照丹尼斯威廉姆森的建议,我确定了顶级程序,管道进程确实总是在同一个处理器上运行。Linux 调度程序,它通常做得非常好,但这次没有这样做。

I figure that something in bash prevents OS from doing it. The thing is that I need a portablesolution for both multi-core and single-core machines. The tasksetsolutionproposed by Dennis Williamsonwon't work on single-core machines. Currently I'm using:,

我认为 bash 中的某些东西阻止了操作系统这样做。问题是我需要一个适用于多核和单核机器的便携式解决方案。Dennis Williamson提出的taskset解决方案不适用于单核机器。目前我正在使用:,

dostuff | taskset -c 0 filterstuff 

but this seems like a dirty hack. Could anyone provide a better solution?

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

采纳答案by ephemient

Suppose dostuffis running on one CPU. It writes data into a pipe, and that data will be in cache on that CPU. Because filterstuffis reading from that pipe, the scheduler decides to run it on the same CPU, so that its input data is already in cache.

假设dostuff在一个 CPU 上运行。它将数据写入管道,该数据将在该 CPU 的缓存中。因为filterstuff是从那个管道读取,调度器决定在同一个 CPU 上运行它,所以它的输入数据已经在缓存中。

If your kernel is built with CONFIG_SCHED_DEBUG=y,

如果您的内核是用CONFIG_SCHED_DEBUG=y,

# echo NO_SYNC_WAKEUPS > /sys/kernel/debug/sched_features

should disable this class of heuristics. (See /usr/src/linux/kernel/sched_features.hand /proc/sys/kernel/sched_*for other scheduler tunables.)

应该禁用此类启发式。(有关其他调度程序可调参数,请参阅/usr/src/linux/kernel/sched_features.h/proc/sys/kernel/sched_*。)

If that helps, and the problem still happens with a newer kernel, andit's really faster to run on separate CPUs than one CPU, please report the problem to the Linux Kernel Mailing List so that they can adjust their heuristics.

如果这有帮助,并且问题仍然发生在较新的内核上,并且在单独的 CPU 上运行确实比在一个 CPU 上运行快,请将问题报告给 Linux 内核邮件列表,以便他们可以调整他们的启发式方法。

回答by Paused until further notice.

Give this a try to set the CPU (processor) affinity:

尝试设置 CPU(处理器)亲和性:

taskset -c 0 dostuff | taskset -c 1 filterstuff

Edit:

编辑:

Try this experiment:

试试这个实验:

  • create a file called proctest and chmod +x proctestwith this as the contents:

    #!/bin/bash
    while true
    do
      ps
      sleep 2
    done  
    
  • start this running:

    ./proctest | grep bash
    
  • in another terminal, start top - make sure it's sorting by %CPU
  • let it settle for several seconds, then quit
  • issue the command ps u
  • start top -pwith a list of the PIDs of the highest several processes, say 8 of them, from the list left on-screen by the exited topplus the ones for proctestand grepwhich were listed by ps- all separated by commas, like so (the order doesn't matter):

    top -p 1234, 1255, 1211, 1212, 1270, 1275, 1261, 1250, 16521, 16522
    
  • add the processor field - press fthen jthen Space
  • set the sort to PID - press Shift+Fthen athen Space
  • optional: press Shift+Hto turn on thread view
  • optional: press dand type .09and press Enterto set a short delay time
  • now watch as processes move from processor to processor, you should see proctestand grepbounce around, sometimes on the same processor, sometimes on different ones
  • 创建一个名为 proctest 的文件,并将chmod +x proctest其作为内容:

    #!/bin/bash
    while true
    do
      ps
      sleep 2
    done  
    
  • 开始运行:

    ./proctest | grep bash
    
  • 在另一个终端中,从顶部开始 - 确保它按 %CPU 排序
  • 让它稳定几秒钟,然后退出
  • 发出命令 ps u
  • top -p最高的几个进程的 PID 列表开始,比如其中的 8 个,从退出屏幕上留下的列表top加上列出的那些proctestgrepps- 全部用逗号分隔,像这样(顺序不没关系):

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

回答by MarkR

The Linux scheduler is designed to give maximum throughput, not do what you imagine is best. If you're running processes which are connected with a pipe, in all likelihood, one of them is blocking the other, then they swap over. Running them on separate cores would achieve little or nothing, so it doesn't.

Linux 调度程序旨在提供最大吞吐量,而不是做您认为最好的事情。如果您正在运行与管道连接的进程,则很可能其中一个正在阻塞另一个,然后它们会交换。在单独的内核上运行它们将实现很少或没有实现,所以它不会。

If you have two tasks which are both genuinely ready to run on the CPU, I'd expect to see them scheduled on different cores (at some point).

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

My guess is, what happens is that dostuff runs until the pipe buffer becomes full, at which point it can't run any more, so the "filterstuff" process runs, but it runs for such a short time that dostuff doesn't get rescheduled until filterstuff has finished filtering the entire pipe buffer, at which point dostuff then gets scheduled again.

我的猜测是,会发生什么事情是 dostuff 运行直到管道缓冲区变满,此时它不能再运行了,所以“filterstuff”进程运行,但它运行的时间很短,dostuff 没有得到重新调度,直到 filterstuff 完成对整个管道缓冲区的过滤,然后再次调度 dostuff。