質問

きんいループにBash:

for foo in `some-command`
do
   do-something $foo
done

do-something はcpuを行っても光沢のある4つのコアプロセッサー持ってき方など、さすがだなと私走ることができる4 do-something'sです。

のナイーブアプローチと考える:

for foo in `some-command`
do
   do-something $foo &
done

この実行 すべての do-somethings"は一度もありカップルのマイナス面は、主にとっても重要なI/Oを行 すべての 一気が減速しております。もう一つの問題は、このコードブロックはただちに復帰していないその他の場合、すべての do-somethings"は終了しました。

はどのように書くこループでは常にありX do-somethings走行では一回しか出来ないのですか?

役に立ちましたか?

解決

によってやりたいxargsもできる(ここでは変換した文書pdf2ps):

cpus=$( ls -d /sys/devices/system/cpu/cpu[[:digit:]]* | wc -w )

find . -name \*.pdf | xargs --max-args=1 --max-procs=$cpus  pdf2ps

からのドキュメント:

--max-procs=max-procs
-P max-procs
       Run up to max-procs processes at a time; the default is 1.
       If max-procs is 0, xargs will run as many processes as  possible  at  a
       time.  Use the -n option with -P; otherwise chances are that only one
       exec will be done.

他のヒント

GNU並列 http://www.gnu.org/software/parallel/ に書き込み:

some-command | parallel do-something

GNU並列の支援も行中のジョブのリモートコンピュータこまつのCPUコアをリモートコンピュータ-場合であっても異なるコア数:

some-command | parallel -S server1,server2 do-something

より高度なもの例:ここではファイルの一覧いただきたいmy_script実行します。ファイルの拡張子も参考になり嬉しいです。jpeg).また、出力のmy_scriptれのファイルbasename.(例:foo.jpeg ->foo.しています。して走らせたいというmy_script一のための各コアをコンピューターとして走らせたいというのでローカルコンピュータです。のためのリモートコンピュータまたはファイルを処理する転送を指定された。時my_scriptを終了または変換される。出所に戻されましたfoo.jpeg やfoo.行からのリモートコンピュータ:

cat list_of_files | \
parallel --trc {.}.out -S server1,server2,: \
"my_script {} > {.}.out"

GNU並行しているのを確認し、出力から仕事なミックスを利にご利用いただけますの出力を入力として別のプログラム:

some-command | parallel do-something | postprocess

のビデオを用例: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

maxjobs=4
parallelize () {
        while [ $# -gt 0 ] ; do
                jobcnt=(`jobs -p`)
                if [ ${#jobcnt[@]} -lt $maxjobs ] ; then
                        do-something $1 &
                        shift  
                else
                        sleep 1
                fi
        done
        wait
}

parallelize arg1 arg2 "5 args to third job" arg4 ...

の代わりに平bashを使用しMakefile、指定数を同時に仕事 make -jX Xはジョブの個数を実行します。

ことができま wait ("man wait"):打上げの複数の子プロセス、コ wait ですが、子プロセスに仕上がります。

maxjobs = 10

foreach line in `cat file.txt` {
 jobsrunning = 0
 while jobsrunning < maxjobs {
  do job &
  jobsrunning += 1
 }
wait
}

job ( ){
...
}

が必要な場合は、ジョブの結果、その割り当てその結果を変数となります。後 wait すぐチェックインの変数が入っています。●

こちらの代替できるソリューションを提供挿入されます。bashrcに使える日常のワーライナー:

function pwait() {
    while [ $(jobs -p | wc -l) -ge $1 ]; do
        sleep 1
    done
}

を活用して、すべてから入れ & 後の仕事とpwaitのパラメータの数並列プロセス:

for i in *; do
    do_something $i &
    pwait 10
done

い寝利用 wait 代わりに忙しいで待機中の出力 jobs -p, があるという明らかな解決を待つまでの、指定された仕事は終了ではなく全員について記入してください。

ってみて、並列化効用ではなく書き換えループ?私の大ファンでxjobs.使っていxjobsすべての質量ファイルをコピーがお客様のネットワーク、通常は設定時に、新しいデータベースサーバーです。http://www.maier-komor.de/xjobs.html

このように bash は不可能でセミ右かなります。 bstark また公正近似のものの不備:

  • 単語分割:できませんパスの他に仕事で使用するには、以下の文字をその引数:"入力文の半角スペース、タブ、改行、星、質問です。みんなでも休みが誰にも予想できなかった
  • に頼って、スクリプトな背景のものです。う場合、またはその後追加のスクリプトを取得する※当アプリをご利用いただくにはししますので忘れません使用を許可backgrounded仕事のため、スニペットかうと思う。

他の近似できないこれらの欠点は次の通りです:

scheduleAll() {
    local job i=0 max=4 pids=()

    for job; do
        (( ++i % max == 0 )) && {
            wait "${pids[@]}"
            pids=()
        }

        bash -c "$job" & pids+=("$!")
    done

    wait "${pids[@]}"
}

なお、こでも容易に適用できるプロジェクト終了コードの各ジョブとしても終了できますので注意のユーザーが仕事の失敗または設定出口よりコード scheduleAll 額に応じて仕事に失敗したときは、あります。

このコードです:

  • での予定につ(この場合)仕事で時間待機し、そのすべての四ます。あさいち早くその他の原因になりますので、次のバッチのジョブで最も長いので、前回のバッチが行われます。

うソリューションの最後の課題に関する kill -0 ポるかどうかのプロセスが消えてしまいますの代わりに wait とスケジュールは次の仕事です。しかし、紹介する小さな新しい問題:お持ちのレース状態の間の仕事を終了し、 kill -0 かどうかの確認が終了しました。場合には仕事を終了し、別のプロセスシステムの起動と同時に、ランダムPIDさせることができること、仕事終え、 kill -0 なに自分の仕事が終わったことをともします。

ソリューションができないからで bash.

ばじ make コマンドでは、ほとんどの時間を表現でき、リストのコマンドを実行したいとして、makefile.例えば、を実行する必要があります$SOME_COMMANDファイル*.入力される*.出力を使用できますmakefile

INPUT  = a.input b.input
OUTPUT = $(INPUT:.input=.output)

%.output : %.input
    $(SOME_COMMAND) $< $@

all: $(OUTPUT)

そして走り

make -j<NUMBER>

時多数のコマンドを行なった。

機能bash:

parallel ()
{
    awk "BEGIN{print \"all: ALL_TARGETS\\n\"}{print \"TARGET_\"NR\":\\n\\t@-\"\$0\"\\n\"}END{printf \"ALL_TARGETS:\";for(i=1;i<=NR;i++){printf \" TARGET_%d\",i};print\"\\n\"}" | make $@ -f - all
}

利用:

cat my_commands | parallel -j 4

のプロジェクトに取り組んに使用し コマンドにパラレル制御シェル(ksh実際に)プロセス。題へのお問IO、現代のOSでは、この並列実行が実際に効率化を図る。すべての過程を読んで同じブロックディスクにより、最初の過程については、物理的ハードウェアその他のプロセスがしばしばきを取得するブロックからOSのディスクキャッシュメモリ.明らかに、からの読み出しメモリは複数の桁以上に早くからの読み出します。また、利益を必要としない符号化変わります。

これは良いかもしれないほど多目的な最適です。

#!/bin/bash

n=0
maxjobs=10

for i in *.m4a ; do
    # ( DO SOMETHING ) &

    # limit jobs
    if (( $(($((++n)) % $maxjobs)) == 0 )) ; then
        wait # wait until all have finished (not optimal, but most times good enough)
        echo $n wait
    fi
done

本当に 開催時間内にこちらのだが、ここでも。

多くの解決な取扱い空間に特殊な文字コマンドのいくN行、食べcpuしかし、ループ、または依拠した外部の依存関係(例えばGNU parallel).

ヒンデッド/ゾンビ過程で取り扱い, こちらのは、純粋なbash解

function run_parallel_jobs {
    local concurrent_max=$1
    local callback=$2
    local cmds=("${@:3}")
    local jobs=( )

    while [[ "${#cmds[@]}" -gt 0 ]] || [[ "${#jobs[@]}" -gt 0 ]]; do
        while [[ "${#jobs[@]}" -lt $concurrent_max ]] && [[ "${#cmds[@]}" -gt 0 ]]; do
            local cmd="${cmds[0]}"
            cmds=("${cmds[@]:1}")

            bash -c "$cmd" &
            jobs+=($!)
        done

        local job="${jobs[0]}"
        jobs=("${jobs[@]:1}")

        local state="$(ps -p $job -o state= 2>/dev/null)"

        if [[ "$state" == "D" ]] || [[ "$state" == "Z" ]]; then
            $callback $job
        else
            wait $job
            $callback $job $?
        fi
    done
}

および使用例:

function job_done {
    if [[ $# -lt 2 ]]; then
        echo "PID $1 died unexpectedly"
    else
        echo "PID $1 exited $2"
    fi
}

cmds=( \
    "echo 1; sleep 1; exit 1" \
    "echo 2; sleep 2; exit 2" \
    "echo 3; sleep 3; exit 3" \
    "echo 4; sleep 4; exit 4" \
    "echo 5; sleep 5; exit 5" \
)

# cpus="$(getconf _NPROCESSORS_ONLN)"
cpus=3
run_parallel_jobs $cpus "job_done" "${cmds[@]}"

出力:

1
2
3
PID 56712 exited 1
4
PID 56713 exited 2
5
PID 56714 exited 3
PID 56720 exited 4
PID 56724 exited 5

たりプロセス出力の取り扱い $$ このログをとるために使用されるファイル、例えば:

function job_done {
    cat "$1.log"
}

cmds=( \
    "echo 1 \$\$ >\$\$.log" \
    "echo 2 \$\$ >\$\$.log" \
)

run_parallel_jobs 2 "job_done" "${cmds[@]}"

出力:

1 56871
2 56872

利用できる簡単な入れ子ループ(代替の適切な整数N-M以下):

for i in {1..N}; do
  (for j in {1..M}; do do_something; done & );
done

これを実行しdo_something N-M倍Mの貿各ラウンドを実行N仕事を行なった。できるNに等しい数のCpuます。

ここではどのようにこれらの問題を解決するために、bashスクリプト:

 #! /bin/bash

 MAX_JOBS=32

 FILE_LIST=($(cat ${1}))

 echo Length ${#FILE_LIST[@]}

 for ((INDEX=0; INDEX < ${#FILE_LIST[@]}; INDEX=$((${INDEX}+${MAX_JOBS})) ));
 do
     JOBS_RUNNING=0
     while ((JOBS_RUNNING < MAX_JOBS))
     do
         I=$((${INDEX}+${JOBS_RUNNING}))
         FILE=${FILE_LIST[${I}]}
         if [ "$FILE" != "" ];then
             echo $JOBS_RUNNING $FILE
             ./M22Checker ${FILE} &
         else
             echo $JOBS_RUNNING NULL &
         fi
         JOBS_RUNNING=$((JOBS_RUNNING+1))
     done
     wait
 done

私の解決には必ず控えを保管してください指定された数のプロセスに走り、追跡誤差を取り扱いubnterruptible/ゾンビプロセス:

function log {
    echo "$1"
}

# Take a list of commands to run, runs them sequentially with numberOfProcesses commands simultaneously runs
# Returns the number of non zero exit codes from commands
function ParallelExec {
    local numberOfProcesses="${1}" # Number of simultaneous commands to run
    local commandsArg="${2}" # Semi-colon separated list of commands

    local pid
    local runningPids=0
    local counter=0
    local commandsArray
    local pidsArray
    local newPidsArray
    local retval
    local retvalAll=0
    local pidState
    local commandsArrayPid

    IFS=';' read -r -a commandsArray <<< "$commandsArg"

    log "Runnning ${#commandsArray[@]} commands in $numberOfProcesses simultaneous processes."

    while [ $counter -lt "${#commandsArray[@]}" ] || [ ${#pidsArray[@]} -gt 0 ]; do

        while [ $counter -lt "${#commandsArray[@]}" ] && [ ${#pidsArray[@]} -lt $numberOfProcesses ]; do
            log "Running command [${commandsArray[$counter]}]."
            eval "${commandsArray[$counter]}" &
            pid=$!
            pidsArray+=($pid)
            commandsArrayPid[$pid]="${commandsArray[$counter]}"
            counter=$((counter+1))
        done


        newPidsArray=()
        for pid in "${pidsArray[@]}"; do
            # Handle uninterruptible sleep state or zombies by ommiting them from running process array (How to kill that is already dead ? :)
            if kill -0 $pid > /dev/null 2>&1; then
                pidState=$(ps -p$pid -o state= 2 > /dev/null)
                if [ "$pidState" != "D" ] && [ "$pidState" != "Z" ]; then
                    newPidsArray+=($pid)
                fi
            else
                # pid is dead, get it's exit code from wait command
                wait $pid
                retval=$?
                if [ $retval -ne 0 ]; then
                    log "Command [${commandsArrayPid[$pid]}] failed with exit code [$retval]."
                    retvalAll=$((retvalAll+1))
                fi
            fi
        done
        pidsArray=("${newPidsArray[@]}")

        # Add a trivial sleep time so bash won't eat all CPU
        sleep .05
    done

    return $retvalAll
}

使用量:

cmds="du -csh /var;du -csh /tmp;sleep 3;du -csh /root;sleep 10; du -csh /home"

# Execute 2 processes at a time
ParallelExec 2 "$cmds"

# Execute 4 processes at a time
ParallelExec 4 "$cmds"

$領域="リストのドメインコマンド" fooに some-command

eval `some-command for $DOMAINS` &

    job[$i]=$!

    i=$(( i + 1))

を行い

Ndomains=echo $DOMAINS |wc -w

その$(配列番号1 1$Ndomains) い echo"の待${仕事[$i]}" お待ち"${仕事[$i]}" を行い

このプロセスの並列.重要なことは前のエバールは'&' これによって、コマンドを持つ。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top