如何在终端中启动多线程grep?


38

我有一个包含250+个2 GB文件的文件夹。我需要在这些文件中搜索字符串/模式并将结果输出到output文件中。我知道我可以运行以下命令,但是它太慢了!

grep mypattern * > output

我想加快速度。作为Java的程序员,我知道多线程可以用来加快进程。我一直在研究如何以grep“多线程模式” 启动并将输出写入单个output文件。




1
确保搜索大量文件是IO绑定问题的经典示例。因此,使用多个线程将无济于事。
乔纳森·哈特利

Answers:


31

有两个简单的解决方案。基本上,使用xargsparallel

xargs方法:

您可以使用xargs具有find如下:

find . -type f -print0  | xargs -0 -P number_of_processes grep mypattern > output

您将在其中替换number_of_processes为要启动的最大进程数。但是,如果您的性能受到I / O的限制,则不能保证为您带来出色的性能。在这种情况下,您可以尝试启动更多进程来补偿等待I / O所浪费的时间。

此外,通过包含find,您可以指定更高级的选项,而不仅仅是文件模式,例如修改时间等。

如Stéphane的评论所解释的,这种方法的一个可能问题是,如果文件很少,则xargs可能无法为它们启动足够多的进程。一种解决方案是使用该-n选项xargs来指定一次应从管道中获取多少个参数。设置-n1将强制xargs为每个文件启动一个新进程。如果文件很大(例如在该问题的情况下)并且文件数量相对较少,则这可能是理想的行为。但是,如果文件本身很小,则启动新进程的开销可能会破坏并行性的优势,在这种情况下,更大的-n值会更好。因此,该-n选项可能会根据文件大小和数量进行微调。

并行方法:

另一种方法是使用Ole Tange GNU并行工具parallel在此处提供)。这样可以更好地控制并行性,甚至可以分布在多个主机上(例如,如果您的目录是共享的,将是有益的)。使用并行的最简单语法为:

find . -type f | parallel -j+1 grep mypattern

如果该选项-j+1指示并行启动一个进程,而该进程超出了计算机内核的数量(这对I / O受限任务可能会有帮助,您甚至可以尝试增加数量)。

xargs实际保留每个过程的输出顺序并生成连续的输出相比,并行还具有优势。例如,使用xargs,如果进程1生成一条线说p1L1,进程2生成一条线p2L1,进程1生成另一条线p1L2,则输出将是:

p1L1
p2L1
p1L2

parallel输出应为:

p1L1
p1L2
p2L1

这通常比xargs输出有用。


1
您可能想与-n结合使用-P。否则,xargs如果有两个文件,则可能最终不会产生多个进程。
斯特凡Chazelas

1
好吧,-n1将在grep每个文件中启动一个。除非文件很大,而且文件很少,否则您可能要增加一点,因为您将花费一些时间来启动和停止grep进程而不是在文件中进行搜索。
斯特凡Chazelas

9

至少有两种方法可以加快CPU的grep速度:

  • 如果要搜索固定字符串而不是正则表达式,请指定-F标志;

  • 如果您的模式仅是ASCII码,请使用8位语言环境而不是UTF-8,例如LC_ALL=C grep ...

如果您的硬盘成为瓶颈,这些将无济于事。在那种情况下,并行化可能也无济于事。


1
刚刚在man grep“直接调用中看到,因为egrep或fgrep已被弃用,但提供该历史记录是为了允许依赖它们的历史应用程序不经修改地运行。” 不确定这是否真的重要,但与grep -F
iyrin

1
另外,当您说“而不是模式”时,是指正则表达式吗?
iyrin

“仅ASCII”搜索使用的CPU少得多。但是您需要阅读stackoverflow.com/a/11777835/198219
famzah

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.