GNU parallel 不能均匀划分工作

GNU parallel 不能均匀划分工作

我的理解是 -X 选项应该在作业之间均匀分配参数。然而,我得到的分布非常不均匀:

user@host:/tmp/ptest$ count() {
>   echo $#
> }
user@host:/tmp/ptest$ export -f count

user@host:/tmp/ptest$ count *.jpg
5825
user@host:/tmp/ptest$ parallel -X count ::: *.jpg
5039
197
197
197
195

有趣的是,仅使用文件的子集会导致参数均匀分布:

user@host:/tmp/ptest$ count p129*.jpg
975
user@host:/tmp/ptest$ parallel -X count ::: p129*.jpg
244
244
244
243

user@host:/tmp/ptest$ count p12*.jpg
4007
user@host:/tmp/ptest$ parallel -X count ::: p12*.jpg
1002
1002
1002
1001

user@host:/tmp/ptest$ count p13*.jpg
1818
user@host:/tmp/ptest$ parallel -X count ::: p13*.jpg
455
455
455
453

为什么第一种情况是错误的以及我该如何修复它?

答案1

-X当到达 EOF 时均匀分布。

因此,在您的情况下,它会填满一个完整命令行的缓冲区(5039 个名称)并启动它。然后它会读取另外 800 个名称,直到到达 EOF。这不足以启动一个完整的作业,因此这些名称会分布在作业槽中。

参见第 37 页https://zenodo.org/record/1146014

这样做是为了避免必须提前阅读所有工作,因为并非所有工作都可用(想想tail -f file.names | parallel ...)。

如果 GNU Parallel 在开始下一个作业之前读取足够多的名称以填满所有作业槽-X,那么它可能是一个更好的主意,这样它就可以更早地检测到 EOF。然而,这尚未实现。欢迎补丁。

解决方法是使用:

ls *.jpg |
  parallel --round --pipe -N1 parallel -Xj1 count

它不能在每次作业后输出,但可以进行行缓冲输出:

ls *.jpg |
  parallel --lb --round --pipe -N1 parallel --lb -Xj1 count

如果文件名包含\n:

printf '%s\0' *.jpg |
  parallel --recend '\0' --round --lb --pipe -N1 parallel -0Xj1 count

相关内容