OpenMP小例子—計算PI
阿新 • • 發佈:2018-11-08
訪問本站觀看效果更佳
title: OpenMP小例子—計算PI
tags:
- openmp
一、第一種並行方法
OpenMP較為簡單,採用編譯製導的方式執行。下面的程式碼
採用
id = omp_get_thread_num();
返回現有組內的各個執行緒標誌符[0,omp_set_num_threads-1]
並行部分i作為每個執行緒組的私有變數執行。
#pragma omp for for (i=0;i< num_steps; i++){ x = (i+0.5)*step; sum[id] += 4.0/(1.0+x*x); }
完整程式碼
#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 對下面{}內的全部內容並行化。
#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); } }
具體程式碼
#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指定某一區域的程式碼,每次只能同時被一個執行緒執行。
#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雖然很方便,但它只支援一些基本操作,比如+,-,*,&,|,&&,||等。
#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);
}