物欲購入目録日誌 写真館
スポンサーサイト
--.--.-- (--:--) スポンサー広告
Twitterでつぶやく
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
OpenMPでベンチーマーク取って遊んでみた!
2012.06.09 (23:27) プログラミングtrackback(0)comment(0)
Twitterでつぶやく

openmp_color.jpg

ちょっと、OpenMPで遊んでみた。ちゃんとスレッドで並列化されるのかベンチマークとってみたわ。
作ったソースは以下の様な感じの、ラプラス方程式をガウス・サイデイル法で解くのにかかる時間を測定するよ。

コンパイルはg++-fopenmpでコンパイルした。


//
// 【laplace.cc】
//
// OpenMPを用いてラプラス方程式をガウス・サイデイル法で
// 解くのにかかる時間を測定する
// 利用スレッド数は環境変数"OMP_NUM_THREADS"で指定しておく
//
// (コンパイル方法)
//
// $ g++ -fopenmp laplace.cc
//
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>
#include <omp.h>
using namespace std;

// 大域変数
const int Xgrid = 700;
const int Ygrid = 700;
const double dx = 0.002;
const double dy = 0.002;
const double tol= 1.0E-6;

// 時間測定用 関数
double gettimeofday_sec(){
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec * 1e-6;
}

// グリッドの初期化関数
void initialize(double** u,int** flag){
// Circle 1
double ox1 = 0.3,oy1 = 0.3;
double radius1 = 0.2;
double value1 = 30.0;

// Circle 2
double ox2 = 0.7,oy2 = 0.6;
double radius2 = 0.06;
double value2 = -20.0;

// ローカル変数
double x = 0.0,y = 0.0;

for(int i = 0;i < Xgrid; i++){
for(int j = 0;j < Ygrid; j++){
x=static_cast(i) * dx;
y=static_cast(j) * dy;
// Circle 1
if(pow((x-ox1),2.0)+pow((y-oy1),2)-pow(radius1,2.0)<=0.0)
{
u[i][j] = value1;
flag[i][j] = 1;
}
// Circle 2
else if(pow((x-ox2),2.0)+pow((y-oy2),2.0)-pow(radius2,2.0)<=0.0)
{
u[i][j] = value2;
flag[i][j] = 1;
}else{
u[i][j] = 0.0;
flag[i][j] = 0;
}
}
}
}

// main
int main(void){
int i,j;
double start= 0.0,end = 0.0;
double err = 0.0,diff = 0.0;
// データ用配列
double** u;
double** uu;
int** flag;
int thread_num = 0;

// グリッドを初期化
u = new double*[Xgrid];
uu = new double*[Xgrid];
flag = new int*[Xgrid];
for(int i = 0;i < Xgrid; i++){
u[i] = new double[Ygrid];
uu[i] = new double[Ygrid];
flag[i] = new int[Ygrid];
}
initialize(u,flag);

// 時間計測開始
start = gettimeofday_sec();

do{
#pragma omp parallel private(i,j,diff)
{
// スレッド数取得
thread_num = omp_get_num_threads();
#pragma omp for
// copy
for (i = 1; i < Ygrid - 1; i++){
for (j = 1; j < Xgrid - 1; j++){
uu[i][j] = u[i][j];
}
}
#pragma omp for
// update
for (i = 1; i < Ygrid - 1; i++){
for (j = 1; j < Xgrid -1; j++){
if(flag[i][j] != 1){
u[i][j] = 0.25 *
(uu[i][j-1] + uu[i][j+1] + uu[i-1][j] + uu[i+1][j]);
}
}
}
#pragma omp single
{ err = 0.0; }
#pragma omp for reduction(+:err)
for (i = 1; i < Ygrid -1; i++){
for (j = 1; j < Xgrid-1; j++){
diff = uu[i][j] - u[i][j];
err += diff * diff;
}
}
}
}
while (err > tol);
// 時間計測終了
end = gettimeofday_sec();
cout << thread_num << "スレッド: " << (double)(end - start) << endl;
return 0;
}


結果はこんな感じ。

opnmp2.png

使ったマシンは自分のCorei7(4コア,8スレッド)のiMacで測定しました。
クワッドコアなので4CPUまでは速度がほぼ線形に向上したんだけど、、

それ以上の並列度はハイパースレッディングでみかけの8CPUなので、L2キャッシュなどを多用する数値計算などではあまり速度向上が見込めない結果になった。

なんかHTってマジで計算速度倍になるかのように素人考えで思っていたけど、そうでもなかったわ。
prevhome next












トラックバックURL
→http://tachiphoto.blog61.fc2.com/tb.php/1697-84374900
home
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。