我的理解是 -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
Run Code Online (Sandbox Code Playgroud)
有趣的是,仅使用文件的子集会导致参数均匀分布:
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
Run Code Online (Sandbox Code Playgroud)
为什么第一种情况是错误的,我该如何修复它?
-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
Run Code Online (Sandbox Code Playgroud)
它不能在每个作业后输出,但可以进行行缓冲输出:
ls *.jpg |
parallel --lb --round --pipe -N1 parallel --lb -Xj1 count
Run Code Online (Sandbox Code Playgroud)
如果文件名包含\n:
printf '%s\0' *.jpg |
parallel --recend '\0' --round --lb --pipe -N1 parallel -0Xj1 count
Run Code Online (Sandbox Code Playgroud)