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个子目录的目录中,我将有很大的表现。
但是,如果所有这些子目录除了一个之外都有一小部分内容,我将只有一个线程将在唯一的“大”目录上工作。
有没有办法遵循这个“大目录”的并行化?我的意思是,剩下的唯一线程能否得到其他线程的帮助(前一个线程在小子目录上工作)?
理想情况是当上面命令行中的 find
命令找到所有小子时,并行命令“自动切换”。可能是我要求太多了?
另一个潜在的优化(如果存在的话):考虑一个通用的树目录结构:有没有办法,例如类似于命令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是一回事。
我想受益于 macOS 上 parallel
命令的所有潜力(似乎存在 2 个版本,GNU 和 Ole Tange 的版本,但我不确定)。
使用以下命令:
parallel -j8 find {} ::: *
如果我位于包含8个子目录的目录中,我将有很大的表现。 但是,如果所有这些子目录除了一个之外都有一小部分内容,我将只有一个线程将在唯一的“大”目录上工作。
有没有办法遵循这个“大目录”的并行化?我的意思是,剩下的唯一线程能否得到其他线程的帮助(前一个线程在小子目录上工作)?
理想情况是当上面命令行中的
find
命令找到所有小子时,并行命令“自动切换”。可能是我要求太多了?另一个潜在的优化(如果存在的话):考虑一个通用的树目录结构:有没有办法,例如类似于命令
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是一回事。