このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
複数のデータセットでの単一プログラムの実行
はじめに
Single Program Multiple Data (spmd) 言語構成を使用すると、逐次プログラミングと並列プログラミングをシームレスにインターリーブできます。spmd
ステートメントには、複数のワーカーで同時に実行されるコード ブロックを定義できます。ワーカーの spmd
ステートメント内で割り当てられた変数の値には、Composite (複合) オブジェクトを介した参照によってクライアントから直接アクセスできます。
どのような時に spmd を使用するか
spmd における "single program (単一プログラム)" の側面は、同一のコードが複数のワーカーで実行されるということです。MATLAB® クライアントで 1 つのプログラムを実行すると、spmd
ブロックというラベルが付いたそのプログラムの部分がワーカーで実行されます。spmd ブロックが完了すると、プログラムはクライアントでの実行を継続します。
"multiple data (複数のデータ)" の側面は、spmd
ステートメントによりすべてのワーカーで同一コードが実行されても、そのコードに対しワーカーごとに固有の異なるデータを使用できるということです。このため、複数ワーカーによる複数データセットへの対応が可能になります。
spmd
に適した典型的アプリケーションは、ワーカー間で通信または同期が必要な場合に複数のデータセットに対してプログラムの同時実行が必要なアプリケーションです。一般的なケースとして以下が挙げられます。
実行に長時間かかるプログラム —
spmd
を使用すると、複数のワーカーで同時に解を計算できます。大規模なデータセットを扱うプログラム —
spmd
によってデータを複数のワーカーに分散できます。
詳細については、spmd、parfor、および parfeval からの選択を参照してください。
spmd ステートメントの定義
spmd
ステートメントの一般的な形式は、次のとおりです。
spmd <statements> end
メモ
並列プールが実行されていない場合、並列基本設定が適切に設定されていれば、spmd
は既定のクラスター プロファイルを使用してプールを作成します。
<statements>
で表されるコード ブロックは、並列プール内のすべてのワーカーで同時に並列実行されます。実行をこれらのワーカーの一部に制限する場合は、実行に使用するワーカーの正確な数を指定します。
spmd (n) <statements> end
このステートメントは、n
個のワーカーが spmd
コードを実行するよう要求します。n
は開いている並列プール内のワーカーの数以下でなければなりません。プールは十分に大きいものの n
個のワーカーは使用可能でない場合、ステートメントは十分な数のワーカーが使用可能になるまで待機します。n
が 0 で、spmd
ステートメントがワーカーを使用せずにクライアントでローカルに実行される場合は、現在実行中のプールがない場合と同じになります。
ワーカー数の範囲を指定できます。
spmd (m,n) <statements> end
この場合、spmd
ステートメントには最低 m
個のワーカーが必要であり、最大で n
個のワーカーを使用します。
spmd
ステートメントを実行するワーカー数の制御が重要な場合は、範囲を使用するのでなく、正確な数をクラスター プロファイルか spmd
ステートメントで設定します。
たとえば、3 つのワーカー上に乱数行列を作成するには、以下を入力します。
spmd (3) R = rand(4,4); end
メモ
この章のこれ以降の例では、並列プールが既に開いており、spmd
ステートメントのシーケンスの合間も開いたままであることを前提としています。
parfor
ループと異なり、spmd
ステートメントに使用されるワーカーにはそれぞれ固有の spmdIndex
値があります。このため、通常は固有のデータにアクセスする目的で、コードが特定のワーカーのみで実行されるように、あるいは実行をカスタマイズするように指定できます。
たとえば、spmdIndex
に応じて異なるサイズの配列を作成します。
spmd (3) if spmdIndex==1 R = rand(9,9); else R = rand(4,4); end end
各ワーカーで spmdIndex
に応じた固有のデータを読み込み、各ワーカーで同じ関数を使用してデータから結果を算出します。
spmd (3) labdata = load(['datafile_' num2str(spmdIndex) '.ascii']) result = MyFunction(labdata) end
spmd
ステートメントを実行する複数のワーカーは同時に動作し、互いを認識しています。通信ジョブの場合と同様に、ワーカー間で直接に通信を制御し、データを転送し、対話型分散配列を使用することができます。
たとえば、spmd
ステートメントで対話型分散配列を使用します。
spmd (3) RR = rand(30, codistributor()); end
各ワーカーには対話型分散配列 RR
からの 30 行 10 列のセグメントがあります。対話型分散配列についての詳細は、対話型分散配列の取り扱いを参照してください。
出力の表示
並列プールで spmd
ステートメントを実行する場合、ワーカーからのコマンド ライン出力は、すべてクライアントのコマンド ウィンドウに表示されます。ワーカーは表示のない MATLAB セッションであるため、プールからはグラフィカルな出力 (Figure ウィンドウなど) は一切表示されません。
MATLAB パス
spmd
ステートメントを実行するすべてのワーカーは、共通のコード ブロック内で呼び出されるすべての関数を実行できるよう、クライアントと同じ MATLAB 検索パスが設定されていなければなりません。このため、クライアントで cd
、addpath
または rmpath
を使用する場合、そのコマンドは可能な範囲ですべてのワーカーでも実行されます。詳細は、parpool
のリファレンス ページを参照してください。ワーカーをクライアントと異なるプラットフォームで実行する場合は、関数 pctRunOnAll
を使用してすべてのワーカーに MATLAB パスを適切に設定してください。
エラー処理
spmd
ステートメントの実行中にワーカーで発生したエラーは、クライアントにレポートされます。クライアントはすべてのワーカーでの実行の中断を試み、ユーザーにエラーをスローします。
ワーカーで生成されたエラーと警告にはワーカー ID (spmdIndex
) が付けられ、MATLAB クライアントで受信された順にクライアントのコマンド ウィンドウに表示されます。
lastwarn
が spmd
本体内で使用されている場合、その動作は spmd の最後では指定されません。
spmd の制限
入れ子関数
関数内の spmd
ステートメントの本体から入れ子関数を参照することはできません。ただし、入れ子関数の関数ハンドルとして定義された変数を使用して入れ子関数を呼び出すことはできます。
spmd
本体はワーカーで実行されるため、spmd
ステートメント内で呼び出される入れ子関数で変数が更新されても、その変数は外側の関数のワークスペースで更新されません。
入れ子にされた spmd
ステートメント
spmd
ステートメントの本体に別の spmd
を直接含めることはできません。ただし、別の spmd
ステートメントを含む関数を呼び出すことはできます。内側の spmd
ステートメントは別の並列プールでは並列実行されず、そのステートメントが含まれる関数を実行するワーカーのシングル スレッドで逐次実行されます。
入れ子にされた parfor
ループ
spmd
ステートメントに parfor
ループを含めることはできず、parfor
ループの本体に spmd
ステートメントを含めることはできません。その理由は、ワーカーからさらに並列プールを起動したり、並列プールにアクセスしたりすることができないためです。
break
、continue
および return
ステートメント
spmd
ステートメントの本体に、break
、continue
または return
の各ステートメントを含めることはできません。spmd
の代わりとして parfeval
または parfevalOnAll
を検討してください。それらに対し cancel
を使用できるためです。
グローバル変数および永続変数
spmd
ステートメントの本体に、global
または persistent
の変数宣言を含めることはできません。その理由は、これらの変数がワーカー間で同期されないためです。関数内では global
変数または persistent
変数を使用できますが、それらの値はそれらの変数を作成するワーカーでのみ可視になります。global
変数の代わりに、関数の引数を使用して値を共有することをお勧めします。
無名関数
spmd
ステートメントの本体で無名関数を定義することはできません。ただし、関数ハンドルを使用して無名関数を参照することはできます。
関数 inputname
spmd
内で inputname
を使用して、引数番号に対応するワークスペース変数名を返すことはサポートされていません。その理由は、spmd
ワーカーが MATLAB デスクトップのワークスペースにアクセスできないためです。これに対処するには、次の例に示すように、spmd
の前に inputname
を呼び出します。
a = 'a'; myFunction(a) function X = myFunction(a) name = inputname(1); spmd X.(name) = spmdIndex; end X = [X{:}]; end
関数 load
spmd
ステートメント内で、出力構造体に代入しない load
の構文はサポートされていません。spmd
内では、必ず load
の出力を構造体に代入します。
関数 nargin
または関数 nargout
spmd
ステートメント内での次の使用はサポートされていません。
関数の引数を指定せずに
nargin
またはnargout
を使用する現在実行している関数の呼び出し内にある入力引数または出力引数の数を検証する目的で
narginchk
またはnargoutchk
を使用する
その理由は、ワーカーが MATLAB デスクトップのワークスペースにアクセスできないためです。これに対処するには、これらの関数を spmd
の前に呼び出します。
myFunction('a','b') function myFunction(a,b) nin = nargin; spmd X = spmdIndex*nin; end end
P コード スクリプト
spmd
ステートメント内から P コードのスクリプト ファイルを呼び出すことができますが、P コードのスクリプトに spmd
ステートメントを含めることはできません。これに対処するには、P コード スクリプトの代わりに P コード関数を使用します。
変数 ans
spmd
ステートメントの外部で定義された変数 ans
を、spmd
ステートメント内で参照することはサポートされていません。使用する前に、spmd
ステートメントの本体内で変数 ans
に代入しなければなりません。
参考
spmd
| parfor
| parfeval
| parfevalOnAll
| Composite