2013-11-29 5 views
4

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

В качестве примера (псевдо-код):

for paramA in 1 2 3 
    for paramB in 1 2 3 
    ./intensiveCommand $paramA $paramB 
    end 
end 

Я хотел бы parallellize intensiveCommand

Или есть более простой способ затем с помощью xargs?

+0

Вы можете добавить и подписать команду в конце команды с помощью "intensCommand". Это запустит задания в parralel. – unixmin

+0

Да, но это не учитывает нагрузку, верно? Таким образом, он будет продолжать добавлять процессы, из-за чего он начнет заменять и замедлять процессы. – MaVe

+0

В этом случае вы можете проанализировать среднее значение загрузки из вывода uname и условно запустить новые процессы. – unixmin

ответ

2

Вы можете использовать GNU parallel. У этого есть опция --load, чтобы избежать перегрузки компьютера.

parallel --load 100% ./intensiveCommand ::: 1 2 3 ::: 1 2 3 
0

Я написал это, которое работает очень красиво - прочитайте комментарии наверху, чтобы узнать, как это работает.

#!/bin/bash 
################################################################################ 
# File: core 
# Author: Mark Setchell 
# 
# Primitive, but effective tool for managing parallel execution of jobs in the 
# shell. Based on, and requiring REDIS. 
# 
# Usage: 
# 
# core -i 8 # Initialise to 8 cores, or specify 0 to use all available cores 
# for i in {0..63} 
# do 
# # Wait for a core, do a process, release core 
# (core -p; process; core -v)& 
# done 
# wait 
################################################################################ 
function usage { 
    echo "Usage: core -i ncores # Initialise with ncores. Use 0 for all cores." 
    echo "  core -p  # Wait (forever) for free core." 
    echo "  core -v  # Release core." 
    exit 1 
} 

function init { 
    # Delete list of cores in REDIS 
    echo DEL cores | redis-cli > /dev/null 2>&1 
    for i in `seq 1 $NCORES` 
    do 
     # Add another core to list of cores in REDIS 
     echo LPUSH cores 1 | redis-cli > /dev/null 2>&1 
    done 
    exit 0 
} 

function WaitForCore { 
    # Wait forever for a core to be available 
    echo BLPOP cores 0 | redis-cli > /dev/null 2>&1 
    exit 0 
} 

function ReleaseCore { 
    # Release or give back a core 
    echo LPUSH cores 1 | redis-cli > /dev/null 2>&1 
    exit 0 
} 

################################################################################ 
# Main 
################################################################################ 
while getopts "i:pv" optname 
    do 
    case "$optname" in 
     "i") 
     if [ $OPTARG -lt 1 ]; then 
      NCORES=`sysctl -n hw.logicalcpu`; # May differ if not on OSX, maybe "nproc" on Linux 
     else 
      NCORES=$OPTARG 
     fi 
    init $NCORES 
     ;; 
     "p") 
    WaitForCore 
     ;; 
     "v") 
    ReleaseCore 
     ;; 
     "?") 
     echo "Unknown option $OPTARG" 
     ;; 
    esac 
done 
usage 

В качестве примера, следующий занимает 10 секунд (не 80), чтобы сделать 16 ждет от 5 секунд:

core -i 8 
for i in {0..15} 
do 
    # Wait for a core, do a process, release core 
    (core -p ; sleep 5 ; core -v)& 
done 
wait 
+0

Это то, что имеется в виду с REDIS: http://redis.io/? – MaVe

+0

Да, это действительно легко установить и запустить. Ключевая функция в нем «BLPOP», которая блокирует ожидание элемента в списке. Это позволяет мне точно контролировать, сколько процессов может работать сразу. Если я хочу 8, я помещаю 8 элементов в список в начале и беру один раз каждый раз, когда выполняю задание, а затем возвращаю его в список по окончании. –

1
number_of_cores=4 #<-- number of processorcores, in my case: 4 

for paramA in 1 2 3 
do 
    for paramB in 1 2 3 
    do 
     #========== automatic load regulator ================== 
     sleep 1 
     while [ $(pgrep -c "intensiveCommand") -ge "$number_of_cores" ] 
     do 
      kill -SIGSTOP $$ 
     done 
     #======================================vvvvvvvvvvvvvvvv    

     (./intensiveCommand $paramA $paramB ; kill -SIGCONT $$) & 

    done 
done 

Эта программа поставит себя на держать, если там работает столько intensiveCommands, сколько ядер. Законченный интенсивный курс позволит программе продолжить (см. kill -SIGCONT $$). Программа снова проверяет и запускает интенсивные команды, пока не закроется снова, когда будет достигнуто максимальное количество интенсивных команд.

Сон заключается в том, чтобы преодолеть латентность между запуском интенсивной команды и ее внешним видом в таблице процессов.

1

Очень плотное планирование в «1 слоте на ядро», твердое и прочное.

#/bin/bash 

#use the filedescriptor as a kind of queue to fill the processing slots. 

exec 3< <(

    for PARAM_A in 1 2 3 
    do 
     for PARAM_B in 1 2 3 
     do 
      echo $PARAM_A $PARAM_B 
     done 
    done 
) 

#4 seperate processing slots running parallel 
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done & 
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done & 
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done & 
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done & 

#only exit when 100% sure that all processes ended 
while pgrep "intensiveCommand" &>"/dev/null" ; do wait ; done 
Смежные вопросы