| 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) のマニュアルページを参照してください。以下に例を示します。
%rshbuild-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. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |