ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

並列ソリューションの紹介

対話形式でのループの並列実行

この節では、簡単な for ループを並列実行できるように変更する方法を示します。このループに多数の反復はなく実行には長時間を要しませんが、同じ原理をより大きなループに適用できます。もっとも、このような簡単な例では、実行速度の上昇に気付かないかもしれません。

  1. 正弦波を作成して波形をプロットするループがコードに含まれているとします。

    for i = 1:1024
      A(i) = sin(i*2*pi/1024);
    end
    plot(A)
  2. parfor ステートメントを使用すると、ループを並列で実行するようコードを変更できます。

    parfor i = 1:1024
      A(i) = sin(i*2*pi/1024);
    end
    plot(A)

    このループの唯一の相違点は、キーワードが for ではなく parfor であることです。ループが開始されると、反復を並列実行するためのワーカーと呼ばれる MATLAB® セッションの並列プールが開きます。ループを実行すると、その結果は前の for ループで生成された結果と同じように見えます。

    反復は他の MATLAB セッション内で並列実行されるため、個々の反復は他のすべての反復から完全に独立していなければなりません。A(100) の値を計算するワーカーは A(500) を計算するワーカーと同じでない可能性があります。順序は保証されないため、A(400) の前に A(900) が計算される可能性があります(MATLAB エディターを使うと、独立した反復を含んでいない可能性がある parfor コードの問題を特定しやすくなります)。データが MATLAB ワーカーから返されてループが完了すると、配列 A の全要素の値を利用できる場所は MATLAB クライアントのセッション内のみとなります。

parfor ループについての詳細は、「並列 for ループ (parfor)」を参照してください。

クラスター プロファイルを変更すると、ループを実行するワーカーの数と、ワーカーをローカルまたはクラスターのどちらに配置するかを制御できます。プロファイルについての詳細は、クラスターとクラスター プロファイルを参照してください。

並列設定を変更して、並列プールを自動作成するかどうかと、タイムアウトまでの時間を制御することができます。設定についての詳細は、並列設定を参照してください。

sim コマンドをループ内で使用して、Simulink® モデルを並列ループの反復で実行できます。parfor と Simulink の併用についての詳細および例は、Simulink ドキュメンテーションの「並列シミュレーションの実行」を参照してください。

バッチ ジョブの実行

batch コマンドを使用すると、MATLAB セッションの負荷をオフロードして別のセッションでバックグラウンドで実行することができます。この例では、前の例の for ループをスクリプト内で使用します。

  1. スクリプトを作成するには、次のように入力します。

    edit mywave
  2. MATLAB エディターで、for ループのソース コードを入力します。

    for i = 1:1024
      A(i) = sin(i*2*pi/1024);
    end
  3. ファイルを保存してエディターを閉じます。

  4. MATLAB コマンド ウィンドウで batch コマンドを使用して、独立した MATLAB ワーカーでスクリプトを実行します。

    job = batch('mywave')

  5. batch コマンドは MATLAB をブロックしないため、結果を取得して表示するには、ジョブが完了するまで待機しなければなりません。

    wait(job)
  6. load コマンドによって、ワーカーで作成された変数がクライアント ワークスペースに転送され、そこで結果を表示することができます。

    load(job,'A')
    plot(A)
  7. ジョブが完了したら、そのデータを永久的に削除し、その参照をワークスペースから削除します。

    delete(job)
    clear job

batch はコードをローカル ワーカーまたはクラスター ワーカーで実行しますが、並列プールは必要ではありません。

batch を使用してスクリプトまたは関数を実行できます。詳細は、関数 batch のリファレンス ページを参照してください。

バッチ並列ループの実行

ジョブをオフロードする機能と並列ループを実行する機能は組み合わせることができます。前の 2 つの例では for ループを変更して parfor ループを作成し、for ループを伴うスクリプトをバッチ ジョブとして投入しました。この例では、これら 2 つを組み合わせてバッチの parfor ループを作成します。

  1. MATLAB エディターでスクリプトを開きます。

    edit mywave
  2. スクリプトを変更して for ステートメントを parfor ステートメントにします。

    parfor i = 1:1024
      A(i) = sin(i*2*pi/1024);
    end
  3. ファイルを保存してエディターを閉じます。

  4. 前と同様に MATLAB で batch コマンドを使用してスクリプトを実行しますが、スクリプトでこのループに並列プールを使用するよう指定しておきます。

    job = batch('mywave','Pool',3)

    このコマンドでは、(バッチ スクリプトを実行するワーカーの他に) 3 つのワーカーでループ反復を評価するよう指定しています。したがって、この例ではバッチ スクリプトを実行する 1 つのワーカーを含め、合計で 4 つのローカル ワーカーを使用します。次の図のように、実行される MATLAB セッションは全部で 5 つあります。

  5. 結果を表示するには、以下を入力します。

    wait(job)
    load(job,'A')
    plot(A)

    結果は前と同じように見えますが、実行方法に 2 つの重要な違いがあります。

    • parfor ループを定義して結果を累積する作業が batch により別の MATLAB セッションにオフロードされる。

    • ループの反復が、1 つの MATLAB ワーカーから同時実行される別の一連のワーカーに分散されるため ('Pool'parfor)、ループがただ 1 つのワーカーで実行される場合より高速で実行される可能性がある。

  6. ジョブが完了したら、そのデータを永久的に削除し、その参照をワークスペースから削除します。

    delete(job)
    clear job

現在のフォルダー ブラウザーでのスクリプトのバッチ ジョブとしての実行

現在のフォルダー ブラウザーから MATLAB スクリプトをバッチ ジョブとして実行できます。それには、ファイルのフォルダーを参照し、ファイルを右クリックして [バッチ ジョブとしてスクリプトを実行] を選択します。バッチ ジョブは既定のクラスター プロファイルにより指定されているクラスター上で実行されます。次の図はスクリプト ファイル script1.m を実行するメニュー オプションを示しています。

ブラウザーからスクリプトをバッチとして実行する際は、クラスターのワーカーを 1 つだけ使用します。このため、スクリプトに parfor ループまたは spmd ブロックが含まれている場合でも、クラスターのワーカー プールが追加で開くことはありません。こうしたコード ブロックはバッチ ジョブに使用される単一のワーカーで実行されます。バッチ スクリプトで追加のワーカー プールを開く必要がある場合は、バッチ並列ループの実行で説明したように、コマンド ラインから実行できます。

ブラウザーからバッチ ジョブを実行する場合は、Job Monitor も開かれます。Job Monitor はスケジューラ キューのジョブを追跡できるツールです。Job Monitor とその機能についての詳細は、Job Monitorを参照してください。

配列の分散および SPMD の実行

分散配列

並列プールのワーカーは相互に通信を行うので、配列を複数のワーカーに分散することが可能となります。各ワーカーは配列の一部を保持し、どのワーカーも、各ワーカーが配列のどの部分を保持しているかを認識しています。

関数 distributed を使用して配列をワーカー間に分散します。

M = magic(4) % a 4-by-4 magic square in the client workspace
MM = distributed(M)

ここで、MMM と等価な分散配列であり、他の配列と同様にその要素の操作や要素へのアクセスを行うことができます。

M2 = 2*MM;  % M2 is also distributed, calculation performed on workers
x = M2(1,1) % x on the client is set to first element of M2

Single Program Multiple Data (spmd)

Single Program Multiple Data (spmd) 構成を使用すると、並列プールのすべてのワーカーで並列に実行されるコード ブロックを定義できます。spmd ブロックはプール内の一部またはすべてのワーカーで実行できます。

spmd     % By default creates pool and uses all workers
    R = rand(4);
end

このコードによりプールの各ワーカーで、乱数からなる 4 行 4 列の行列 R が個別に作成されます。

Composite

spmd ステートメントの後、クライアントでは、ブロックからの値が実際にはワーカーに保存されているときでもそのデータにアクセスできます。クライアントでは、こうした変数は Composite (複合) オブジェクトと呼ばれます。Composite の各要素は、プールのワーカーにある値 (データ) を参照する記号です。変数が一部のワーカーで定義されていないために、Composite に未定義の要素が含まれる場合があることに注意してください。

上記の例に戻ると、クライアントにおいて、Composite R にはワーカーごとに 1 つの要素があります。

X = R{3};  % Set X to the value of R from worker 3.

上のコードでは、ワーカー 3 からデータを取得して X の値に代入します。次のコードはデータをワーカー 3 に送信します。

X = X + 2;
R{3} = X; % Send the value of X from the client to worker 3.

並列プールが spmd ステートメント間で開いたままで同じワーカーが使用される場合、各ワーカーのデータは spmd ステートメント間で保持されます。

spmd
    R = R + labindex  % Use values of R from previous spmd.
end

spmd の典型的な使用方法は、同じコードを、異なるデータセットにアクセスする複数のワーカーで実行することです。以下に例を示します。

spmd
    INP = load(['somedatafile' num2str(labindex) '.mat']);
    RES = somefun(INP)
end

これにより、ワーカー 1 の RES{1}、ワーカー 2 の RES{2} など、ワーカー上の RES の値がクライアントからアクセス可能になります。

セル配列にインデックスを付ける場合と同様に、Composite にインデックスを付ける方法には 2 とおりあります。

  • AA{n} はワーカー n から AA の値を返します。

  • AA(n) はワーカー n から AA の内容のセル配列を返します。

並列プールが開いている限り、データは spmd ブロック間でワーカーに保持されますが、並列プールのインスタンス間では保持されません。すなわち、プールが削除されてから新規のプールが作成された場合、最初のプールのデータはすべて失われます。

分散配列、spmd および Composite の使用方法についての詳細は、「分散配列 および SPMD」を参照してください。

この情報は役に立ちましたか?