OpenMP小例子—计算PI

一、第一种并行方法
OpenMP较为简单,采用编译制导的方式执行。下面的代码
采用

1
id = omp_get_thread_num();

返回现有组内的各个线程标志符[0,omp_set_num_threads-1]
并行部分i作为每个线程组的私有变量运行。

1
2
3
4
5
#pragma omp for
for (i=0;i< num_steps; i++){
x = (i+0.5)*step;
sum[id] += 4.0/(1.0+x*x);
}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <omp.h>
static long num_steps = 100000;
double step;
#define NUM_THREADS 2
void main ()
{
int i;
double x, pi, sum[NUM_THREADS];
step = 1.0/(double) num_steps;
//设置并行子域进程数上限
omp_set_num_threads(NUM_THREADS);
//指定线程组内部私有变量i,此时各个线程组内分别拥有一个i的副本
#pragma omp parallel private(i)
{
double x;
int id;
//返回现有组内的一个线程标志符[0,omp_set_num_threads-1]主线程号始终为0
id = omp_get_thread_num();
sum[id] = 0;
#pragma omp for
for (i=0;i< num_steps; i++){
x = (i+0.5)*step;
sum[id] += 4.0/(1.0+x*x);
}
}
for(i=0, pi=0.0;i<NUM_THREADS;i++)pi += sum[i] * step;
printf("Pi = %lf\n",pi);
}

二、第二种并行方法
以下程序与之前的区别在于, #pragma omp parallel 对下面{}内的全部内容并行化。

1
2
3
4
5
6
7
8
9
10
11
#pragma omp parallel 
{
double x;
int id;
////返回现有组内的一个线程标志符[0,omp_set_num_threads-1]主线程号始终为0
id = omp_get_thread_num();
for (i=id, sum[id]=0.0;i< num_steps; i=i+NUM_THREADS){
x = (i+0.5)*step;
sum[id] += 4.0/(1.0+x*x);
}
}

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <omp.h>
static long num_steps = 100000;
double step;
#define NUM_THREADS 4
void main ()
{ int i;
double x, pi, sum[NUM_THREADS];
step = 1.0/(double) num_steps;
//设置并行子域进程数上限NUM_THREADS
omp_set_num_threads(NUM_THREADS);
//最基本的parallel指令形式,表示一下部分并行执行
#pragma omp parallel
{
double x;
int id;
////返回现有组内的一个线程标志符[0,omp_set_num_threads-1]主线程号始终为0
id = omp_get_thread_num();
for (i=id, sum[id]=0.0;i< num_steps; i=i+NUM_THREADS){
x = (i+0.5)*step;
sum[id] += 4.0/(1.0+x*x);
}
}
for(i=0, pi=0.0;i<NUM_THREADS;i++)pi += sum[i] * step;
printf("Pi = %lf\n",pi);
}

三、第三种方法
新使用的指令

#pragma omp parallel private (x,i,sum)

//指定需要处理为各个进程组私有变量的参数x,i,sum

#pragma omp critical

//critical指定某一区域的代码,每次只能同时被一个线程执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <omp.h>
static long num_steps = 100000;
double step;
#define NUM_THREADS 8
void main ()
{
int i,id;
double x, sum, pi=0.0;
step = 1.0/(double) num_steps;
omp_set_num_threads(NUM_THREADS);
//指定需要处理为各个进程组私有变量的参数x,i,sum
#pragma omp parallel private (x,i,sum)
{
id = omp_get_thread_num();
for (i=id,sum=0.0;i< num_steps;i=i+NUM_THREADS){
x = (i+0.5)*step;
sum += 4.0/(1.0+x*x);
}
//critical指定某一区域的代码,每次只能同时被一个线程执行。
#pragma omp critical
pi += sum*step;

}
printf("Pi = %lf\n",pi);

}

四、第四种方法
我们在#pragma omp parallel for 后面加上了 reduction(+:sum),它的意思是告诉编译器:下面的for循环你要分成多个线程跑,但每个线程都要保存变量sum的拷贝,循环结束后,所有线程把自己的sum累加起来作为最后的输出。
reduction虽然很方便,但它只支持一些基本操作,比如+,-,*,&,|,&&,||等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <omp.h> 
static long num_steps = 100000;
double step;
#define NUM_THREADS 8
void main ()
{ int i;
double x, pi, sum = 0.0;
step = 1.0/(double) num_steps;
omp_set_num_threads(NUM_THREADS);

#pragma omp parallel for reduction(+:sum) private(x)
for (i=0;i<num_steps; i++){
x = (i+0.5)*step;
sum = sum + 4.0/(1.0+x*x);
}
pi = step * sum;
printf("Pi = %lf\n",pi);
}

-------------End of the articleThank you for reading-------------
  • Author of this article:zfish
  • Link to this article: archives/857ca6f3.html
  • Copyright Notice: All articles in this blog, except for special statements, please indicate the source!
0%