このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
parfor
ループ内の変数のトラブルシューティング
parfor
ループの変数が連続的に増加する整数であることの確認
parfor
ループ内のループ変数は、連続的に増加する整数でなければなりません。このため、次の例はエラーを返します。
parfor i = 0:0.2:1 % not integers parfor j = 1:2:11 % not consecutive parfor k = 12:-1:1 % not increasing
iValues = 0:0.2:1; parfor idx = 1:numel(iValues) i = iValues(idx); ... end
parfor
ループでのオーバーフローの回避
MATLAB® は parfor
ループ変数のオーバーフローする可能性を検出すると、エラーを報告します。
オーバーフロー条件 | 例 | 解決法 |
---|---|---|
| 以下で、 parfor idx=int8(-128:127) idx; end | より大きなデータ型を parfor idx=-128:127 int8(idx); end |
| 以下で、 parfor idx=uint32(0:1) idx; end |
|
parfor
ループ内の変数分類の問題の解決
MATLAB が parfor
ループ内の名前を変数として認識すると、その変数は次の表に示す複数のカテゴリのいずれかに分類されます。変数が一意に分類され、カテゴリ要件を満たすことを確認してください。要件に違反する parfor
ループはエラーを返します。
分類 | 説明 |
---|---|
ループ変数 | ループ インデックス |
スライス化された変数 | そのセグメントがループの異なる反復で演算される配列 |
ブロードキャスト変数 | ループの前に定義される変数。その値はループ内に必要ですがループ内で割り当てられることはありません。 |
リダクション変数 | ループの反復を通して値を累積する変数。反復の順序は考慮されません。 |
一時変数 | ループ内で作成される変数。ループ外ではアクセスできません。 |
使用している変数を確認するには、コード フラグメントを調べます。表内のすべての変数分類がこのコードに示されています。
変数分類の問題が生じた場合は、parfor
ループの本体を関数に変換するさらに難しい方法を用いる前に、以下の方法を検討してください。
入れ子にされた
for
ループを使用して、スライス化された配列にインデックスを付ける場合、parfor
ループ内の他の場所でその配列を使用することはできません。左側のコードは機能しません。A
がスライス化されており、入れ子にされたfor
ループ内でインデックスが付けられているためです。右側のコードは機能します。入れ子にされたループの外側でv
がA
に代入されているためです。1 行全体を計算してから、スライス化された出力への代入を一度に実行できます。無効 有効 A = zeros(4, 10); parfor i = 1:4 for j = 1:10 A(i, j) = i + j; end disp(A(i, 1)) end
A = zeros(4, 10); parfor i = 1:4 v = zeros(1, 10); for j = 1:10 v(j) = i + j; end disp(v(1)) A(i, :) = v; end
左側のコードは機能しません。
parfor
内の変数x
を分類できないためです。この変数が分類できない理由は、x
の異なる部分への代入が複数あるためです。したがって、parfor
はループの反復間に依存関係があるかどうかを判定できません。右側のコードは、x
の値を完全に上書きしているため機能します。これでparfor
は、x
が一時変数であると明確に判定できます。無効 有効 parfor idx = 1:10 x(1) = 7; x(2) = 8; out(idx) = sum(x); end
parfor idx = 1:10 x = [7, 8]; out(idx) = sum(x); end
次の例では、構造体配列のフィールドをスライス化する方法を説明します。詳細については、
struct
を参照してください。左側のコードは機能しません。parfor
内の変数a
を分類できないためです。この変数を分類できないのは、インデックス付けの形式が、スライス化された変数では無効なためです。a
のフィールドx
が正しくスライス化されているように見えますが、第 1 レベルのインデックス付けはスライス化されたインデックス付け操作ではありません。右側のコードは正しく機能します。struct
のフィールドを別の変数tmpx
に抽出しているためです。これでparfor
は、この変数がスライス化されていることを正しく判定できます。通常、struct
のフィールドやオブジェクトのプロパティを、スライス化された入力変数や出力変数としてparfor
内で使用することはできません。無効 有効 a.x = []; parfor idx = 1:10 a.x(idx) = 7; end
tmpx = []; parfor idx = 1:10 tmpx(idx) = 7; end a.x = tmpx;
parfor ループの構造体配列
一時変数としての構造体の作成
ドット表記の代入を使用して parfor
ループ内に構造体を作成することはできません。左側のコードでは、ループ内の両方の行で分類エラーが発生します。右側のコードでは、回避策として関数 struct
を使用することで、ループ内または最初のフィールド内に構造体を作成できます。
無効 | 有効 |
---|---|
parfor i = 1:4 temp.myfield1 = rand(); temp.myfield2 = i; end | parfor i = 1:4 temp = struct(); temp.myfield1 = rand(); temp.myfield2 = i; end parfor i = 1:4 temp = struct('myfield1',rand(),'myfield2',i); end |
構造体フィールドのスライス化
構造体フィールドを、スライス化された "入力または出力" 配列として parfor
ループ内で使用することはできません。つまり、ループ変数を使用して、構造体フィールドの要素にインデックスを付けることはできません。左側のコードでは、インデックス付けが原因でループ内の両方の行に分類エラーが発生します。右側のコードでは、スライス化された出力を回避するために、スライス化された別々の配列をループ内で使用します。そのうえで、ループの完了後に構造体フィールドを割り当てます。
無効 | 有効 |
---|---|
parfor i = 1:4 outputData.outArray1(i) = 1/i; outputData.outArray2(i) = i^2; end | parfor i = 1:4 outArray1(i) = 1/i; outArray2(i) = i^2; end outputData = struct('outArray1',outArray1,'outArray2',outArray2); |
スライス化された入力の問題を回避するには、ループの前に構造体フィールドを別の配列に割り当てます。この新しい配列はスライス化された入力に使用できます。
inArray1 = inputData.inArray1; inArray2 = inputData.inArray2; parfor i = 1:4 temp1 = inArray1(i); temp2 = inArray2(i); end
parfor
ループ本体から関数への変換
他のすべてが失敗した場合でも、parfor
ループ本体を関数に変換することにより、parfor
ループでの変数分類の問題を通常は解決できます。左側のコードでは、コード アナライザーが変数 y の問題にフラグを設定しますが、この問題を解決することはできません。右側のコードでは、parfor
ループ本体を関数に変換することでこの問題が解決されます。
無効 | 有効 |
---|---|
function parfor_loop_body_bad data = rand(5,5); means = zeros(1,5); parfor i = 1:5 % Code Analyzer flags problem % with variable y below y.mean = mean(data(:,i)); means(i) = y.mean; end disp(means); end | function parfor_loop_body_good data = rand(5,5); means = zeros(1,5); parfor i = 1:5 % Call a function instead means(i) = computeMeans(data(:,i)); end disp(means); end % This function now contains the body % of the parfor-loop function means = computeMeans(data) y.mean = mean(data); means = y.mean; end Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers. 0.6786 0.5691 0.6742 0.6462 0.6307 |
明確な変数名
parfor
ループ内の変数として MATLAB で明確に識別できない名前を使用すると、関数を参照しているものと解析時に想定されます。その上で、実行に際して関数が見つからないと、MATLAB でエラーが発生します変数名を参照してください。たとえば、次のコードでは、f(5)
は f
という配列の 5 番目の要素を参照しているか、または引数 5
をもつ f
という関数を参照しているかのいずれかです。f
がコード内で変数として明確に定義されていない場合、MATLAB ではコード実行時にパスで関数 f
を検索します。
parfor i = 1:n ... a = f(5); ... end
透過的な parfor
ループ
parfor
ループ本体は "透過的" でなければなりません。つまり、変数への参照はすべてコードのテキストにおいて "可視" でなければなりません。透過性の詳細については、parfor ループまたは spmd ステートメント内での透過性の確保を参照してください。
グローバル変数および永続変数
parfor
ループの本体に、global
または persistent
の変数宣言を含めることはできません。