コード:
double x(){return (double)rand()/(double)RAND_MAX;}
double y(){return (double)rand()/(double)RAND_MAX;}
double z(){return (double)rand()/(double)RAND_MAX;}
int d(double x, double y, double z){
if ( ( (pow(x,2)+pow(y,2)) <1 ) && ( z<=1 && z>=0 )) return 1;
return 0;
}
double f(double x, double y, double z){
return 1;
}
#pragma omp parallel default(none) private(id,numt,j,local_sum,local_good_dots,local_coi,x_,y_,z_) shared(total_sum,good_dots,count_of_iterations)
{
local_coi = count_of_iterations;
id = omp_get_thread_num() + 1;
numt = omp_get_num_threads();
#pragma omp for
for (j = 1; j <= local_coi; j++){
x_=x();
y_=y();
z_=z();
if (d(x_,y_,z_) == 1){
local_sum += f(x_,y_,z_);
local_good_dots += 1;
}
}
#pragma omp critical
{
total_sum = total_sum + local_sum;
good_dots = good_dots + local_good_dots;
}
}
f()
コメント:このコードは、面積の関数の3次元積分を計算するためのモンテカルロ法を実現したものですd()
。
このコードはマルチスレッドモード(openmp)でより高速に動作することを期待しています。
しかし、何かがうまくいかない。
数時間の変更(reduction
openmpプラグマ、if-conditionの簡略化(のようなf(x_,y_,z_) * d(x_,y_,z_)
))の後、私は理解していませんでした。なぜこの単純なループは、スレッドの数が多いほど遅くなるのですか。
しかし、ループの前に座標ごとに3次元配列を生成してドロップするとshared
、プログラムはより高速になります。
だから、質問:
このコードを変更する方法と、並列ブロックで許可されている関数(操作)はどれですか?
PS:私が見るように、そのrand
機能は許可されていません(または私は間違っていますか?)
手伝ってくれてありがとう!
変更(@HristoIlievの助けを借りて)
double x(){return (double)rand()/(double)RAND_MAX;}
double y(){return (double)rand()/(double)RAND_MAX;}
double z(){return (double)rand()/(double)RAND_MAX;}
int d(double x, double y, double z){
if ( ( (pow(x,2)+pow(y,2)) <1 ) && ( z<=1 && z>=0 )) return 1;
return 0;
}
double f(double x, double y, double z){
return 1;
}
#pragma omp parallel default(none) private(j,local_coi,x_,y_,z_) shared(count_of_iterations) reduction(+:total_sum,good_dots)
{
local_coi = count_of_iterations;
#pragma omp for(prng)
for (j = 1; j <= local_coi; j++){
#pragma omp critical(prng)
{
x_=x();
y_=y();
z_=z();
}
if (d(x_,y_,z_) == 1){
total_sum += f(x_,y_,z_);
good_dots += 1;
}
}
}