1

複数のジョブを並行して実行するために bash スクリプトを使用しようとしています。ジョブはメモリを集中的に使用するため、一度に起動する数を制御する必要があります。私が持っているものは以下のもので、広く機能しますが、遅延ループが開始されたばかりのジョブを認識しない場合があるため、いくつかの追加のジョブが起動され、システムのメモリが不足します。

遅延ループの while ステートメントの前にスリープを追加すると、この問題は軽減されますが、完全になくなるわけではありません。これを治す方法を知っている方。関連する場合は、Solarisで実行しています。

#!/bin/bash
delay(){
while [ 8 -le $(ps -ef |grep  myjob |wc -l) ]
do
sleep 1
done
}

./myjob -params1 &
delay
./myjob -params2 &
delay
./myjob -params3 &
delay
./myjob -params4 &
delay
.
.
.
4

4 に答える 4

2

GNUparallelユーティリティhttp://www.gnu.org/software/parallel/は、xargs よりも使いやすいと言えるため、適切なツールである可能性があります。

于 2012-08-20T12:13:09.310 に答える
0

これを行うために使用xargsします。これを渡して-n 1、ジョブごとに 1 つのパラメーターを示し、--max-jobsパラメーターを使用して同時プロセスの数を指定します。

于 2012-08-20T10:38:11.710 に答える
0

a に関してスクリプトを作成し、makefileParallel Executionmake -j Nで整理します。

于 2012-08-20T15:01:49.100 に答える
0

最初に、いくつかの Linux スクリプトで行っていることの簡単な例を示します。これは、solaris で動作するはずですが、現在テストするシステムがありません。/proc を使用するいくつかの変更を加えたので、何かうまくいかない場合はお知らせください。

#!/bin/bash

# set the max # of threads
max_threads=4
# set the max system load
max_load=4

print_jobs(){
# flush finished jobs messages
  jobs > /dev/null
  for x in $(jobs -p) ; do
   # print all jobs
    echo "$x"
  done
}

job_count(){
  cnt=$(print_jobs $1)
  if [ -n "$cnt" ]; then
    wc -l <<< "$cnt"
  else
    echo 0
  fi
}

cur_load(){
  # get the 1 minute load average integer
  uptime |sed 's/.*load average[s]*:[[:space:]]*\([^.]*\)\..*/\1/g'
}


main_function(){
 # get current job count and load
  jcnow=$(job_count)
  loadnow=$(cur_load)

 # first, enter a loop waiting for load/threads to be below thresholds
  while [ $loadnow -ge $max_load ] || [ $jcnow -ge $max_threads ]; do
    if ! [ $firstout ]; then
      echo "entering sleep loop. load: $loadnow, threads: $jcnow"
      st=$(date +%s)
      local firstout=true
    else
      now=$(date +%s)
     # if it's been 5 minutes, echo again:
      if [ $(($now - $st)) -ge 300 ]; then
        echo "still sleeping. load: $loadnow, threads: $jcnow"
        st=$(date +%s)
      fi
    fi
    sleep 5s

   # refresh these variables for loop
    loadnow=$(cur_load)
    jcnow=$(job_count)
  unset firstout
  done

  ( ./myjob $@ ) &
}

# do some actual work
for jobparams in "params1" "params2" "params3" "params4" "params5" "params6" "params7" ; do
   main_function $jobparams
done

wait

いくつかの注意事項:

  • 子プロセスを強制終了できるように、シグナルをトラップする必要があります。私はsolarisでこれを行う方法を知りませんが、これはLinuxで機能します:trap 'echo "exiting" ; rm -f $lockfile ; kill 0 ; exit' INT TERM EXIT
  • ジョブがすでに実行されている間に負荷が上昇した場合、スロットルを下げる機能はありません

負荷をまったく気にしない場合は、これは少し簡単になります。

#!/bin/bash

# set the max # of threads
max_threads=4

print_jobs(){
# flush finished jobs messages
  jobs > /dev/null
  for x in $(jobs -p) ; do
   # print all jobs
    echo "$x"
  done
}

job_count(){
  cnt=$(print_jobs $1)
  if [ -n "$cnt" ]; then
    wc -l <<< "$cnt"
  else
    echo 0
  fi
}

main_function(){
 # get current job count
  jcnow=$(job_count)

 # first, enter a loop waiting for threads to be below thresholds
  while [ $jcnow -ge $max_threads ]; do
    if ! [ $firstout ]; then
      echo "entering sleep loop. threads: $jcnow"
      st=$(date +%s)
      local firstout=true
    else
      now=$(date +%s)
     # if it's been 5 minutes, echo again:
      if [ $(($now - $st)) -ge 300 ]; then
        echo "still sleeping. threads: $jcnow"
        st=$(date +%s)
      fi
    fi
    sleep 5s

   # refresh these variables for loop
    jcnow=$(job_count)
  unset firstout
  done


  ( ./myjob $@ ) &
}

# do some actual work
for jobparams in "params1" "params2" "params3" "params4" "params5" "params6" "params7" ; do
   main_function $jobparams
done

wait
于 2013-08-20T20:01:24.513 に答える