例題は,次の式に台形公式を適用して円周率を求めるというもの.
なんで求められるかはよくわかってないけど,やってみたら近似解が求められた♪そのプログラムは次のとおりで,THREADS と定義されている定数を1にしたバージョンと2にしたバージョンでそれぞれ計算してみると速度の違いがわかるはず.(もちろん,Mac Pro とかを持ってるリッチな方は,8とかにしても OK だと思う!)
#include <stdio.h>
#include <omp.h>
#define N 100000000
#define THREADS 2
int main(void)
{
int i;
long double top;
long double bottom;
long double step = 1.0L / N;
long double sum = 0.0L;
omp_set_num_threads(THREADS);
#pragma omp parallel private(top, bottom)
{
#pragma omp for reduction(+:sum)
for (i = 0; i < N; i++) {
top = 4.0L / (1.0L + (step * i) * (step * i));
bottom = 4.0L / (1.0L + (step * (i + 1)) * (step * (i + 1)));
sum += (top + bottom) * step / 2.0L;
}
}
printf("pi = %.16Lf\n", sum);
return 0;
}
ここで,reduction 句というものが初登場してる.これは,sum をそれぞれのスレッドで保持し,最後に同期するときにそれらを計算するというような指示をしている句だ.それぞれのスレッドで sum へどんどん加算し,最後にすべての sum を加算するというかんじ.reduction 句を無くすと遅くなるのがよくわかるので,試してみてほしい.
time コマンドで測定したら,次のような結果になった.音楽聞きながら(ちなみに,アーティストは capsule♪)実行という状況だったので,あまり信用できる結果ではないけどwww
・実行時間
1CPU:4.6秒
2CPU:2.4秒
・実行環境
機種:MacBook (Late 2006)
OS:Mac OS X
バージョン:10.5.5
プロセッサ:2 GHz Intel Core 2 Duo
メモリ:2 GB 667 MHz DDR2 SDRAM
GCC:4.4.0 20080801 (experimental)
およそ2倍の速度で計算できてるのがわかると思う.OpenMP で速度向上ってのが体感できるとおもうので,ぜひコンパイルして実行してみてね♪Mac Pro で実行してみたいな〜.
参考文献:
C 言語による OpenMP 入門
追記(2008年11月25日):
間違って追記した内容を修正.sum を初期化しなくていいと書いてたんだけど,間違っていた.reduction 句によって内部で準備されるプライベート変数が自動的に,加算なら0に乗算なら1に初期化されるのであって,sum のような変数は初期化されないので,やはり初期化する必要があった.
混乱を避けるため,前回の11月10日の追記は削除しました.コメントでご指摘いただきありがとうございました.
2 件のコメント:
私のところでは初期化が必要でした.
long double sum = 0;
$ gcc-4.2 -fopenmp test.c
すみません.間違ってました.
reduction 句についての説明を誤読してました.
ご指摘ありがとうございました.
コメントを投稿