一時変数
"一時変数" とは、インデックス付けされていない直接的代入の対象であり、リダクション変数ではない任意の変数です。次の parfor
ループでは、a
および d
は一時変数です。
a = 0; z = 0; r = rand(1,10); parfor i = 1:10 a = i; % Variable a is temporary z = z + i; if i <= 5 d = 2*a; % Variable d is temporary end end
for
ループの動作とは異なり、MATLAB® は parfor
ループの各反復の前に、すべての一時変数をクリアします。反復の独立性を確保するため、一時変数の値をループの 1 つの反復から別の反復に渡すことはできません。したがって、一時変数は parfor
ループの本体内で指定されなければなりません。そのため、一時変数の値は各反復で個別に定義されます。
MATLAB は一時変数をクライアントに送り返しません。parfor
ループ内の一時変数は、ループ外に存在する同名の変数に影響を与えません。この動作は、通常の for
ループとは異なります。
初期化されない一時変数
parfor
ループ内の一時変数は、各反復の開始時にクリアされます。一時変数が反復内で設定される前にループ反復がその一時変数を使用するケースを MATLAB が検出することがあります。この場合、MATLAB は実行時エラーではなく静的エラーを発行します。実行時エラーが間違いなく発生する場合、実行の続行を許可することにはほとんど意味がありません。このようなエラーは、特に変数の分類ルールに関して for
と parfor
の間で混同があるため、頻繁に発生します。以下に例を示します。
b = true; parfor i = 1:n if b && some_condition(i) do_something(i); b = false; end ... end
このループは通常の for
ループであれば許容されます。しかし parfor
ループでは、b
はループ内の直接の代入先となっているため、一時変数となります。したがって、この一時変数は各反復の開始時にクリアされるため、if
の条件での使用では絶対に初期化されませんparfor
を for
に変更すると、b
の値によってループの逐次実行が仮定されます。この場合、b
が false
に設定されるまでの i
の値が低い場合についてのみ、do_something(i)
が実行されます。
リダクション変数としての一時変数
一時変数が初期化されないもう 1 つの一般的な原因となり得るのは、リダクション変数として想定した変数が存在する場合です。しかし、この変数をループ内の他の位置で使用すると、一時変数として分類されます。以下に例を示します。
s = 0; parfor i = 1:n s = s + f(i); ... if (s > whatever) ... end end
s
の出現箇所が本体の最初のステートメントの 2 箇所のみである場合、s
はリダクション変数として分類されます。しかしこの例では、s
はリダクション変数ではありません。リダクション代入以外にも、s > whatever
の行で使用されているためです。s
は (最初のステートメントにおいて) 代入先であるため、一時変数です。したがって、MATLAB はエラーを発行しますが、リダクションとの関連の可能性も指摘します。
parfor
を for
に変更した場合、リダクション代入外での s
の使用は、特定の順序で実行される反復に依存します。parfor
ループ内では、その進行過程でリダクション変数の値が "考慮されない" 点が重要です。リダクション値が使用可能になるのは、ループを抜けてからです。
変数 ans
parfor
ループの本体内で、変数 ans
は一時変数として分類されます。ans
には一時変数に対するすべての考慮事項と制約が適用されます。たとえば、parfor
ループ内での ans
への代入は、ループ外の ans
に影響しません。