Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

複数のデータセットでの単一プログラムの実行

はじめに

Single Program Multiple Data (spmd) 言語構成を使用すると、逐次プログラミングと並列プログラミングをシームレスにインターリーブできます。spmd ステートメントには、複数のワーカーで同時に実行されるコード ブロックを定義できます。ワーカーの spmd ステートメント内で割り当てられた変数の値には、Composite (複合) オブジェクトを介した参照によってクライアントから直接アクセスできます。

この章では、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 検索パスが設定されていなければなりません。このため、クライアントで cdaddpath または rmpath を使用する場合、そのコマンドは可能な範囲ですべてのワーカーでも実行されます。詳細については、parpool のリファレンス ページを参照してください。ワーカーをクライアントと異なるプラットフォームで実行する場合は、関数 pctRunOnAll を使用してすべてのワーカーに MATLAB パスを適切に設定してください。

エラー処理

spmd ステートメントの実行中にワーカーで発生したエラーは、クライアントにレポートされます。クライアントはすべてのワーカーでの実行の中断を試み、ユーザーにエラーをスローします。

ワーカーで生成されたエラーと警告にはワーカー ID (spmdIndex) が付けられ、MATLAB クライアントで受信された順にクライアントのコマンド ウィンドウに表示されます。

lastwarnspmd 本体内で使用されている場合、その動作は spmd の最後では指定されません。

spmd の制限

入れ子関数

関数内の spmd ステートメントの本体から入れ子関数を参照することはできません。ただし、入れ子関数の関数ハンドルとして定義された変数を使用して入れ子関数を呼び出すことはできます。

spmd 本体はワーカーで実行されるため、spmd ステートメント内で呼び出される入れ子関数で変数が更新されても、その変数は外側の関数のワークスペースで更新されません。

入れ子にされた spmd ステートメント

spmd ステートメントの本体に別の spmd を直接含めることはできません。ただし、別の spmd ステートメントを含む関数を呼び出すことはできます。内側の spmd ステートメントは別の並列プールでは並列実行されず、そのステートメントが含まれる関数を実行するワーカーのシングル スレッドで逐次実行されます。

入れ子にされた parfor ループ

spmd ステートメントに parfor ループを含めることはできず、parfor ループの本体に spmd ステートメントを含めることはできません。その理由は、ワーカーからさらに並列プールを起動したり、並列プールにアクセスしたりすることができないためです。

breakcontinue および return ステートメント

spmd ステートメントの本体に、breakcontinue または 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 に代入しなければなりません。

参考

| | | | |

関連するトピック