并行化一个while循环,数组从bash中的文件读取

时间:2013-05-16 15:15:10

标签: bash parallel-processing gnu-parallel

我在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并行来并行化这个循环(因为条目很多并且处理速度很慢),但是我不知道如何将每一行分配给数组,就像我在这里一样。 / p>

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

3 个答案:

答案 0 :(得分:9)

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

“”“
table_file.tsv的内容:

foo<TAB>bar
baz <TAB> quux

运行:

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

你可以跑:

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

“”“

所以在你的情况下它将是:

cat fileinput | parallel --colsep '\t' myprogram {1} {2} {1}_vs_{2}.result

答案 1 :(得分:5)

我想要@chepner黑客。 并且通过限制并行执行次数似乎没有那么棘手的完成类似的行为:

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 )替换为所需金额来轻松改变它。

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

答案 2 :(得分:3)

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

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

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