基于openMP的并行计算实验.docx
《基于openMP的并行计算实验.docx》由会员分享,可在线阅读,更多相关《基于openMP的并行计算实验.docx(12页珍藏版)》请在冰豆网上搜索。
基于openMP的并行计算实验
并行计算实验报告
课程:
并行计算
姓名:
郑波
学号:
2013211644
班级:
计算机科学与技术13-2班
日期:
2015年12月7日
实验一:
OpenMP基本使用
一、实验目的
1、熟悉OpenMP编程。
2、比较串行算法与并行算法在执行时间上的差别;
3、考察线程数目使用不同对并行算法执行时间的影响;
4、考察运算规模N对串、并行算法执行时间上的影响。
二、实验内容
1、使用OpenMP进行两个矩阵A和B的加法,并分析串行、并行时间的差别以及问题规模对程序运行时间的影响
三、实验步骤
1、整个程序的设计流程
①全局变量设置三个宏定义过的size×size的二维数组啊a,b,c。
②初始化a数组为全1,b数组为全2
③通过omp_set_num_threads()库函数设置线程数
④调用openMP库函数omp_get_wtime()获取当前时间start
#pragmaompparallelfor开始做并行区部分
…
结束后再次调用omp_get_wtime()获取时间end,end-start即为并行消耗时间
⑤再次调用时间函数更新strat
串行做一边矩阵相加
更新end,end-start即为串行耗时
代码如下:
#include
#include
#definesize10000
usingnamespacestd;
inta[size][size],
b[size][size],
c[size][size];
intmain()
{
for(inti=0;i!
=size;++i)//initialthematrix
for(intj=0;j!
=size;++j){
a[i][j]=1;
b[i][j]=2;
}
doublestart=omp_get_wtime();
omp_set_num_threads(4);
#pragmaompparallelfor
for(inti=0;ifor(intj=0;jc[i][j]=a[i][j]+b[i][j];
doubleend=omp_get_wtime();
cout<<"并行运行时间:
"<start=omp_get_wtime();
for(inti=0;ifor(intj=0;jc[i][j]=a[i][j]+b[i][j];
end=omp_get_wtime();
cout<<"串行运行时间:
"<system("pause");
}
2、问题规模对串、并行程序时间的影响(A、B矩阵的大小为N*M)
(1)通过不断增加问题规模,观察串行和并行程序的执行时间,得到如下表格的时间消耗数据:
100*100
1000*1000
10000*10000
串行消耗(ms)
0.03
4.36
296.91
并行消耗(ms)
7.06
9.54
182.27
(2)可以发现,当矩阵规模较小时,串行算法仍然要比并行算法运行的快,当规模到达一定程度的时候,并行运行的速度较串行有了提升。
并行算法对各个CPU的调度也占用一定的时间,当问题规模很小的时候,这个调度时间占了很大的比重,而在规模较大的时候,这个调度时间就显得微乎其微了
3、线程数目对并行程序的影响(这里假设问题规模为:
N*M=10000*10000)
(1)在使用OpenMP进行并行执行矩阵加法时,我们可以自由设置进行并行计算的并行线程数目。
(2)在并行区域中,通过函数intomp_set_num_threads(int)设置并行区域中要创建的线程数,分别设置为2、4、8、16,得到如下表格的时间消耗
2
4
8
16
并行消耗(ms)
262.73
205.12
248.97
295.38
(3)观察发现,在问题规模不变的前提下,随着线程数目的增加,问题解决的时间也在相应的减少。
但是,问题消耗的时间并不会随着线程数目的增加而不断的减少,原因可能是因为,随着线程数目的增减,线程的额外准备时间开销也将扩大。
四、心得体会
通过本次实验,了解了openMP库函数,掌握了openMP最基本的多线程程序编写。
通过分析比较串并行运行时间,体会了不同规模下串并行的使用效果。
实验二:
使用OpenMP实现圆周率计算的并行算法
一、实验目的
1、考察问题规模N对圆周率计算精确度的影响;
2、考察线程数目对圆周率计算执行时间的影响;
3、比较串、并行算法在执行时间上的差别。
二、实验内容
1、使用OpenMP和近似计算公式计算圆周率π的大小,并分析串行、并行时间的差别以及问题规模对程序运行时间的影响
三、实验步骤
1、整个程序的设计流程
①全局变量设置宏size,用来描述计算范围
②利用如下公式准备计算圆周率π的近似值
③通过omp_set_num_threads()库函数设置线程数
④调用openMP库函数omp_get_wtime()获取当前时间start
#pragma omp parallel for reduction(+:
sum)
开始做并行区部分
注意:
其中sum是共享的,因为是个连续和的问题,采用reduction之后,每个线程根据reduction(+:
sum)的声明算出自己的sum,然后再将每个线程的sum加起来。
避免各个线程共享sum资源时出现问题
…
结束后再次调用omp_get_wtime()获取时间end,end-start即为并行消耗时间
⑤再次调用时间函数更新strat
串行做一边矩阵相加
更新end,end-start即为串行耗时
代码如下:
#include
#include
#define size 10000000
using namespace std;
int main()
{
double sum=0,start,end;
omp_set_num_threads(4);
start=omp_get_wtime();
#pragma omp parallel for reduction(+:
sum)
for(int i=0;isum+=4/(1+((0.5+i)/size)*((0.5+i)/size))*1/size;
}
end=omp_get_wtime();
cout<<"并行时间:
"<sum=0;
start=omp_get_wtime();
for(int i=0;isum+=4/(1+((0.5+i)/size)*((0.5+i)/size))*1/size;
}
end=omp_get_wtime();
cout<<"串行时间:
"<cout.precision(20);
cout<<"π:
"<system("pause");
}
2、问题规模对串、并行程序时间的影响(N的大小影响时间)
(1)通过不断增加问题规模,观察串行和并行程序的执行时间,得到如下表格的时间消耗数据:
1000
100000
10000000
串行消耗(ms)
0.04
4.10
365.70
并行消耗(ms)
4.60
15.04
188.48
(2)可以发现,当规模较小时,串行算法仍然要比并行算法运行的快,当规模到达一定程度的时候,并行运行的速度较串行有了提升。
并行算法对各个CPU的调度也占用一定的时间,当问题规模很小的时候,这个调度时间占了很大的比重,而在规模较大的时候,这个调度时间就显得微乎其微了
3、线程数目对并行程序的影响(这里假设问题规模为:
N=100000)
(1)在使用OpenMP进行并行执行运算时,我们可以自由设置进行并行计算的并行线程数目。
(2)在并行区域中,通过函数intomp_set_num_threads(int)设置并行区域中要创建的线程数,分别设置为2、4、8、16,得到如下表格的时间消耗
2
4
8
16
并行消耗(ms)
3.26
3.23
3.14
30.9
(3)观察发现,在问题规模不变的前提下,随着线程数目的增加,问题解决的时间也在相应的减少。
但是,问题消耗的时间并不会随着线程数目的增加而不断的减少,原因可能是因为,随着线程数目的增减,线程的额外准备时间开销也将扩大。
四、心得体会
通过本次实验,进一步深入了openMP的编程,对openMP各线程共享资源、各自拥有自己的资源有了初步认识。
再一次体会到了并行计算给大规模计算带来的便利性。
实验三:
使用OpenMP求最大值
一、实验目的
1、掌握求最大值的并行算法
2、比较串行算法与并行算法在执行时间上的差别;
3、考察线程数目使用不同对并行算法执行时间的影响;
二、实验内容
1、使用OpenMP求一个乱序数列的最大值,并分析串行、并行时间的差别以及问题规模对程序运行时间的影响
三、实验步骤
1、整个程序的设计流程
本程序实现了平衡树算法,但由于处理器数目有限,并行结果反而不如串行,不过当处理器足够多时(理想情况为数组长度的一半)时,并行会有大的提升。
这里只讲一下平衡树算法思路。
1全局变量设置num×size的二维数组,最后一维用来保存数列
其中:
num=log(size-1)/log
(2)+1;表示平衡树的高度
②初始化最后一维数组
③通过omp_set_num_threads()库函数设置线程数
④调用openMP库函数omp_get_wtime()获取当前时间start
#pragmaompparallelfor开始做并行区部分
…
结束后再次调用omp_get_wtime()获取时间end,end-start即为并行消耗时间
⑤算法核心部分:
算法先处理最后一层平衡树(假设个数为n),两个数据一组比较,取大的,生成新的一层平衡树(个数为n/2或者(n+1)/2),放在二维数组的上一维。
迭代处理每一层,最后使得新的一层个数为1,这个值就是最大值,即a[1][1];
并行处理每一层平衡树
代码如下:
#include
#include
#include
constintsize=10000;
usingnamespacestd;
inta[size+1][size+1];
intmain()
{
intnum=log(size-1)/log
(2)+1;
for(size_ti=1;i<=size;++i){//初始