GNU parallel:从起始目录为整个树的每个节点(目录和子*目录)分配一个线程

GNU parallel: assign one thread for each node (directories and sub* directories) of an entire tree from a start directory

我想受益于 macOS 上 parallel 命令的所有潜力(似乎存在 2 个版本,GNU 和 Ole Tange 的版本,但我不确定)。

使用以下命令:

parallel -j8  find {} ::: *

如果我位于包含8个子目录的目录中,我将有很大的表现。 但是,如果所有这些子目录除了一个之外都有一小部分内容,我将只有一个线程将在唯一的“大”目录上工作。

  1. 有没有办法遵循这个“大目录”的并行化?我的意思是,剩下的唯一线程能否得到其他线程的帮助(前一个线程在小子目录上工作)?

    理想情况是当上面命令行中的 find 命令找到所有小子时,并行命令“自动切换”。可能是我要求太多了?

  2. 另一个潜在的优化(如果存在的话):考虑一个通用的树目录结构:有没有办法,例如类似于命令make -j8,将每个当前线程分配给一个子线程(sub-(sub- ....)))) 目录,一旦浏览了当前目录(别忘了,我主要想通过 find Linux 命令使用此优化) , 另一个线程探索另一个目录 sub-(sub-(sub- ....)))) directory?

    当然,总线程数运行不大于用parallel命令指定的数量(在我上面的例子中是parallel -j8):我们可以说如果一个树元素的数量(1 个节点=1 个目录)大于线程的数量,我们不能超过这个数字。

    我知道在递归上下文中并行化很棘手,但当我想将文件查找到大树结构时,也许我可以获得重要因素?

    这就是我以命令 make -j8 为例的原因:我不知道它是如何编码的,但这让我认为我们可以对一对 parallel/find 命令行做同样的事情我的 post.

    的开始

最后,我想听听您对这两个问题的建议,更一般地说,对于这些优化建议,目前哪些是可能的,哪些是不可能的,以便更快地找到具有经典 find 的文件命令。

更新 1: 正如@OleTange 所说,我不知道我想要 gupdatedb 索引的先验目录结构。所以,很难提前知道maxdepth。您的解决方案很有趣,但是 find 的第一次执行不是多线程的,您不使用 parallel 命令。我有点惊讶 gupdatedb 的多线程版本不存在:在纸面上,它是可行的,但一旦我们想在 MacOS 10.15 的脚本 GNU gupdatedb 中编写它,它就更难了。

如果有人有其他建议,我会采纳!

如果您要并行化find,您需要确保您的磁盘可以传送数据。

对于磁驱动器,您很少会看到加速。有时用于 RAID、网络驱动器和 SSD,而经常用于 NVMe。

并行化 find 的最简单方法是使用 */*:

parallel find ::: */*

*/*/*:

parallel find ::: */*/*

这将在 sub-sub 目录和 sub-sub-子目录中搜索。

他们不会搜索顶级目录,但这可以通过 运行 一个额外的 find 和适当的 -maxdepth.

来完成

以上解决方案假定您对目录结构有所了解,因此它不是通用解决方案。

我从来没有听说过通用的解决方案。这将涉及广度优先搜索,并行启动一些 worker。我可以看到它是如何编程的,但我从未见过它。

如果我要实现它,它会是这样的(轻微测试):

#!/bin/bash

tmp=$(tempfile)
myfind() {
  find "" -mindepth 1 -maxdepth 1
}
export -f myfind
myfind . | tee $tmp
while [ -s $tmp ] ; do
    tmp2=$(tempfile)
    cat $tmp | parallel --lb myfind | tee $tmp2
    mv $tmp2 $tmp
done
rm $tmp

(PS:我有理由相信Ole Tange写的parallel和GNU Parallel是一回事。