Параллелизация цикла for с очень большим количеством итераций

Я хочу распараллелить цикл for, где число итераций в цикле может быть очень большим, например 10 ^ 6. Таким образом, будет лучше, если я смогу создавать потоки, а не обрабатывать. Как это сделать? Код выглядит следующим образом

N=$1 for (( i=0; i < $N; i++ )); do ./random >> output /* in each iteration one random number is appended to a file "output" */ done 

  • Замените «...» многострочный вывод команды find
  • Что делает $ {3 #?}?
  • Базовое имя дает дополнительную ошибку операнда
  • Escape whitespace в поиске для pdftk без xargs -J
  • Как выводить некоторые данные в разные ячейки файла Excel?
  • Является ли `grep -P` (Perl / Python regex) переносимым для большинства дистрибутивов Linux
  • Запуск сценария Python из любого места
  • Найти и заменить с помощью sed с помощью подстановочных знаков при поиске и замене
  • 4 Solutions collect form web for “Параллелизация цикла for с очень большим количеством итераций”

    1. Вы не можете создавать потоки из оболочки.
    2. Вы не хотите писать в один файл из нескольких процессов.
    3. Если вся ваша random программа генерирует один номер,
      • он должен быть достаточно быстрым, чтобы ваша петля была ограничена.
      • если можно, вы должны отредактировать его, чтобы принять аргумент и напечатать много чисел.
      • если фактическое выполнение является узким местом, вы должны переосмыслить, как сгенерировать числа. Возможно, разместите код в Code Review .

    Если вы действительно все еще хотите сделать это так, сделайте это в кусках:

     for i in {0..9}; do for ((j = 1; j < $N/10; j++)); do ./random done > tmp$i & pid[$i]=$? done for i in {0..9}; do wait ${pid[$i]} done cat tmp{0..9} >> outfile - for i in {0..9}; do for ((j = 1; j < $N/10; j++)); do ./random done > tmp$i & pid[$i]=$? done for i in {0..9}; do wait ${pid[$i]} done cat tmp{0..9} >> outfile 

    Я не знаю какой-либо оболочки, которая позволяет вам вручную создавать новые потоки, обычно вы можете использовать только существующие потоки в текущей оболочке (или создавать подоболочки, которые действительно являются новыми процессами). Вместо этого используйте python или другой язык.

    Даже если бы вы могли, я бы не рекомендовал использовать сценарий оболочки для чего-то в этом масштабе. Потери производительности по сравнению с скомпилированным языком при выполнении 10 ^ 6 итераций могут быть существенными.

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

    Кроме того, наличие параллельных потоков зависит от количества операций, которые будут выполняться. Гораздо лучше, если есть хорошее сочетание программирования: память, процессор, i / o и т. Д. Если все подпроцессы будут делать все cpu, то запуск 10-20 сразу не ускорит что-либо. Вы можете попытаться обработать обработку на других машинах; например, используя ssh для запуска вызовов на других машинах и возврата результатов.

    Быстрый и грязный первый проход может выглядеть примерно так:

     N=$1 # max number to iterate on shift # rest of command line is the command to run: eg "./random" maxcount=10 # maximum in the pool curcount=0 # how many currently in the pool reaper () { wait curcount=`expr $curcount - 1` } spawnnext () { n=$1 shift while [ $curcount -ge $maxcount ]; do sleep 1 # wait for a free slot in the pool done echo $n "$@" & curcount=`expr $curcount + 1` } trap 'reaper' CHLD for (( i=0; i < $N; i++)); do spawnnext $i "$@" done 

    Заметка; Я не тестировал это; просто написал это на лету.

    Но я бы сделал это на более высоком уровне, более эффективном языке, таком как Python: https://stackoverflow.com/questions/3033952/python-thread-pool-similar-to-the-multiprocessing-pool

    Если ваша задача – просто генерировать случайные числа:

     perl -e 'for($t=0;$t<1000000;$t++) { print int(rand()*1000),"\n" }' 

    Если ваша задача действительно что-то еще, вы можете использовать GNU Parallel:

     parallel ./random :::: <(seq 1000000) > output 

    Вы можете установить GNU Parallel, просто:

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

    Смотрите видеоролики, чтобы узнать больше: http://pi.dk/1

    Linux и Unix - лучшая ОС в мире.