2013-05-07 7 views
8

Я оцениваю, если GNU Parallel может использоваться для поиска файлов, хранящихся в системе, параллельно. В каждый день года может быть только один файл (doy) (так что максимум 366 файлов в год). Допустим, в системе имеется 3660 файлов (около 10 лет). Системой может быть многопроцессорный многоядерный Linux или многопроцессорный Solaris.Как подать большой массив команд GNU Parallel?

Я сохраняю команды поиска для работы с файлами в массиве (по одной команде для каждого файла). И это то, что я делаю прямо сейчас (используя Баш), но тогда я не имею никакого контроля на сколько поисков, чтобы начать параллельно (определенно не хочу, чтобы начать все 3660 поисков сразу):

#!/usr/bin/env bash 
declare -a cmds 
declare -i cmd_ctr=0 

while [[ <condition> ]]; do 
    if [[ -s $cur_archive_path/log.${doy_ctr} ]]; then 
     cmds[$cmd_ctr]="<cmd_to_run>" 
     let cmd_ctr++ 
    fi 
done 

declare -i arr_len=${#cmds[@]} 
for ((i=0; i<${arr_len}; i++)); 
do 
    # Get the command and run it in background 
    eval ${cmds[$i]} & 
done 
wait 

Если бы я использовал parallel (который автоматически определит максимальные ЦП/ядра и начнет только так много поисков параллельно), как я могу повторно использовать массив cmds с параллельным и переписать вышеприведенный код? Другой альтернативой является запись всех команд в файл, а затем сделать cat cmd_file | parallel

+0

Чтобы быть педантичным, в моей вселенной 10 лет не могут дать 3660 файлов, так как не может быть 10 последовательных високосных годов. Но так как вы написали «о», я полагаю, вы знаете это и не смотрите в меня из параллельной вселенной (что меня немного огорчает) ;-) –

+0

@Adrian Вы правы; Я добавил 'about' для учета високосных лет :) –

ответ

6

https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Using-shell-variables говорит:

parallel echo ::: "${V[@]}" 

Вы не хотите эхо, так:

parallel ::: "${cmds[@]}" 

Если вам не нужны $ cmds для чего-либо еще, затем используйте «sem» (который является псевдонимом для параллельного файла -emap) https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-mutex-and-counting-semaphore

while [[ <condition> ]]; do 
    if [[ -s $cur_archive_path/log.${doy_ctr} ]]; then 
    sem -j+0 <cmd_to_run> 
    fi 
done 
sem --wait 

Вы не описали, что может быть < состояние. Если вы просто делаете что-то вроде для петли можно заменить весь сценарий с:

parallel 'if [ -s {} ] ; then cmd_to_run {}; fi' ::: $cur_archive_path/log.{1..3660} 

(на основе https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Composed-commands).

+0

Спасибо за все советы. Но у меня есть ощущение, что оболочка взорвется, если «$ {cmds [@]}» расширяется в строке, особенно если в массиве cmds есть 1000 элементов/команд в нем? Думаете, безопаснее кормить команды из файла? –

+0

Кроме того, когда '$ {cmds [@]}' расширяется, что является разделителем между несколькими командами (мне нужно использовать ';' в конце каждой команды)? Как это отличается от 'cat cmd_file | parallel ', где я предполагаю, что новый символ линии считается разделителем команд? –

+0

Я могу запустить командные строки 130 КБ, поэтому, если ваша команда <130 символов, вы должны быть в безопасности. Но лично я просто просто собирал команды параллельно (таким образом, избегая как ограничения оболочки, так и временного файла) или позволяя параллельным генерировать команды. –