変数のスレッド固有化は、プログラムの並列化を向上させる上で便利な方法です。しかし、スレッド固有変数がループの外側で参照される場合には、その値が正しいことを保証することが必要になります。次の例を考えてみましょう。
for (i=1; i < 1000; i++) { t = 2 * a[i]; /* S1 */ b[i] = t; /* S2 */ } x = t; /* S3 */ |
「3.4.3 ストアバック変数の使用」では、文 S3 で参照されている変数 t の値が、ループを終了したときの最終結果になります。変数 t がスレッド固有化され、ループの実行が終了したあと、t の正しい値をオリジナルの変数に戻すことが必要になります。この操作をストアバック (書き戻し) といいます。これは、繰り返しの最後における t の値をオリジナルの変数 t に書き込むことで実現できます。多くの場合、この操作はコンパイラによって自動的に行われます。しかし、最終値を簡単に計算できないこともあります。
for (i=1; i < 1000; i++) { if (c[i] > x[i] ) { /* C1 */ t = 2 * a[i]; /* S1 */ b[i] = t; /* S2 */ } } x = t*t; /* S3 */ |
正しく実行した場合、文 S3 の t の値は、一般的にはループの最後における t の値にはなりません。最後の繰り返しで、C1 が真の場合に限って、最後の t の値に等しくなります。すべての場合における t の最終値を計算することは、非常に困難です。このような場合には、コンパイラはループを並列化しません。