どの共有メモリ型の場合もそうだと思いますが、OpenMPの並列リージョンの中では変数は共有(shared)か局所(private)のどちらかに決まります。
例えば、前に出てきた、以下のプログラムで考えましょう。
002-2.c
#include<stdio.h>
#include<omp.h>
#define N 1000000
int main(int argc,char *argv[])
{
int my,n;
int i,A[N];
double start,end;
start = omp_get_wtime();
for (n=0;n<1000;n++)
{
#pragma omp parallel for
for (i = 0 ; i < N ; i++)
A[i]=i;
}
end = omp_get_wtime();
printf("elapsed time = % lf \n",(end-start));
return 0;
}
何気なく並列化していますが、これには暗黙の了解が含まれています。
- forループの制御変数はprivateである
- 特に指定しない場合はsharedである
これを先のコードに当てはめると…
- forループの制御変数 i は局所変数(private)である
- Nはプリプロセス時に展開されるので問題ない
- Aは並列リージョン内で共有(shared)される
となります。
よく考えてみましょう、ループの制御変数は各スレッドで共有すると変なことになりますよね。
例えばスレッド1でi=1として働いているときに別のスレッドがi=10として使い始めると、スレッド1のiの値が10に変更されて実行されてしまう。それが起きると実行結果がおかしくなるのは想像できますよね。ですから各スレッドで局所的にこの変数 i をもって自由に使うことでループを分割して実行することができます。
反対にAの配列を局所化すると、今回の場合は実行結果は変わらないかもしれませんが、そうするためには各スレッドでどこの部分が書き換わったのかを覚えておいてそれをあとで一つの配列にまとめ直さなければいけなくなります。これでは実行時間が膨大になってしまいます。
OpenMPはこのように、局所化と共有化をうまく利用して計算を速くすることができます。
細かい局所化や共有方法は後日申し上げるとして、今日はこのくらいにしておきます。