Main Content

並列ワーカーへの配列の分散

分散配列を使用したワーカー間でのデータの分割

データがメモリに収まるかどうかに応じて、次の方法のいずれかを選択します。

  • データが現在ローカル マシンのメモリにある場合は、関数 distributed を使用して、既存の配列をクライアント ワークスペースから並列プールのワーカーに分散することができます。このオプションは、repmat のように配列のサイズを大幅に増加させる操作のテストや、その操作の実行前に有用です。

  • データがローカル マシンのメモリに収まらないが、クラスターのメモリには収まる場合、datastore を関数 distributed と併用して、並列プールのワーカーのメモリにデータを読み込むことができます。

  • データがクラスターのメモリに収まらない場合、datastoretall 配列と併用してデータをチャンクに分割し、処理することができます。tall 配列およびデータ ストアを使用するビッグ データのワークフローも参照してください。

datastore を使用した分散配列の並列読み込み

データがローカル マシンのメモリに収まらないが、クラスターのメモリには収まる場合、datastore を関数 distributed と併用して分散配列を作成し、ワーカー間でデータを分割することができます。

次の例では、datastore を使用して分散配列を作成し、読み込む方法を説明します。航空会社のフライト データの表形式ファイルを使用して、データ ストアを作成します。このデータセットは小さすぎるため、ワーカー間でデータが均等に分割されません。大規模なデータセットをシミュレートするため、repmat を使用してデータ ストアのサイズを人為的に増加します。

files = repmat({'airlinesmall.csv'}, 10, 1);
ds = tabularTextDatastore(files);

例の変数を選択します。

ds.SelectedVariableNames = {'DepTime','DepDelay'};
ds.TreatAsMissing = 'NA';

データ ストアを並列で読み取ることにより分散テーブルを作成します。ワーカーごとに 1 パーティションとなるように、データ ストアを分割します。これにより、各ワーカーは対応するパーティションからすべてのデータを読み取ります。ファイルは、ワーカーがアクセスできる共有場所になければなりません。

dt = distributed(ds);
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.

分散テーブルに関する概要情報を表示します。

summary(dt) 
Variables:

    DepTime: 1,235,230×1 double
        Values:

            min          1
            max       2505
            NaNs    23,510

    DepDelay: 1,235,230×1 double
        Values:

            min      -1036
            max       1438
            NaNs    23,510

tall table のサイズを求めます。

size(dt) 
ans =

     1235230           2

dt の最初の数行を返します。

head(dt) 
ans =

    DepTime    DepDelay
    _______    ________

     642       12      
    1021        1      
    2055       20      
    1332       12      
     629       -1      
    1446       63      
     928       -2      
     859       -1      
    1833        3      
    1041        1      

最後に、各ワーカーが読み込んだデータ量をチェックします。

spmd, dt, end
Worker 1: 
  
  This worker stores dt2(1:370569,:).
  
          LocalPart: [370569×2 table]
      Codistributor: [1×1 codistributor1d]
  
Worker 2: 
  
  This worker stores dt2(370570:617615,:).
  
          LocalPart: [247046×2 table]
      Codistributor: [1×1 codistributor1d]
  
Worker 3: 
  
  This worker stores dt2(617616:988184,:).
  
          LocalPart: [370569×2 table]
      Codistributor: [1×1 codistributor1d]
  
Worker 4: 
  
  This worker stores dt2(988185:1235230,:).
  
          LocalPart: [247046×2 table]
      Codistributor: [1×1 codistributor1d]

データはワーカーに均等に分割されています。datastore の詳細については、データストアとはを参照してください。

ビッグ データのワークフローの詳細については、並列計算の解決策の選択を参照してください。

分散配列および対話型分散配列を作成する代替方法

データがローカル マシンのメモリに収まる場合は、分散配列を使用してワーカー間にデータを分割できます。関数 distributed を使用して MATLAB クライアントに分散配列を作成し、開いている並列プールのワーカーにそのデータを格納します。分散配列は単一の次元内で、その次元に沿ってできるだけ均等にワーカー間に分散されます。分散配列を作成する際、分散の詳細は制御できません。

分散配列は、いくつかの方法で作成できます。

  • 関数 distributed を使用して、既存の配列をクライアント ワークスペースから並列プールのワーカーに分散する。

  • 任意の関数 distributed を使用して、ワーカーに分散配列を直接作成する。この手法では配列があらかじめクライアントに存在している必要がないため、クライアント ワークスペースのメモリ要件が少なくて済みます。関数には eye(___,'distributed')rand(___,'distributed') などがあります。完全な一覧については、distributed オブジェクトのリファレンス ページを参照してください。

  • spmd ステートメント内に対話型分散配列を作成し、spmd ステートメント外で分散配列としてその配列にアクセスする。この手法では、既定以外の分散スキームを使用できます。

最初の 2 つの手法では、配列の作成に spmd が関わっていませんが、この方法で作成された配列を spmd を使用して操作することができます。以下に例を示します。

クライアント ワークスペースで配列を作成し、それを分散配列にします。

parpool('Processes',2) % Create pool
W = ones(6,6);
W = distributed(W); % Distribute to the workers
spmd
    T = W*2; % Calculation performed on workers, in parallel.
             % T and W are both codistributed arrays here.
end
T            % View results in client.
whos         % T and W are both distributed arrays here.
delete(gcp)  % Stop pool

別の方法として、関数 codistributed を使用できます。これにより、次元や分割など、より多くのオプションを制御できますが、多くの場合はより複雑になります。codistributed 配列は、spmd ステートメント内または通信ジョブ内のいずれかで、ワーカー自体で実行することにより作成できます。codistributed 配列の作成時に、次元や分割など、分散のあらゆる特徴を制御できます。

分散配列と対話型分散配列の関係は観点の 1 つです。対話型分散配列は、それを作成または操作するコードの実行元となるワーカーの間で分割されます。クライアントで分散配列を作成すると、spmd ステートメント内で対話型分散配列としてこの配列にアクセスできます。spmd ステートメント内で対話型分散配列を作成すると、クライアント内では分散配列としてこの配列にアクセスできます。spmd ステートメントを使用した場合のみ、同じ配列データに 2 つの異なる観点からアクセスできます。

codistributed 配列は複数の方法で作成できます。

  • spmd ステートメントまたは通信ジョブ内で、関数 codistributed を使用して、そのジョブを実行するワーカーに既に存在しているデータを対話型で分散する。

  • 任意の対話型分散関数を使用して、対話型分散配列をワーカーに直接作成する。この手法では、ワーカーにあらかじめその配列が存在している必要がありません。関数には eye(___,'codistributed')rand(___,'codistributed') などがあります。完全な一覧については、codistributed オブジェクトのリファレンス ページを参照してください。

  • spmd ステートメント外で分散配列を作成し、同じ並列プールで実行される spmd ステートメント内でその配列に対話型分散配列としてアクセスする。

既定ではない分散スキームを使用して、spmd ステートメント内で対話型分散配列を作成します。まず、3 番目の次元に沿って 1 次元の分散を定義し、ワーカー 1 に 4 つの部分、ワーカー 2 に 12 の部分を割り当てます。続いて、ゼロからなる 3×3×16 の配列を作成します。

parpool('Processes',2) % Create pool
spmd
    codist = codistributor1d(3,[4,12]);
    Z = zeros(3,3,16,codist);
    Z = Z + spmdIndex;
end
Z  % View results in client.
   % Z is a distributed array here.
delete(gcp) % Stop pool

対話型分散配列の詳細については、対話型分散配列の取り扱いを参照してください。

参考

| | | | | | |

関連する例

詳細