tee
将其标准输入转发到指定的每个文件,而pee
执行相同操作,但针对管道。这些程序将其标准输入的每一行发送到指定的每个文件/管道。
但是,我正在寻找一种方法来将标准输入“负载平衡”到不同的管道,因此一行被发送到第一个管道,另一行被发送到第二个管道,等等。如果管道的标准输出也被收集到一个流中,那就太好了。
用例是对逐行工作的 CPU 密集型进程进行简单的并行化。我正在处理sed
一个 14GB 的文件,如果我可以使用多个进程,它可以运行得更快sed
。命令如下:
pv infile | sed 's/something//' > outfile
为了并行化,最好的办法是GNU并行将像这样支持此功能(组成选项--demux-stdin
):
pv infile | parallel -u -j4 --demux-stdin "sed 's/something//'" > outfile
但是,没有这样的选项,并且parallel
总是使用其 stdin 作为其调用的命令的参数,例如xargs
。所以我尝试了这个,但它非常慢,原因很明显:
pv infile | parallel -u -j4 "echo {} | sed 's/something//'" > outfile
我只是想知道是否有其他方法可以做到这一点(除了自己编写代码)。如果有“负载平衡” tee
(我们称之为lee
),我可以这样做:
pv infile | lee >(sed 's/something//' >> outfile) >(sed 's/something//' >> outfile) >(sed 's/something//' >> outfile) >(sed 's/something//' >> outfile)
不太漂亮,所以我绝对更喜欢虚构的parallel
版本,但这也可以。
答案1
我们正在讨论如何在 GNU Parallel 的邮件列表中实现此功能http://lists.gnu.org/archive/html/parallel/2011-01/msg00001.html
欢迎加入:http://lists.gnu.org/mailman/listinfo/parallel
原型现已准备好进行测试:http://lists.gnu.org/archive/html/parallel/2011-01/msg00015.html
答案2
我会考虑用 Perl 来实现Parallel::ForkManager。您可以在脚本中进行行拆分,然后将结果行输入到 Parallel::ForkManager 进程中。使用回调run_on_finish
来收集输出。显然,对于您的 sed 示例,您可以改为在 perl 中执行文本操作,也许可以使用类似任何事件处理并行性。