Sun WorkShop の概要 |
付録 C
dmake
ユーティリティの使用この付録では、分散メーク (
dmake
) ユーティリティで構築プロセスを複数のホストに分散し、複数のワークステーションやマルチプロセッサ上で並列的にプログラムを構築する方法について説明します。dmake
(1) のマニュアルページも参照してください。基本概念
分散メーク (
dmake
) は、make
ユーティリティのスーパーセットです。dmake
を使用することにより、多数のプログラムで構成される大規模なプロジェクトの構築プロセスを複数のワークステーション (マルチプロセッサシステムの場合は複数の CPU) に分散して、並列的に作業を進めることができます。
dmake
ホスト上でdmake
を実行すると、構築サーバーにジョブが分散されます。ジョブはdmake
ホストにも割り当てることができ、その場合は、dmake
ホストも構築サーバーと見なされます。dmake
ユーティリティは、構築が並列可能であると判断した、メークファイル内のターゲットに基づいてジョブを分散します。dmake
ホストから、使用する構築サーバーや各構築サーバーに割り当てるdmake
ジョブ数を制御できます。また、構築サーバーで実行可能なdmake
ジョブ数を制限することもできます。
dmake
ジョブの分散は、次の 2 通りの方法で制御されます。
- 構築サーバーとして使用するマシンと各構築サーバーに分散するジョブ数:
dmake
ユーザーがdmake
ホストからを指定します。- サーバーに割り当て可能な総
dmake
ジョブ数: 構築サーバーの所有者 (構築サーバー構成ファイル/etc/opt/SPROdmake/dmake.conf
を編集する権限を持つユーザー) が制御できます。
注 - 「構築」ウィンドウからdmake
を使用する際の構築サーバーとジョブの指定方法については、オンラインヘルプを参照してください。コマンド行からdmake
にアクセスする場合は、dmake
(1) のマニュアルページを参照してください。
dmake
を理解するには、次のことを理解する必要があります。
dmake
ホスト
dmake
ホストとは、dmake
コマンドの発行元のマシンです。dmake
ユーティリティは、実行時構成ファイルの内容に基づいて、ジョブをどこに分散するかを決定します。一般に、このファイルは、dmake
ホストのホームディレクトリ内に、.dmakerc
という名前で置かれている必要があります。dmake
ユーティリティは、以下の順序で実行時構成ファイルを探します。
- コマンド行で
-c
オプションを使用して指定されたパス名DMAKE_RCFILE
という名のメークファイルマクロを使用して指定されたパス名DMAKE_RCFILE
環境変数を使用して指定されたパス名$(HOME)/.dmakerc
実行時構成ファイルが見つからない場合、
dmake
ユーティリティはdmake
ホストに 2 つのジョブを割り当てます。実行時構成ファイルによって、各構築サーバーのリストと各構築サーバーに分散するジョブの数を指定できます。次に、
コード例 C-1.dmakerc
ファイルの例を示します。.dmakerc
ファイル
# 自分のマシン。この行により dmake は自分のマシンへジョブを分散する。falcon { jobs = 1 }hawkeagle { jobs = 3 }# 上司のマシン。たいてい、会議中。heron { jobs = 4 }avocet
falcon
、hawk
、eagle
、heron
、avocet
は構築サーバー名です。これらの構築サーバーのそれぞれに割り当てるジョブ数を指定できます。デフォルトのジョブ数は 2 つです。#
から始まる行はすべてコメントと解釈されます。上記の例の構築サーバーのリストには、dmake
ホストでもあるfalcon
が指定されています。dmake
ホストを構築サーバーとして指定することもできます。実行時構成ファイルに指定されていないホストに、dmake
ジョブが割り当てられることはありません。実行時構成ファイルで、複数の構築サーバーグループを定義できます。これにより、状況に応じて構築サーバーグループを柔軟に切り換えることができます。たとえば、異なるオペレーティングシステムでの構築処理ごとに、複数の異なる構築サーバーグループを定義できます。また、特殊なソフトウェアがインストールされた複数の異なる構築サーバーグループを定義することもできます。
次に、構築サーバーのグループを定義した実行時構成ファイルの例を示します。
コード例 C-2 構築サーバーグループを定義した.dmakerc
ファイル
構築サーバーのグループは
group
キーワードを使用して指定し、そのメンバーは中括弧 ({}
) で区切ります。グループのメンバーとなる構築サーバーは、オプションのhost
キーワードを使用して指定します。グループを他のグループのメンバーにすることができます。個々の構築サーバーを、構築サーバーのグループを含んでいる実行時構成ファイルに指定することもできます。この場合、構築サーバーは無名のグループのメンバーとみなされます。
dmake
ユーティリティは、次の順序で各ジョブを分散させます。
- コマンド行で
-g
オプションを使用して指定されたグループDMAKE_GROUP
という名のメークファイルマクロで指定されたグループDMAKE_GROUP
環境変数を使用して指定されたグループ- 実行時構成ファイルで指定された最初のグループ
コード例 C-3 構築サーバーの代替パスを指定した
dmake
ユーティリティを使用すると、構築サーバーごとに異なる実行パスを指定できます。デフォルトでは、dmake
は、論理サーバー内のdmake
ホストと同じ論理パス上にあるdmake
サポートバイナリを検索します。構築サーバーの代替パスは、たとえば次のように、ホスト属性として.dmakerc
ファイルに指定できます。.dmakerc
ファイル
group lab1 {host falcon { jobs = 10 , path = "/set/dist/sparc-S2/bin" }host hawk { path = "/opt/SUNWspro/bin" }}
コード例 C-4 特殊文字を使用した
.dmakerc
ファイル内のグループ名とホスト名は、二重引用符で囲むことができます。二重引用符で囲むことで、グループ名に使用できる文字の種類が増え、英字だけでなく、数字も使用できるようになります。たとえば、次に示すように、グループ名が数字で始まる場合は、二重引用符で囲んでください。.dmakerc
group "123_lab" {host "456_hawk" { path = "/opt/SUNWspro/bin" }}
構築サーバー
分散構築に参加する各構築サーバーには、
/etc/opt/SPROdmake/dmake.conf
というファイルが存在している必要があります。このファイルは、構築サーバー構成ファイルで、特定の構築サーバーに全dmake
ユーザーが分散できるdmake
ジョブの最大数を指定します。また、すべてのdmake
ジョブを実行する際の優先順位nice
を指定できます。
注 - 構築サーバーに/etc/opt/SPROdmake/dmake.conf
ファイルがない場合は、そのサーバー上でdmake
ジョブを実行することはできません。
コード例 C-5 に
コード例 C-5/etc/opt/SPROdmake/dmake.conf
ファイルの例を示します。この例では、(dmake
ユーザーが全体として) 1 つの構築サーバー上で実行できるdmake
ジョブの最大数を 8 個に設定しています。dmake.conf
ファイル
max_jobs: 8nice_prio: 5
構築サーバーとして使用するマシンは、次の条件を満たしている必要があります。
dmake
ホスト (使用するマシン) から、パスワードの入力を求められずにrsh
を使用して、構築サーバー上でコマンドを遠隔実行できること。rsh
(1) のマニュアルページを参照してください。以下に例を示します。
%rsh
build-serverwhich dmake
/opt/SUNWspro/bin/dmake- その構築サーバーから、
dmake
ソフトウェアがインストールされているbin
ディレクトリにアクセスできること。
すべての構築サーバーが同じdmake
インストールディレクトリを共有するようにしてください。share
(1M) およびmount
(1M) のマニュアルページを参照してください。dmake
から見て、デフォルトで、dmake
実行可能ファイルへの論理パスが構築サーバー上とdmake
ホスト上とで同じであること。
このデフォルト設定は、実行時構成ファイルのホストエントリの属性としてパス名を指定することによって変更できます。以下に例を示します。
group sparc-cluster {host wren { jobs = 10 , path = "/export/SUNWspro/bin"}host stimpy { path = "/opt/SUNWspro/bin" }- 構築するソースの階層構造が、構築サーバーで同じ名前でマウントされ、アクセスできること。
dmake
ユーティリティとメークファイル分散メークを実行するには、標準的な
make
ユーティリティの代わりにdmake
という実行可能ファイルを使用します。したがって、dmake
を使用する前に、Solaris のmake
ユーティリティについて理解しておく必要があります。make
ユーティリティの詳細については、Solaris のマニュアル『プログラミングユーティリティ』およびmake
(1) のマニュアルページを参照してください。これまでにmake
ユーティリティを使用したことがある場合は、ほとんど変更作業を伴わずに、dmake
に移行できます。この節では、
dmake
でのさまざまな問題の解決に役立つ方法と例を紹介します。必ずしもこれらの方法が最善の解決策であるとは限りませんが、できるだけわかりやすく機能が説明されています。手順が複雑になるに従って、これを実現するメークファイルも複雑になります。この節では一般的なコード開発の作業を進める上での問題点を取り上げ、
dmake
による簡単な解決方法について、例を紹介しながら説明します。プロジェクトの最初の段階からメークファイルテンプレートを利用するようにしてください。メークファイルテンプレートから作成することによって、実際のメークファイルが理解しやすく、統合、保守、再利用が容易になります。
ターゲットの並列構築
大規模なソフトウェア開発プロジェクトは、それぞれ独立した多数のモジュールで構成されるのが一般的です。これらのモジュールを、それぞれ分散させ、並列的に構築できます。こうした並列処理により、大規模な開発プロジェクトを構築するのに必要な時間が大幅に省けます。
dmake
は、構築するターゲットが与えられると、そのターゲットに関連する依存関係を調べ、同期の取れていない依存関係も構築します。この依存関係の構築では、依存関係の依存関係の構築を伴うこともあります。ジョブを分散する際、dmake
は起動可能なすべてのターゲットを起動します。それらのターゲットが終了すると、dmake
はその他のターゲットを起動します。デフォルトでは、入れ子構造になったdmake
の呼び出しは同時には実行されません。ただし、この設定は変更可能です (詳細については、「並列処理に対する制限」を参照)。
dmake
では複数のターゲットが並列に構築されるため、各構築プロセスの出力は同時に生成されます。各コマンドからの出力が混ざらないよう、dmake
では各構築の出力を個別に収集します。またdmake
は、コマンドを実行する前に、そのコマンドの内容を表示します。実行したコマンドによって出力、警告、またはエラーが生成されると、dmake
ユーティリティは該当するコマンドの出力全体を表示します。後から開始したコマンドが先行するコマンドよりも先に終了することもあるので、出力の順序が予想と異なる場合があります。メークファイルに対する制限事項
複数のターゲットを同時に構築する場合は、メークファイルに多少の制限が伴います。たとえば、暗黙の依存関係の順序に依存しているメークファイルは、並列構築を行なったとき正しく機能しないことがあります。また同じファイルの修正を行うターゲットがあり、これらファイルが 2 つの異なるターゲットで同時に変更されると、メークファイル中のターゲットで問題が起きることがあります。この節では、こうした問題の例を取り上げます。
依存関係リスト
ターゲットの並列構築をするときは、依存関係リストが正確であることが重要なポイントになります。たとえば、 2 つの実行可能ファイルが同じオブジェクトファイルを共有しているときに、一方のファイルでしか依存関係が指定されていないと、並列構築がエラーになる可能性があります。次のメークファイルの例を考えてみます。
all: prog1 prog2prog1: prog1.o aux.o$(LINK.c) prog1.o aux.o -o prog1prog2: prog2.o$(LINK.c) prog2.o aux.o -o prog2逐次構築では、ターゲット
aux.o
はprog1
に依存するファイルとして構築され、prog2
の構築時に利用されます。これに対し、並列構築では、prog2
のリンクが、aux.o
の構築前に開始されることがあり、その場合は、不正になります。make
の.KEEP_STATE
機能で検出できる依存関係も一部ありますが、上記のような関係はその対象にはなりません。依存関係リストにおける依存関係の順序指定
次に、暗黙の順序にもとづく依存関係がある場合は、問題がさらに複雑になるという例を示します。たとえば、あるシステムのヘッダーをすべて作成してから構築を開始する場合は、すべての要素がこの構築に依存していなければなりません。このため、メークファイルがさらに複雑になり、新しいターゲットをメークファイルに追加した場合などにエラーが起きる可能性が高くなります。この場合は、メークファイルの中で特殊な
.WAIT
ターゲットを指定して、暗黙の依存関係があることを明示できます。dmake
により依存関係リストの中に.WAIT
ターゲットが検出されると、これまでの依存関係の処理を一時停止してから、以降の依存関係の処理を実行するようになります。 1 つの依存関係リストに、複数の.WAIT
ターゲットを入れることもできます。次に、.WAIT
を使用して、まずヘッダーを作成してから、以降の処理を続行する例を示します。
all: hdrs .WAIT libs functions
.WAIT
ターゲットに適用する空の規則をメークファイルに追加することによって、make
ユーティリティでも、このメークファイルを使用できます。ファイルの同時修正
ターゲットの構築プロセスでは、同時に同じファイルを修正しないように注意する必要があります。この問題は、さまざまな形で起きる可能性があります。一時ファイルを使用する新しい接尾辞の規則を定義する場合、一時ファイルの名前は、ターゲットごとに異なっていなければなりません。この場合は、
$@
や$*
の動的マクロを利用できます。たとえば、ソースファイルをコンパイルする前に.c
ファイルに修正を加える場合、.c.o
の規則は次のように定義できます。
.c.o:awk -f modify.awk $*.c > $*.mod.c$(COMPILE.c) $*.mod.c -o $*.o$(RM) $*.mod.cライブラリの同時更新
並列処理でもう 1 つの問題になる可能性があるのは、ライブラリを作成するときのデフォルトの規則です。すなわち、ライブラリという固定ファイルが変更される場合があるということです。本来適用されるべきでない
.c.a
規則によって、dmake
がそれぞれのオブジェクトファイルを構築し、このオブジェクトファイルをアーカイブする可能性があります。dmake
が 2 つのオブジェクトファイルを同時にアーカイブすると、並列的に更新が行われてアーカイブファイルが壊れることがあります。
.c.a:$(COMPILE.c) -o $% $<$(AR) $(ARFLAGS) $@ $%$(RM) $この場合は、各オブジェクトファイルを構築し、その構築が完了した後、すべてのオブジェクトファイルをアーカイブするようにします。正しい接尾辞の規則と対応するライブラリの規則は次のとおりです。
.c.a:$(COMPILE.c) -o $% $<lib.a: lib.a($(OBJECTS))$(AR) $(ARFLAGS) $(OBJECTS)$(RM) $(OBJECTS)複数のターゲット
ファイルの同時更新の問題は、同じ規則を複数のターゲットに対して定義した場合にも起きます。たとえば、
lex(1)
で使用できるプログラムとヘッダーの両方を構築するyacc(1)
というプログラムがあります。 1 つの規則にもとづいて複数のターゲットファイルを構築する場合は、+
記号を使用して各ファイルを 1 つのグループとして指定する必要があります。特に、並列構築の場合に、このことが重要になります。
y.tab.c y.tab.h: parser.y$(YACC.y) parser.yこの規則は、次のように 2 つの規則が指定された場合と同等になります。
y.tab.c: parser.y$(YACC.y) parser.yy.tab.h: parser.y$(YACC.y) parser.y逐次処理の
make
は、最初の規則に基づいてy.tab.c
を作成してから、y.tab.h
が最新であり、構築の必要がないと判断します。これに対し、並列構築では、yacc
がy.tab.c
の構築を完了する前にy.tab.h
を調べるため、y.tab.h
の構築が必要であると判断し、最初のyacc
と並行して別のyacc
を起動します。両方のyacc
が同じファイル (y.tab.c
とy.tab.h
) に書き込みを行うため、これらのファイルが壊れ、不正になる可能性があります。正しい規則では、次の例に示すように、+
構文を使用して、両方のターゲットを同じ規則に従って同時に作成するように指示します。
y.tab.c + y.tab.h: parser.y$(YACC.y) parser.y並列処理に対する制限
メークファイルでファイルの衝突が避けられない場合があります。その 1 つの例が、C プログラムから文字列を抽出して共有文字列を生成する
xstr(1)
コマンドです。xstr
コマンドでは、変更した C プログラムをx.c
という固定したファイルに書き出し、抽出した文字列はxs.c
という固定ファイルに書き出します。xstr
は C ファイル単位で実行する必要があるため、次の新しい.c.o
規則がよく定義されます。
.c.o:$(CC) $(CPPFLAGS) -E $*.c | xstr -c -$(CC) $(CFLAGS) $(TARGET_ARCH) -c x.cmv x.o $*.oこの場合、各ターゲットを作成するごとに、
x.c
とxs.c
という同じファイルに書き出しを行うので、dmake
ユーティリティは上の規則に基づいてターゲットを同時に構築することはできません。また、使用するファイルを変更することもできません。この場合は、.NO_PARALLEL:
という特殊なターゲットを使用して、dmake
に各ターゲットを同時に構築しないように指示できます。たとえば、.c.o
規則を使用して構築するオブジェクトをOBJECTS
マクロで定義している場合は、次のようにして、各ターゲットを逐次構築するようdmake
に指示します。
.NO_PARALLEL: $(OBJECTS)大部分のオブジェクトを逐次構築する必要がある場合は、依存関係のない
.NO_PARALLEL:
ターゲットを含めることによって、全オブジェクトをデフォルトで強制的に逐次処理するようにした方が、安全で簡単です。並列構築できるターゲットは、次のように.PARALLEL:
ターゲットに依存するファイルとして記述できます。
.NO_PARALLEL:.PARALLEL: $(LIB_OBJECT)
dmake
が、さらに別のdmake
コマンドを呼び出すターゲットを検出すると、並列ではなく、逐次にターゲットが作成されます。これにより、 2 つの異なるdmake
によって、同じディレクトリ中の同じターゲットが構築されなくなります。このような問題は、 2 つの異なるプログラムを並列構築して、両方が同じライブラリにアクセスする場合などに起きます。それぞれのdmake
の呼び出しで、必ず最新のライブラリを適用するには、dmake
を再帰的に呼び出して、ライブラリを構築する必要があります。dmake
ユーティリティは、コマンド行から$(MAKE)
マクロが使用されている場合にのみ、入れ子になった呼び出しを認識します。コマンドを入れ子にしても、衝突することがない確信がある場合は、
.PARALLEL:
構文を使用して並列処理できます。メークファイルの中に、並列的に同時に動作する入れ子のコマンドが多数含まれている場合は、負荷均衡アルゴリズムによって、多数の構築ジョブがローカルのマシンに割り当てられることがあります。この結果、スワップ空間の不足といった別の問題が生じたり、負荷が大きくなったりすることも考えられます。こうした問題が起きた場合は、入れ子にしたコマンドをすべて逐次実行されるようにしてください。
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |