私は研究プロジェクトの一環として、大量のデータを複数のファイルに分割して処理しています。
フォルダ内のすべてのファイルは、フォルダ内のすべての要素に関連するスクリプトとして処理する必要がありfoo
ます。myScript
bar
これはmyScript
:
for f in bar/*
do
awk 'NR==FNR{a[$0]=$0;next}!a[$0]' $f $1 > tmp
cp tmp $1
done
すべてのファイルを処理するためにforループを使用する最初のアイデアは次のとおりです。
for f in foo/*
do
./myScript $f
done
しかし、時間がかかります。単純に追加してバックグラウンドで各myScriptを起動すると、&
何千もの並列実行と膨大な入力をawk
含むインスタンスが作成されるため、cp
明らかに悪くなります。
以下を使用して生成される「スレッド」の数を制限したいと思います。
for f in foo/*
do
THREAD_COUNT=$(ps | wc -f)
while [ $THREAD_COUNT -ge 12 ]
do
sleep 1
THREAD_COUNT=$(ps | wc -f)
done
./myScript $f &
done
ちなみに、ノードに8つのコアがあり、明らかに常にbash
ランニングがps
ありwc
、呼び出し時のヘッダラインもランニングであるため、12と比較していますps | wc -l
。
残念ながら を呼び出すmyScript
と、いくつかの追加エントリが に表示されるので、ps
私のスクリプトは期待どおりに動作しません。
私の質問はこんな感じです。より簡単な方法がありますか?どちらがより安定していますか?
ノードで他のタスクを実行しないため、発生するすべてのタスクはスクリプトによって発生します。
答え1
シェルスクリプトを使用してこれを行うことはできますが、難しいです。シェルスクリプトは、いくつかのバックグラウンドタスクを実行するのにあまりうまくいきません。
私の提案は以下を使用することです。GNUが作るあるいは、異なるバージョンの make は、複数のジョブを並列-j
に実行することを選択できます。各サブタスクを makefile ルールで作成します。
以下のメイクファイルの部分があなたのルールを実装しているようですが、あなたのコードは従うのが難しいので、今すぐ結果が得られた可能性があります。最初の行は、入力ファイルの出力ファイルを列挙します(注:入力ファイルを上書きしないでください。何らかの理由でジョブが途中で停止した場合、処理されたかどうか不明なデータが残ります)。インデントされた行は実行するコマンドです。 8つのスペースの代わりにタブを使用して各コマンドをインデントします。このコマンドでは、ソースファイル(file)を$<
表し、ターゲットファイル(file)を表し、拡張子のないターゲットです。シェルコマンドのすべてのシンボルは2倍にする必要があり、改行を抑制するために末尾にを追加しない限り、各コマンドラインは別々のサブシェルで実行されます(シェルでは開始と終了が1行の長い行として表示されます)。.in
$@
.out
$*
$
\
set -e
done
all: $(patsubst %.in,%.out,$(wildcard foo/*.in))
%.out: %.in
cp $< $*.tmp.in
set -e; \
for f in bar/*; do \
awk 'NR==FNR{a[$$0]=$$0;next}!a[$$0]' $$f $*.tmp.in >$*.tmp.out; \
mv $*.tmp.out $*.tmp.in; \
done
mv $*.tmp.in $@
Makefile
名前付きファイルに入れて呼び出しますmake -j12
。
答え2
GNU Parallel(http://www.gnu.org/software/parallel/)を使用すると、次のようになります。
parallel awk \'NR==FNR\{a\[\$0\]=\$0\;next\}\!a\[\$0\]\' {1} {2} '>{2}.tmp; mv {2}.tmp {2}' ::: bar/* ::: foo/*
これにより、コアごとに1つのジョブが実行されます。-j150%
コアごとに1.5個のジョブを実行するために使用されます。
複数を並列に実行するには、myScript
次のようにします。
parallel ./myScript ::: foo/*
詳しくは、紹介ビデオをご覧ください。https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
答え3
ulimit
bashのマニュアルページで試すことができます。
ulimit [-HSTabcdefilmnpqrstuvx [limit]]
Provides control over the resources available to the shell and to processes started by it,
on systems that allow such control.
[...]
-u The maximum number of processes available to a single user
ulimit -u 8
したがって、スクリプト内の適切な場所に配置すると、シェルで使用できるプロセスは8つに制限されます。
しかし、まだテストしていません。