13

我在 Bash 中有一个 while 循环,处理方式如下:

while IFS=$'\t' read -r -a line;
do
    myprogram ${line[0]} ${line[1]} ${line[0]}_vs_${line[1]}.result;
done < fileinput

它从具有此结构的文件中读取,以供参考:

foo   bar
baz   foobar

依此类推(制表符分隔)。

我想使用 GNU 并行并行化这个循环(因为条目很多并且处理可能很慢),但是这些示例不清楚我将如何将每一行分配给数组,就像我在这里所做的那样。

什么是可能的解决方案(GNU 并行工作的替代方案)?

4

3 回答 3

9

From https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Use-a-table-as-input:

"""
Content of table_file.tsv:

foo<TAB>bar
baz <TAB> quux

To run:

cmd -o bar -i foo
cmd -o quux -i baz

you can run:

parallel -a table_file.tsv --colsep '\t' cmd -o {2} -i {1}

"""

So in your case it will be:

cat fileinput | parallel --colsep '\t' myprogram {1} {2} {1}_vs_{2}.result
于 2013-05-16T16:26:55.910 回答
9

我想要@chepner hack。通过限制并行执行的数量来完成类似的行为似乎并不那么棘手:

while IFS=$'\t' read -r f1 f2;
do
    myprogram "$f1" "$f2" "${f1}_vs_${f2}.result" &

    # At most as number of CPU cores
    [ $( jobs | wc -l ) -ge $( nproc ) ] && wait
done < fileinput

wait

它限制了系统上存在的最大 CPU 内核数的执行。您可以很容易地通过替换$( nproc )所需的数量来改变它。

同时你应该明白什么是不诚实的分配。因此,它不会在一个完成后立即启动新线程。相反,它只是等待完成所有,在开始最大数量之后。因此汇总吞吐量可能略低于并行。特别是如果您的程序的运行时间可能在很大范围内变化。如果每次调用所花费的时间几乎相同,那么摘要时间也应该大致相等。

于 2015-10-10T20:23:45.803 回答
6

parallel这里不是绝对必要的;只需在后台启动所有进程,然后等待它们完成。该数组也是不必要的,因为您可以提供read多个变量来填充:

while IFS=$'\t' read -r f1 f2;
do
    myprogram "$f1" "$f2" "${f1}_vs_${f2}.result" &
done < fileinput
wait

这确实会为列表中的每个项目启动一个作业,而parallel可以限制一次运行的作业数量。您可以在 中完成相同的操作bash,但这很棘手。

于 2013-05-16T18:18:12.743 回答