Параллелизация для цикла

При вызове без любых опций, column делает каждый разграничил строки, выравниваются к ближайшему СТОЛБЦУ ПОЗИЦИИ ТАБУЛЯЦИИ. В терминале, который обычно находится на каждом 8-м символьном столбце.. Взгляните на этот пример:

Создайте файл (ztxt) содержа некоторый символ табуляции \t разграниченные строки, распространенные по 3 строкам, которые заканчиваются символом новой строки \n:

aaa1\taaaaaaaaaaaaaa2\taaaaaaaaaaaaaaaaaaa3\taaa4
bbbbbbb1\tbbb2\tbbb3
ccc1\tccc2

Вывод: column ztxt - отлично выровненный к ближайшей ПОЗИЦИИ ТАБУЛЯЦИИ

aaa1    aaaaaaaaaaaaaa2 aaaaaaaaaaaaaaaaaaa3    aaa4
bbbbbb1 bbb2    bbb3
ccc1    ccc2
|       |       |       |       |       |       |
|-------|-------|-------|-------|-------|-------|

Для выравнивания LSH каждого последовательного поля к тому выше его необходимо использовать -t опция, например. column -t ztxt

aaa1     aaaaaaaaaaaaaa2  aaaaaaaaaaaaaaaaaaa3  aaa4
bbbbbb1  bbb2             bbb3
ccc1     ccc2

Если все Ваши данные находятся в одном длинном потоке без каких-либо повреждений новой строки, Вы можете uss фильтр представлять их; например, каждые 4 поля. sed может сделать это с этой командой.

sed -re 's/(([^\t]*\t){3}[^\t]*)\t/\1\n/g' 

По умолчанию, column команда объединит несколько смежных разделителей в единственный разделитель.. Обслуживать это в sed фильтр, этому также нужно:

sed -re 's/\t+/\t/g;' 

Так команда для разделения непрерывного потока разграниченных вкладкой строк, как каждая 4-я строка:

<ztxt sed -re 's/\t+/\t/g;s/(([^\t]*\t){3}[^\t]*)\t/\1\n/g' | column -t  

Вывод такого входного потока contionuous (использование исходного демонстрационного входа, но измененный путем замены исходных новых строк символами табуляции - это должно все еще сохранить свое запаздывание \n):

aaa1      aaaaaaaaaaaaaa2  aaaaaaaaaaaaaaaaaaa3  aaa4
bbbbbbb1  bbb2             bbb3                  ccc1
ccc2
9
25.09.2017, 14:04
2 ответа
#!/bin/bash
# set -x # debug version
N=${1:-123}
n=${2:-45}
workers=${workers:-${3:-10}}
((workers < 1)) && ((workers = 1))
((workers > 20)) && ((workers = 20))

((min=100000000000000))  #set min to some garbage value

work() {
  for i in ${*}; do
    for (( j=1; j<=${n}; j++ )); do
      val=$(/path/to/a.out)
      val2=$(echo ${val} | bc)
      (( val2 < min )) && (( min = val2 ));
    done
    echo ${min}
    # # debug version
    # echo ${i} ${j} ${min}
  done
}

# --
arr=($(
  seq ${N} | xargs -n$[N/workers + 1] | while read i; do
    work ${i} &
  done
  wait
))
echo ${arr[*]}
# --

# # debug version
# seq ${N} | xargs -t -n$[N/workers + 1] | while read i; do
#  work ${i} &
# done
# wait

Всегда используйте рабочих при порождении параметризованных чисел процессов и ограничьте максимальное количество рабочих, которые могут метать икру.

xargs -n | while read простое средство итерации списков в пакетах.

  • seq создает список чисел от 1 до N.
  • xargs -n повреждения, которые перечисляют в пакеты N/workers+1.
    • например, N=100 workers=10 будет продолжать 10 линий до 11 чисел от 1 до 100.
  • while read i чтения каждая строка чисел.
  • work ${i} & просто вызовы work функция с ${i} пакет чисел.

Для отладки я добавил прокомментированный код отладки. Просто замените echo с отладочной версией и кодом между # -- с его отладочной версией и Вы видите, как она работает над пакетами. Некомментарий set -x для более подробного вывода отладки, который Вы могли бы хотеть перенаправить в файл.

Просто выполните отладочную версию с различными параметрами, чтобы смотреть, как она работает:

parallel.sh 223 5 1
parallel.sh 223 5 5
parallel.sh 223 5 10
parallel.sh 223 5 20

Отказ от ответственности: Этот код не синхронизируется min значение между рабочими процессами. Получение минимального значения не является ужасным осуществлением. Это, вероятно, сделает:

parallel.sh 223 5 20 | tr ' ' '\n' | sort -n | head -1

Или просто добавьте то же к самому сценарию:

echo ${arr[*]} | tr ' ' '\n' | sort -n | head -1
10
27.01.2020, 20:05
  • 1
    , можно ли объяснить код? Мне не ясно, как Вы использовали рабочие потоки здесь. –  RIchard Williams 03.12.2011, 15:09
  • 2
    @prasenjit Сделан. Я надеюсь, что это полезно. –  nicerobot 03.12.2011, 18:42

Использование параллели GNU:

#!/bin/bash

N=$1
n=$2

arr=($(
# Generate all combinations of 1..n and 1..N
parallel -k --tag /path/to/a.out {1} {2} '|' bc :::: <(seq $N) <(seq $n) |
  perl -ane 'BEGIN{$min=1e30} $last||=$F[0]; if($F[0] != $last) {print $min,"\n";$min=1e30;$last=$F[0]} $min = $F[2]<$min ? $F[2] : $min; END {print $min,"\n"}'
))
echo ${arr[*]}

Это будет работать /path/to/a.out на каждом CPU. Вывод будет похож:

1 1 19269
1 2 6158
1 3 2794
1 4 25104
2 1 13160
2 2 32683
2 3 12535
2 4 15197
3 1 8228
3 2 7673
3 3 8428
3 4 24463

Сценарий жемчуга смотрит на первый столбец и находит минимум в 3-м столбце, который имеет тот же первый столбец.

Можно установить Параллель GNU просто:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

Посмотрите вводные видео для узнавания больше: https://www.youtube.com/playlist? list=PL284C9FF2488BC6D1

8
27.01.2020, 20:05
  • 1
    Ссылка в Вашем последнем абзаце связывается со страницей взгляда Facebook, которая говорит посетителю, что он выиграл эксклюзивный подарок (реклама или жульничество). Нет никаких видео. Необходимо удалить его. –  Marco 31.10.2012, 09:33

Теги

Похожие вопросы