-j について知って以来、私は -j8 を気軽に使ってきました。先日、アトラスのインストールをコンパイルしていて、make が失敗しました。最終的に、私はそれが順不同で作成されていることを突き止めました-そして、シングルスレッドのmakeに戻ると、うまくいきました. これは私を緊張させます。make -j で予想外のことをしないようにするために、独自の make ファイルを作成するときは、どのような条件に注意する必要がありますか?
6 に答える
make -j は Makefile で指定した依存関係を尊重すると思います。つまり、objA が objB と objC に依存するように指定した場合、make は objB と objC が完了するまで objA の処理を開始しません。
ほとんどの場合、Makefile は操作の必要な順序を十分に厳密に指定していません。シングル スレッドの場合にうまく機能するのは運がいいだけです。
これは、並列ビルドを使い始めたときに遭遇した問題の例です。ターゲットを最初から再構築するために使用する「fresh」というターゲットがあります(「fresh」ビルド)。以前は、依存関係として「クリーン」を示し、次に「ビルド」を示すだけで、「フレッシュ」ターゲットをコーディングしていました。
build: ## builds the default target
clean: ## removes generated files
fresh: clean build ## works for -j1 but fails for -j2
並列ビルドを使い始めるまでは問題なく機能しましたが、並列ビルドでは、「クリーン」と「ビルド」の両方を同時に実行しようとします。そこで、正しい操作順序を保証するために、「フレッシュ」の定義を次のように変更しました。
fresh:
$(MAKE) clean
$(MAKE) build
これは基本的に、依存関係を正しく指定するだけの問題です。秘訣は、並列ビルドはシングルスレッドビルドよりもこれに関してより厳密であるということです。私の例は、特定のターゲットの依存関係のリストが必ずしも実行の順序を示しているわけではないことを示しています。
効果が明確に表示されないため、subsetbrewの回答に追加すると思いました。ただし、いくつかのスリープ コマンドを追加すると機能します。まあ、Linuxで動作します。
次に make を実行すると、以下との違いが表示されます。
- 作る
- -j4 を作る
all: toprule1
toprule1: botrule2 subrule1 subrule2
@echo toprule 1 start
@sleep 0.01
@echo toprule 1 done
subrule1: botrule1
@echo subrule 1 start
@sleep 0.08
@echo subrule 1 done
subrule2: botrule1
@echo subrule 2 start
@sleep 0.05
@echo subrule 2 done
botrule1:
@echo botrule 1 start
@sleep 0.20
@echo "botrule 1 done (good prerequiste in sub)"
botrule2:
@echo "botrule 2 start"
@sleep 0.30
@echo "botrule 2 done (bad prerequiste in top)"