用并行处理找到更好的unix?


43

unix find(1)实用程序非常有用,它使我可以对符合某些规范的许多文件执行操作,例如

find /dump -type f -name '*.xml' -exec java -jar ProcessFile.jar {} \;

上面的代码可能在特定目录中的每个XML文件上运行脚本或工具。

假设我的脚本/程序占用大量CPU时间,并且我有8个处理器。一次最多处理8个文件会很好。

GNU make允许带有-j标志的并行作业处理,但find似乎不具有这种功能。是否有替代的通用工作计划方法来解决这个问题?

Answers:


65

xargs-P选项(进程数)。假设我想将所有日志文件压缩到4-cpu机器上的目录中:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2

您也可以说-n <number>每个流程的最大工作单元数。所以说我有2500个文件,然后我说:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -n 500 -P 4 bzip2

这将启动4个bzip2进程,每个进程包含500个文件,然后当第一个进程完成时,将为最后500个文件启动另一个进程。

不知道为什么前面的答案使用xargs make,您在那里有两个并行引擎!


7
使用find / xargs时要小心:find默认将换行符作为输出定界符,而xargs默认将任何空格用作输入定界符。为安全起见,请在两者上都使用-0,或切换到默认为换行符的GNU并行作为输入分隔符(匹配find的输出)。
短暂

1
哇,太神奇了!我刚刚检查了,的确如此,xargs可以-P选择!
PP。

当心使用xargs -P-它有一个永远不会修正的错误:parallel无论何时有2个线程恰巧在同一时刻产生输出,都会使输出(不同于)
Vlad

34

GNU parallel也可以提供帮助。

find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}

请注意,不带-j8参数,parallel默认为计算机上的内核数:-)


6

无需“修复” find-利用make自身来处理并行性。

让您的进程创建一个日志文件或其他一些输出文件,然后使用如下所示的Makefile:

.SUFFIXES:  .xml .out

.xml.out:
        java -jar ProcessFile.jar $< 1> $@

并因此被调用:

find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8

更好的是,如果确保仅在Java进程成功完成后才创建输出文件,则可以利用make的依赖项处理来确保下次仅处理未处理的文件。


1
希望这些文件名中没有空格或其他“有趣的”字符;Make不能很好地处理这些问题。
短暂

好主意!从来没有想过使用这样的makefile。
oscfri

3

查找具有并行选项,您可以使用“ +”符号直接使用;不需要xargs。将其与grep结合使用,可以迅速遍历您的树以寻找匹配项。例如,如果我正在源目录中查找包含字符串“ foo”的所有文件,则可以调用
find sources -type f -exec grep -H foo {} +


12
阅读查找手册,您会发现该-exec command +语法不是并行运行的,而是将许多文件“分组”在一起并同时运行以多个文件作为参数的命令。碰巧grep可以并行查看其目标。
Gyscos
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.