Распараллеливание цикла while с массивами, считанными из файла в bash
у меня есть цикл while в Bash обрабатывается следующим образом:
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 parallel, однако примеры не ясны о том, как я бы назначил каждую строку массиву, как я делаю здесь.
каким было бы возможное решение (альтернативы GNU параллельная работа)?
3 ответов
от 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
parallel
здесь не обязательно; просто запустите все процессы в фоновом режиме, а затем дождитесь их завершения. Массив также не нужен, так как вы можете дать read
более одной переменной для заполнения:
while IFS=$'\t' read -r f1 f2;
do
myprogram "$f1" "$f2" "${f1}_vs_${f2}.result" &
done < fileinput
wait
это запускает одно задание для пункт в вашем списке, тогда как parallel
можно ограничить количество заданий, выполняемых одновременно. Вы можете сделать то же самое в bash
, но это сложно.
Я хотел бы @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
это ограничивает выполнение при максимальном количестве ядер процессора, присутствующих в системе. Вы можете легко изменить это, заменив $( nproc )
на желаемую сумму.
пока вы должны понять, что это не честное распределение. Таким образом, он не запускает новую нить сразу после завершения. Вместо этого просто дождитесь окончания всего, после начала максимальной суммы. Так суммарная пропускная способность может быть немного меньше, чем при параллельной. Особенно, если время работы вашей программы может варьироваться в большом диапазоне. Если время, затраченное на каждый вызов, почти одинаковое, то суммарное время также должно быть примерно эквивалентно.