cout.precision(20);
cout«"n:
"vvsumvvendl;
system("pause");
}
2、问题规模对串、并行程序时间的影响(N的大小影响时间)
⑴通过不断增加问题规模,观察串行和并行程序的执行时间,得到如下表格的时
间消耗数据:
1000
100000
10000000
串行消耗
0.04
4.10
365.70
(ms)
并行消耗
4.60
15.04
188.48
(ms)
(2)可以发现,当规模较小时,串行算法仍然要比并行算法运行的快,当规模到达
定程度的时候,并行运行的速度较串行有了提升。
并行算法对各个CPU的调度也占用一定的时间,当问题规模很小的时候,这个调
度时间占了很大的比重,而在规模较大的时候,这个调度时间就显得微乎其微了
3、线程数目对并行程序的影响(这里假设问题规模为:
N=100000)
(1)在使用OpenMP进行并行执行运算时,我们可以自由设置进行并行计算的并行线程数目。
(2)在并行区域中,通过函数intomp_set_num_threads(in设置并行区域中要创建的
线程数,分别设置为2、4、816,得到如下表格的时间消耗
2
4
8
16
并行消耗
3.26
3.23
3.14
30.9
(ms)
(3)观察发现,在问题规模不变的前提下,随着线程数目的增加,问题解决的时间
也在相应的减少。
但是,问题消耗的时间并不会随着线程数目的增加而不断的减少,原因可能是因为,随着线程数目的增减,线程的额外准备时间开销也将扩大。
四、心得体会
通过本次实验,进一步深入了openMP的编程,对openMP各线程共享资源、各自拥有自己的资源有了初步认识。
再一次体会到了并行计算给大规模计算带来的便利性。
实验三:
使用OpenMP求最大值
一、实验目的
1、掌握求最大值的并行算法
2、比较串行算法与并行算法在执行时间上的差别;
3、考察线程数目使用不同对并行算法执行时间的影响;
二、实验内容
1、使用OpenMP求一个乱序数列的最大值,并分析串行、并行时间的差别以及问题规模对程序运行时间的影响
三、实验步骤
1、整个程序的设计流程本程序实现了平衡树算法,但由于处理器数目有限,并行结果反而不如串行,不过当处理器足够多时(理想情况为数组长度的一半)时,并行会有大的提升。
这里只讲一下平衡树算法思路。
1全局变量设置numxsize的二维数组,最后一维用来保存数列
其中:
num=log(size-1)/log
(2)+1;表示平衡树的高度
2初始化最后一维数组
3通过omp_set_num_threads库函数设置线程数
4调用openMP库函数omp_get_wtime(获取当前时间start
#pragmaompparallelfor开始做并行区部分
结束后再次调用omp_get_wtime(获取时间end,end-start即为并行消耗时间
5算法核心部分:
算法先处理最后一层平衡树(假设个数为n),两个数据一组比较,取大的,生成新的一层平衡树(个数为n/2或者(n+1)/2),放在二维数组的上一维。
迭代处理每一层,最后使得新的一层个数为1,这个值就是最大值,即a[1][1];
并行处理每一层平衡树
代码如下:
#include
#include#includeconstintsize=10000;
usingnamespacestd;
inta[size+1][size+1];
intmain()
{
intnum=log(size-1)/log
(2)+1;
for(size_ti=1;i<=size;++i){//初始化
a[num][i]=i;
}
intm=0;
doublestart=omp_get_wtime();
for(size_ti=1;i<=size;++i)//串行if(a[num][i]>=m)m=a[num][i];
doubleend=omp_get_wtime();cout<<"串行:
"<intamax=size;
omp_set_num_threads(4);start=omp_get_wtime();
for(intk=num-1;k>=0;k--){
#pragmaompparallelfor
for(intj=1;j<=(amax-1)/2+1;j++){
if(2*j>amax)
a[k][j]=a[k+1][amax];
else
a[k][j]=a[k+1][2*j-1]>a[k+1][2*j]?
a[k+1][2*j-1]:
a[k+1][2*j];
}
}
end=omp_get_wtime();
cout«"并行:
"<system("pause");
}
2、问题规模对串、并行程序时间的影响(数列长度为N)
⑴通过不断增加问题规模,观察串行和并行程序的执行时间,得到如下表格的时
间消耗数据:
N
100
1000
10000
串行消耗
1.23e-6
1.35e-5
3.4e-5
(ms)
并行消耗
0.0031
0.0360
0.047
(ms)
(2)可以发现,并行总是比串行慢。
主要原因是:
平衡树算法对处理器个数有很高的要求,在处理器个数达到问题
规模的一半的时候才有最好的效果,本机只有4个线程,线程的调度反而使得整个时间消
耗比串行多。
3、线程数目对并行程序的影响(这里假设问题规模为:
N*M=10000*10000)
(1)在使用OpenMP进行并行执行矩阵加法时,我们可以自由设置进行并行计算的
并行线程数目
(2)在并行区域中,通过函数intomp_set_num_threads(in设置并行区域中要创建的
线程数,分别设置为2、4、816,得到如下表格的时间消耗
2
4
8
16
并行消耗
0.006
0.004
0.04
0.06
(ms)
(3)观察发现,在问题规模不变的前提下,随着线程数目的增加,问题解决的时间也在相应的减少。
但是,问题消耗的时间并不会随着线程数目的增加而不断的减少,原因可能是因为,随着线程数目的增减,线程的额外准备时间开销也将扩大。
四、心得体会
通过本次实验,学会了平衡树的算法设计思想,见识到了高性能计算在庞大任务规模面前的解决问题的能力。
在实验的过程中使用平衡树没有得到理想的结果,也说明了高性能计算在处理器方面的限制。
实验四:
使用OpenMP计算矩阵相乘
一、实验目的
1、掌握矩阵的乘法的串、并行算法
2、比较串行算法与并行算法在执行时间上的差别;
3、考察线程数目使用不同对并行算法执行时间的影响;
二、实验内容
1、给定两个矩阵A[N,M1]和B[M1,M]的乘积,即求C[N,M]=A[N,M1]*B[M1,M]。
三、实验步骤
1、整个程序的设计流程
计算矩阵的乘法,简单的使用三重循环完成,并行对最外层循环并行计算
1全局变量设置3个数组:
a[M+1][N+1],b[N+1][M+1],c[M+1][M+1]
2初始化三个数组
3通过omp_set_num_threads库函数设置线程数
4调用openMP库函数omp_get_wtime(获取当前时间start
#pragmaompparallelfor开始做并行区部分
结束后再次调用omp_get_wtime(获取时间end,end-start即为并行消耗时间
代码如下:
#include
#include
#define?
M?
500
#define?
N?
500
using?
namespace?
std;
int?
a[M+1][N+1],b[N+1][M+1],c[M+1][M+1];
int?
main()
{
//init?
array
for(int?
i=1;i<=Mi++)
for(int?
j=1;j<=N;j++)
a[i][j]=1;
for(int?
i=1;i<=N;i++)
for(int?
j=1;j<=Mj++)
b[i][j]=2;
〃parallel?
do
omp_set_num_threads(4);
double?
start=omp_get_wtime();
#pragma?
omp?
parallel?
for
for(int?
i=1;i<=Mi++)
for(int?
j=1;j<=Mj++)
for(int?
k=1;k<=Nk++)
c[i][j]+=a[i][k]*b[k][j];
double?
end=omp_get_wtime();
cout<<"并行:
"<//serial?
do
start=omp_get_wtime();
for(int?
i=1;i<=Mi++)
for(int?
j=1;j<=Mj++)
for(int?
k=1;k<=N|k++)
c[i][j]+=a[i][k]*b[k][j];
end=omp_get_wtime();
cout«"串行:
"<system("pause");
}
2、问题规模对串、并行程序时间的影响(二维数组为N*N)
⑴通过不断增加问题规模,观察串行和并行程序的执行时间,得到如下表格的时
间消耗数据:
N
100
300
10000
串行消耗
0.0072
0.119
0.49
(ms)
并行消耗
0.0198
0.100
0.31
(ms)
(2)可以发现,当规模较小时,串行算法仍然要比并行算法运行的快,当规模到达
一定程度的时候,并行运行的速度较串行有了提升。
并行算法对各个CPU的调度也占用一定的时间,当问题规模很小的时候,这个调
度时间占了很大的比重,而在规模较大的时候,这个调度时间就显得微乎其微了
3、线程数目对并行程序的影响(这里假设问题规模为:
N*M=500*500)
(1)在使用OpenMP进行并行执行矩阵加法时,我们可以自由设置进行并行计算的
并行线程数目。
(2)在并行区域中,通过函数intomp_set_num_threads(in设置并行区域中要创建的
线程数,分别设置为2、4、816,得到如下表格的时间消耗
2
4
8
16
并行消耗
0.418
0.254
0.252
0.352
(ms)
(3)观察发现,在问题规模不变的前提下,随着线程数目的增加,问题解决的时间也在相应的减少。
但是,问题消耗的时间并不会随着线程数目的增加而不断的减少,原因可能是因为,随着线程数目的增减,线程的额外准备时间开销也将扩大。
四、心得体会
挺水的一次实验,不是因为实验水,而是感觉跟第一次实验没什么区别,线程只是利用线程数去减少了时间开销,而不是降低了问题的复杂度。
主要是矩阵的乘法,自己没有用到好的算法。
不过目前计算矩阵的乘法还没有找到0(nT)或者比0(nA2)时间复杂度更小的算法吧