1

元のコードは次のようになります。

for i = 1 : size(H, 1)
    for j = 1 : size(H, 2)
        H{i,j} blabla

そして、私はそれを次のような並列コードに適応させようとしました:

parfor ind = 1 : numel(H)
    [i, j] = ind2sub(ind);
    H{i,j} blabla

parforH{i,j} のために実行できないというエラーが生成されます。

では、ここでのエラーは何ですか?また、ネストされたループを parfor に適応させるにはどうすればよいでしょうか?

1つの可能な解決策

for i = 1 : size(H, 1)
    parfor j = 1 : size(H, 2)
        H{i,j} blabla

しかし、別のループ内で parfor を使用するとオーバーヘッドが増加し、parforその結果として計算時間が増えるとは思えません。

4

2 に答える 2

2

parfor を使用するためのエラーは[i,j]、関数の結果であるため、Matlab がループを通じて一意であることを検出できないことだと思います。したがって、エンジンの場合、H{i,j}複数回アクセスする可能性があり、反復は互いに独立して分析されません。

編集: patrik が述べたように、2 つの反復の間に依存関係がないことを確認する必要があります。つまり、ここでは、H{i,j}に依存せず、反復内の変数の値が別の反復で使用されていません。この要件は、リダクション代入を除いて、parfor を許可するための基本的な要件です。H{k,l}i!=k and j!=l

その点に加えて、独立した計算を並行して実行したい場合、そしてそれが価値がある場合は、常にparfor最も外側のループを選択してください。これに加えて、 Matlab ではネストされた;が許可されていないことに注意してください。parfor代わりに、parfor内側の for ループを並列化したい場合は、実行する関数を作成する必要があります。内側のループを並列化しても速度が向上しない場合があります (parpool 内のワーカー数によって異なります)。

私の経験から、並列の内部ループを実行することはお勧めしません。例として (Matlab 以外で)、LibSVM を引用します。これは、計算を高速化したい場合は、最も外側のループのみを openmp で並列化し、他の内側のループを並列化しないことを推奨しています。

この推奨事項の理由は、ワーカーのプールが限られていることと、ワーカーがスレッドと見なされる可能性があることです。スレッドを追加すると、スレッド間の切り替え時間のために計算が遅くなるという制限があります。Matlab はこの部分をうまく処理できますが、ポイントは、ワーカーのプールのサイズが制限されることです。最も外側の各反復に多くの時間がかかり、多数の反復がある場合、各ワーカーが反復全体 (内側のループを含む) を実行するためにビジー状態になるため、内側のループを並列化する時間がなくなります。

それにもかかわらず、各オプションをテストすることは常に良いことです.それらのいくつかは、直観に反してあなたの問題により適応しているかもしれません.

于 2014-05-05T09:47:13.020 に答える
1

単純に線形インデックスを使用して H に割り当ててみませんか? 例えば:

H = cell(4, 4);
parfor idx = 1:16
  [i, j] = ind2sub([4, 4], idx);
  H{idx} = rand(i, j); % or whatever
end

それ以外の場合は、最も外側のループを PARFOR ループにするのが常に最善です。以下も機能します。

H = cell(4, 4);
parfor r = 1:4
  for c = 1:4
    H{r, c} = rand(r, c);
  end
end
于 2014-05-06T06:50:00.190 に答える