Visual studio メモ1 --OpenMPを使ってfor分を並列化する--



  • メニュー>プロジェクト>プロパティ>C/C++>言語>OpenMPのサポート  を「はい」にする
  • 並列化したいfor文の前に以下を挿入
 #pragma omp parallel shared( *, *, ...) num_threads(**)
{
    #pragma omp for private(*, *,...)
    for1(...){...}

    #pragma omp for private(*, *,...)
    for2(...){...}
} 

  • for文が一つなら以下でもok
  #pragma omp parallel for
    for1(...){...} 
shared( *, *, ...)には,並列化時に全てのスレッドから共有されるメモリ領域を指定する.省略可(明示するかどうかはプログラマ任せで,書かなかったらどうという物ではなさそう.)でもちゃんとした人は書いてるっぽい.
num_threads(**)には,スレッド数を入れる.省略した場合、CPUのコア数が割り当てられるらしい.
private(*, *,...)には,対象forループの外で宣言した変数の内,スレッドがローカルに使いたいものがあれば入れる.↓例.
int x, y;
#pragma omp for private(y)
for( x=0...){
    for( y=0...){...}
} 
ただ,この例も,
#pragma omp for
for( int x=0...){
    for(int y=0...){...}
}  
と書けばprivate必要ない.

  • 総和計算にはreduction使う
for ループの中で,変数vの総和を計算する時,以下のように書く.
double v = 0;
#pragma omp parallel for reduction( + : v )
for( int i=0; i<100; ++i){ ...; v+=??; } 

スレッド数が4個のときの行われる計算のイメージは以下
まず並列にfor文を計算
スレッド1 : doble v1=0; for( int i= 0; i< 25; ++i){ ...; v1+=??; }
スレッド2 : doble v2=0; for( int i=25; i< 50; ++i){ ...; v2+=??; }
スレッド3 : doble v3=0; for( int i=50; i< 75; ++i){ ...; v3+=??; }
スレッド4 : doble v4=0; for( int i=75; i<100; ++i){ ...; v4+=??; }

for文が終わったら、全ての結果を足し合わせ.
v = v1 + v2 + v3 + v4; 

OpenMPはプログラマを甘やかし過ぎなんじゃないかと思うくらい便利.2行書いただけで数倍高速になったりする。。。