Sun WorkShop TeamWare ユーザーズガイド ホーム目次前ページへ次ページへ索引


第 10 章

dmake ユーティリティの使用

この章では、分散メーク (dmake) ユーティリティで構築プロセスを複数のホストに分散し、複数のワークステーションやマルチプロセッサ上で並列的にプログラムを構築する方法について説明します。

この章は、次の節で構成されています。

dmake の基礎

分散メーク (dmake) を使用して、多数のプログラムから構成される大規模なプロジェクトを構築する処理を、複数のワークステーション上、またはマルチプロセッサシステムの複数の CPU 上に分散できます。dmake ユーティリティは、メークファイルを解析して次のことを行います。

dmake ユーティリティは、make ユーティリティのスーパーセットです。

dmake を理解するためには、次の事柄についての知識が必要です。

構成ファイル

dmake ユーティリティは、どの構築サーバーにジョブを分散するか、また各サーバーにどれだけのジョブを分散するかを決定する際に、2 つのファイルを参照します。

実行時構成ファイル

dmake ユーティリティは、dmake ホスト上の実行時構成ファイルから、ジョブの分散先に関する情報を得ます。通常、このファイルは dmake ホストのホームディレクトリに .dmakerc という名前で格納されています。このファイルには、構築サーバーおよび各構築サーバーに分散できるジョブ数が記述されています。詳細は、「dmake ホスト」を参照してください。

構築サーバーの構成ファイル

それぞれの分散構築に使用する構築サーバーには、必ず /etc/opt/SPROdmake/dmake.conf ファイルが存在している必要があります。このファイルは、dmake ユーザーが全体として各構築サーバーに割り当てることができる dmake ジョブの最大数を指定します。また、すべての dmake ジョブの実行に適用される nice 優先度も指定できます。

詳細は、「構築サーバー」を参照してください。

dmake ホスト

dmake ホストとは、dmake コマンドが最初に起動されるマシンです。dmake ユーティリティは、実行時構成ファイルの内容に基づいて、ジョブをどこに分散するかを決定します。一般に、このファイルは、dmake ホストのホームディレクトリ内に、.dmakerc という名前で置かれている必要があります。dmake ユーティリティは、以下の順序で実行時構成ファイルを探します。

  1. コマンド行で -c オプションを使用して指定されたパス名

  2. DMAKE_RCFILE という名のメークファイルマクロを使用して指定されたパス名

  3. DMAKE_RCFILE 環境変数を使用して指定されたパス名

  4. $(HOME)/.dmakerc

実行時構成ファイルが見つからない場合、dmake ユーティリティは dmake ホストに 2 つのジョブを割り当てます。

実行時構成ファイルによって、各構築サーバーのリストと各構築サーバーに分散するジョブの数を指定できます。次に、.dmakerc ファイルの例を示します。

# My machine. This entry causes dmake to distribute to it.
falcon { jobs = 1 }
hawk
eagle  { jobs = 3 }
# Manager's machine. She's usually at meetings
hero   { jobs = 4 }
avocet

コード例 10-1   dmakerc ファイル

実行時構成ファイルには、構築サーバーのグループを設定することもできます。この方法によって、状況に応じて構築サーバーのグループを簡単に切り替えることができます。たとえば、異なるオペレーティングシステムでの構築処理ごとにユーザーが構築サーバーグループを定義したり、特殊なソフトウェアがインストールされている構築サーバーのグループを定義したりできます。

次に、構築サーバーのグループが定義されている実行時構成ファイルの例を示します。

earth  { jobs = 2 }
mars   { jobs = 3 }

 
group lab1 {
        host falcon { jobs = 3 }
        host hawk
        host eagle  { jobs = 3 }
}

 
group lab2 {
        host heron
        host avocet { jobs = 3 }
        host stilt  { jobs = 2 }
}

 
group labs {
        group lab1
        group lab2
}

 
group sunos5.x {
        group labs
        host jupiter
        host venus { jobs = 2 }
        host pluto { jobs = 3 }
}

dmake ユーティリティは、次の優先順位に従ってジョブを分散します。

  1. コマンド行で -g オプションの引数として指定されたグループ

  2. DMAKE_GROUP という名のメークファイルマクロを使用して指定されたグループ

  3. DMAKE_GROUP 環境変数を使用して指定されたグループ

  4. 実行時構成ファイルで最初に指定されたグループ

dmake ユーティリティは、構築サーバーごとに異なる実行パスを指定できます。デフォルトでは、dmake は、dmake ホストと同じ論理パスを使用して、構築サーバー上の dmake サポートバイナリファイルを検索します。次のように、.dmakerc ファイルで構築サーバー用の別のパスをホスト属性として指定できます。

group lab1 {
      host falcon { jobs = 10 , path = "/set/dist/sparc-S2/bin" }
      host hawk   { path = "/opt/SUNWspro/bin"                  }
}

.dmakerc ファイルでは、グループ名およびホスト名を二重引用符で囲むことができます。文字列の一部として二重引用符を使用することで、グループおよびホストに付ける名前の制約が緩和されます。数字も英字と同様に使用できるようになります。数字で始まる名前は、次のように、二重引用符で囲む必要があります。

group "123_lab" {
       host "456_hawk" { path = "/opt/SUNWspro/bin"             }
}

構築サーバー

構築サーバーのファイルシステム内に /etc/opt/SPROdmake/dmake.conf というファイルがあります。このファイルは、この構築サーバーでユーザーが全体として並行して実行できる dmake ジョブの最大数を指定するために使用します。また、すべての dmake ジョブの実行に適用される nice 優先度も指定できます。次に /etc/opt/SPROdmake/dmake.conf ファイルの例を示します。このファイルでは、1 つの構築サーバーで実行可能な (すべての dmake ユーザーからの) dmake ジョブの最大数を、 8 に設定しています。

max_jobs: 8
nice_prio: 5


注 - 構築サーバーに /etc/opt/SPROdmake/dmake.conf ファイルが存在しない場合、そのサーバーで、dmake ジョブを実行することはできません。

dmake ユーティリティについて

分散メークを実行するには、標準の make ユーティリティの代わりに、dmake を使用します。dmake を使用する前に、Solaris の make ユーティリティを理解しておく必要があります。make ユーティリティについての詳細は、Solaris の『プログラミングユーティリティ』を参照してください。make ユーティリティを使用している場合、ほとんど変更なしで dmake を使用できます。

dmake ユーティリティがメークファイルに与える影響

この節では、dmake で解決可能な種類の問題を例に挙げて説明します。手続きが複雑になるにしたがって、それらを実装するメークファイルの内容も複雑になります。適切なメークファイルをもたらす方法を知る必要があります。この節では、一般的なコード開発の例を挙げ、dmake を使用して作業を簡略化する方法を説明します。

メークファイルテンプレートの使用

プロジェクトを開始する時点でメークファイルテンプレートを使用することがわかっている場合は、メークファイルテンプレートをカスタマイズして独自のメークファイルを作成すると、次の利点があります。

メークファイルの編集にかかる時間を節約し、プログラムやプロジェクトの開発により多くの時間を費やすことができます。

ターゲットの並列構築

一般的に、大規模なソフトウェア開発プロジェクトは、並列して構築できる独立した多数のモジュールで構成されています。dmake ユーティリティは、ネットワークにまたがった複数のマシン上でのターゲットの並列処理を行うことができます。こうした並列処理により、大規模な開発プロジェクトを構築するのに必要な時間が大幅に省けます。

dmake は、構築するターゲットが与えられると、そのターゲットに関連する依存関係を調べ、古くなっている依存関係を構築します。この依存関係の構築では、依存関係の依存関係の構築を伴うこともあります。ジョブを分散する際、dmake は開始可能なすべてのターゲットを開始します。それらのターゲットが終了すると、dmake はその他のターゲットを起動します。デフォルトでは、入れ子構造になった dmake の呼び出しは同時には実行されません。ただし、この設定は変更可能です (詳細は、「並列処理に対する制限」を参照)。

dmake では複数のターゲットが並列に構築されるため、各構築プロセスの出力は同時に生成されます。各コマンドからの出力が混ざらないよう、dmake では各構築の出力を個別に収集します。また dmake は、コマンドを実行する前に、そのコマンドの内容を表示します。実行したコマンドによって出力、警告、またはエラーが生成されると、dmake ユーティリティは該当するコマンドの出力全体を表示します。後から開始したコマンドが先行するコマンドよりも先に終了することもあるので、出力の順序が予想と異なる場合があります。

メークファイルに関する制限事項

複数のターゲットを同時に構築する場合は、メークファイルに多少の制限が伴います。たとえば、暗黙の依存関係の順序に依存しているメークファイルは、並列構築を行なったとき正しく機能しないことがあります。また、同じファイルを修正する複数のターゲットは、そのファイルが 2 つの異なるターゲットによって同時に変更されると失敗することがあります。この節では、こうした問題の例を取り上げます。

依存関係リスト

ターゲットを並列構築するときは、依存関係リストが正確であることが重要なポイントになります。たとえば、 2 つの実行可能ファイルが同じオブジェクトファイルを共有しているときに、一方のファイルでしか依存関係が指定されていないと、並列構築がエラーになる可能性があります。次のメークファイルの例を考えてみます。

all: prog1 prog2 
prog1: prog1.o aux.o 
    $(LINK.c) prog1.o aux.o -o prog1 
prog2: prog2.o 
    $(LINK.c) prog2.o aux.o -o prog2 

逐次構築では、ターゲット aux.oprog1 に依存するファイルとして構築され、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 $% $< 
    $(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.y
y.tab.h: parser.y
    $(YACC.y) parser.y

逐次処理の make は、最初の規則に基づいて y.tab.c を作成してから、y.tab.h が最新であり、構築の必要がないと判断します。これに対し、並列構築では、 yaccy.tab.c の構築を完了する前に y.tab.h を調べるため、y.tab.h の構築が必要であると判断し、最初の yacc と並行して別の yacc を起動します。両方の yacc が同じファイル (y.tab.cy.tab.h) に書き込みを行うため、これらのファイルが壊れ、不正になる可能性があります。正しい規則では、次の例に示すように、+ 構文を使用して、両方のターゲットを同じ規則に従って同時に作成するように指示します。

y.tab.c + y.tab.h: parser.y
    $(YACC.y) parser.y

並列処理に対する制限

1 つのメークファイルの中でファイルの衝突が避けられない場合があります。その 1 つの例が、C プログラムから文字列を抽出して、共有文字列を生成する xstr(1) コマンドです。xstr コマンドでは、変更された C プログラムは x.c という固定したファイルに書き込まれ、抽出した文字列は strings という固定ファイルに追加されます。xstr は C ファイルごとに実行する必要があるため、次の新しい .c.o 規則がよく定義されます。

.c.o:
    $(CC) $(CPPFLAGS) -E $*.c | xstr -c - 
    $(CC) $(CFLAGS) $(TARGET_ARCH) -c x.c
    mv x.o $*.o

この場合、各ターゲットを作成するごとに、x.cstrings という同じファイルに書き込みを行うので、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 を再帰的に呼び出してライブラリを構築できます。コマンド行で $(MAKE) マクロを指定した場合のみ、dmake ユーティリティは入れ子呼び出しを認識できます。

入れ子にしたコマンドが衝突を起こさないと分かっている場合は、.PARALLEL: を使用して、強制的に並列構築が行われるように設定できます。

メークファイルの中に、並行して実行される入れ子のコマンドが多数含まれている場合、負荷均衡アルゴリズムが、強制的にローカルマシンに構築処理を過剰に割り当ててしまうことがあります。これによって、負荷が大きくなったり、スワップ領域が不足するなどの問題を引き起こすことがあります。こうした問題が発生した場合は、入れ子にしたコマンドを逐次実行するようにしてください。

dmake ユーティリティの使用方法

dmake ホストで dmake コマンドを実行すると、構築サーバーにジョブが分散されます。また、dmake ホストにジョブを分散することもできます。この場合、dmake ホストも構築サーバーとみなされます。dmake ユーティリティは、(メークファイルをもとにして) 並行構築が可能であると判断したターゲットに基づいて、ジョブを分散します。次の条件を満たしているマシンを、構築サーバーとして使用できます。

dmake ホストから、使用する構築サーバーと各構築サーバーに割り当てる dmake ジョブの数を制御できます。特定の構築サーバーで実行可能な dmake ジョブの数は、その構築サーバー上でも制限できます。

-m オプションと parallel 引数を指定した場合、または DMAKE_MODE 変数またはマクロの値として parallel を設定している場合、dmake は、実行時構成ファイルをスキャンしません。このため、ジョブの数は、-j オプション、DMAKE_MAX_JOBS 変数またはマクロを使用して指定する必要があります。このどの方法でもジョブ数を指定しなかった場合は、デフォルトのジョブ数の 2 が使用されます。

dmake を分散モードで使用している時に、-j オプション、DMAKE_MAX_JOBS 変数またはマクロを使用してジョブの最大数を変更した場合、指定した値が実行時構成ファイルで設定されている値の代わりにしようされます。指定した値は、すべての構築サーバーへ分散可能なジョブ数の合計値として使用されます。

「構築」ウィンドウから dmake を使用する場合は、オンラインヘルプで構築サーバーとジョブ数の指定方法についての説明を参照してください。コマンド行から dmake を使用する場合は、dmake(1) のマニュアルページ (dmake.1) を参照してください。


サン・マイクロシステムズ株式会社
Copyright information. All rights reserved.
ホーム   |   目次   |   前ページへ   |   次ページへ   |   索引