4

並行して実行したいコマンドがたくさんあります。コマンドはほぼ同じです。それらはほぼ同じ時間かかることが予想され、完全に独立して実行できます。それらは次のようになります。

command -n 1 > log.1
command -n 2 > log.2
command -n 3 > log.3
...
command -n 4096 > log.4096

シェル スクリプトでそれらすべてを並行して起動することもできますが、システムは、CPU をビジー状態に保つために厳密に必要以上にロードしようとします (各タスクは、完了するまで 1 つのコアの 100% を使用します)。これにより、ディスクがスラッシングし、貪欲でない実行方法よりも全体が遅くなります。

最良のアプローチは、おそらくnタスクの実行を維持することnです。使用可能なコアの数はどこにありますか。

車輪の再発明はしたくありません。makeこの問題は、Unixプログラムでは既に解決されています (-j nオプションを使用した場合)。次のような線形サイズの Makefile を回避するために、上記の一般的な Makefile ルールを記述できるかどうか疑問に思っていました。

all: log.1 log.2 ...
log.1:
        command -n 1 > log.1
log.2:
        command -n 2 > log.2
...

最良の解決策が使用するのではなくmake、別のプログラム/ユーティリティを使用することである場合、依存関係が合理的である限り、私はそれを受け入れます(makeこの点で非常に優れていました)。

4

5 に答える 5

4

ブレース拡張に依存しない、より移植性の高いシェルコードは次のとおりです。

ログ:= $(shell seq 1 1024)

より効率的な変数を定義するために:=を使用していることに注意してください:単純に拡張された「フレーバー」。

于 2010-11-09T10:12:45.817 に答える
3

まず簡単な部分。Roman Cheplyakaが指摘しているように、パターンルールは非常に便利です。

LOGS = log.1 log.2 ... log.4096
all: $(LOGS)

log.%:
    command -n $* > log.$*

トリッキーな部分は、そのリストを作成することLOGSです。Makeは数字の扱いがあまり得意ではありません。最善の方法は、おそらくシェルを呼び出すことです。(シェルに合わせてこのスクリプトを調整する必要があるかもしれません。シェルスクリプトは私の最強のテーマではありません。)

NUM_LOGS = 4096

LOGS = $(shell for ((i=1 ; i<=$(NUM_LOGS) ; ++i)) ;  do  echo log.$$i ; done)
于 2010-11-05T16:01:09.917 に答える
3

パターンルールを見る

これが を必要とする唯一の理由である場合、もう 1 つの方法は、とのオプションmakeを使用することです。-n-Pxargs

于 2010-11-05T14:58:23.160 に答える
3

xargs -P は、これを行う「標準的な」方法です。ディスク I/O によっては、コアではなくスピンドルに制限したい場合があることに注意してください。コアに限定したい場合は、最近の coreutils の新しい nproc コマンドに注意してください。

于 2010-11-05T16:19:33.730 に答える
2

GNU Parallel を使用すると、次のように記述できます。

parallel command -n {} ">" log.{} ::: {1..4096}

10 秒のインストール:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

詳細: http://www.gnu.org/software/parallel/parallel_tutorial.html https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

于 2013-11-05T21:30:10.530 に答える