并行程序设计实验报告.docx
《并行程序设计实验报告.docx》由会员分享,可在线阅读,更多相关《并行程序设计实验报告.docx(12页珍藏版)》请在冰豆网上搜索。
并行程序设计实验报告
并行程序设计实验报告
公共部分
1.用MPI_Send、MPI_Recv实现MPI_Bcast、MPI_Alltoall、MPI_Gather、MPI_Scatter等MPI群及通信函数功能。
_MPI_Bcast:
程序运行结果如下
伪代码如下:
_MPI_Bcast(sendbuf,sendcount,sendtype,root,comm)
对每个处理器执行以下算法
ifmy_rank=rootthen
fori=0topdo//p为进程个数
MPI_Send(sendbuf,sendcount,sendtype,i,root,comm)//root向每个进程发送消息
endfor
endif
//每个进程从root接收带有root标签的消息,接受信息存在各自的sendbuf中
MPI_Recv(sendbuf,sendcount,sendtype,root,root,comm.,&status)
_MPI_Scatter:
将字符串”abcdefgh”以进程2为根散播出去,程序运行结果如下:
伪代码如下:
_MPI_Scatter(sendbuf,sendcount,sendtype,recvbuf,recvcount,recvtype,root,comm)
各处理器执行以下算法
ifmy_rank=rootthen
fori=0tosendcountdo
MPI_Send(sendbuf+i,1,sendtype,i,root,comm)
//将sendbuf中的信息按进程标识顺序发送给各个进程
endfor
endif
//每个进程从root处接收各自的消息,并存在recvbuf中第root号位置
MPI_Recv(recvbuf+root,1,recvtype,root,root,comm.,&status)
_MPI_Alltoall:
进程0到进程5存储的数据分别为”000000”到”555555”,经全局交换之后运行结果如下:
伪代码如下:
_MPI_Alltoall(sendbuf,sendcount,sendtype,recvbuf,recvcount,recvtype,comm)
对每个处理器执行以下代码:
fori=0top-1
_MPI_Scatter(sendbuf,sendcount,sendtype,recvbuf,recvcount,recvtype,i,comm)
//_MPI_Scatter即为前一个程序的伪代码
//Alltoall就是每一个进程都以自己为root执行一次Scatter
endfor
_MPI_Gather:
将四个进程的第3个字符汇聚到进程2,执行结果如下:
伪代码如下:
_MPI_Gather(sendbuf,sendcount,sendtype,recvbuf,recvcount,recvtype,root,comm)
对每个进程执行以下代码
MPI_Send(sendbuf,sendcount,sendtype,root,root,comm)
ifmy_rank=rootthen
fori=0top-1do
MPI_Recv(recvbuf+i,recvcount,recvtype,i,root,comm.,&status)
endfor
endif
2.LU分解的MPI实现(顺序划分)
5个节点、处理9x9矩阵时运行结果如下:
伪代码如下:
输入:
矩阵A(nxn)
输出:
下三角矩阵L(nxn),上三角矩阵U(nxn)
Begin
对所有处理器my_rank(0..p-1)同时执行如下算法:
fori=0tom-1do//对处理器的各行**************
forj=0top-1do
if(my_rank=j)then
v=j*m+i;//当前主行************************
fork=vtondo
f[k]=a[i,k]
endfor
else
v=j*m+i;//当前主行************************
接收主行所在处理器广播来的主行元素
Endif
if(my_rank=j)then//编号为j的处理器对其i+1行以后各行进行变换
fork=i+1tom-1do
a[k,v]=a[k,v]/f[v]
forw=v+1ton-1do
a[k,w]=a[k,w]–f[w]*a[k,v]
endfor
endfor
if(my_rank>j)then//编号大于j的处理器对其所有行变换
fork=0tom-1do
a[k,v]=a[k,v]/f[v]
forw=v+1ton-1do
a[k,w]=a[k,w]–f[w]*a[k,v]
endfor
endfor
endif
endfor
endfor
end
大体思路如同上面的伪代码给出,核心思想就是如果当前主行在第j号处理器,那么按照顺序划分的想法,编号小于j的处理器已经变换完了自己的各行,不需要做什么处理;编号为j的处理器应用当前主行为其j+1行等后续各行变换;编号大于j的处理器其各行都还没有经过变换,所以应用主行对其所有行进行变换。
有几个地方需要说明,以上伪代码只适用于处理器个数能被矩阵行数整除的情况,例如9行9列3个处理器这样。
为了能够对任意数目处理器适用,需做以下改进:
记录nmodp为left,当left等于0或者当前处理器编号小于left的时候,说明这些处理器都有m行数据需要处理,而其他各行都只有m-1行数据需要处理。
例如矩阵为11x11,有3个处理器,则m=ceil(11/3)=4,left=11mod3=2,所以处理器0和处理器1有4行数据,处理器2只有3行数据。
这导致算法中用”***********************”标注的行需做必要修改,在矩阵发送与结果接收的时候同样要做一些修改,该问题在此处不是主要矛盾,故不赘述,详情可参见代码ludep.c。
编写的程序已经能够正常处理不能整除的情况,参见算法之前给出的5个处理器的运行结果。
加速表如下:
去除了输入输出时间,纯并行计算的时间
规模节点数
2
4
8
500
0.355469
0.203125
0.179688
1000
2.835938
1.527344
0.988281
2000
22.835938
12.609375
6.816406
从以上加速表可见,当规模增加的时候,如果节点数不变,并行算法计算的时间相应延长。
当规模不变处理器数目增加的时候,如果问题规模不太大,则算法运行时间降低,但不是线性降低,即处理器越多,由并行带来的加速效果变化越来越小(如规模500和1000的问题,8处理器相对于4处理器的加速效果弱于4处理器相对于2处理器的加速效果)。
可以验证当处理器过多的时候(与规模有关),并行算法非但不能降低运行时间,反而会延长。
这些都是因为消息传输花费的时间过多。
如果规模相对于处理器数目比较大,那么处理器数目的增加几乎能带来等比例的加速效果的提升(如规模2000的问题,8处理器相对于4处理器的加速效果几乎与4处理器相对于2处理器的加速效果相同),因为此时通信时间相对于运行时间还不那么明显。
3.LU-OpenMP
3线程处理9x9矩阵时运行结果如下:
加速表如下:
去除了输入输出时间,纯并行计算的时间
规模线程数
2
4
8
500
0.362900
0.185099
0.233649
1000
2.934302
1.442188
1.485869
2000
23.556917
11.816813
11.932859
从以上加速表可见,当规模增加的时候,如果线程数不变,并行算法计算的时间相应延长。
当规模不变而线程数目增加的时候,一定变化范围内算法运行时间几乎随处理器数目线性降低。
而如果线程数目过多,运行时间几乎不再改变甚至有所增加,这是由于每个核的处理能力、资源都有限,过多的线程不能继续提高并行计算的效率,反而要花更多的时间调度分配,导致效率不能继续提高甚至有所下降。
依赖关系如下:
图中设第k行为主行,纵坐标为矩阵A的行号,从k起始,横坐标为矩阵A的列号,从k起始。
从上图可见,主行k中每列元素对之后各行每列元素进行变换,同时各行的第k列元素对之后各列元素进行变换,即各行内部有依赖关系,而各行之间没有依赖关系,所以可以按照行划分。
4.划分通信域
伪代码如下:
每个处理器执行以下操作:
MPI_Get_processor_name(name,&namelength)
Color=atoi(name+4)//我们节点的名称都是以node起始,后面是编号
//按照Color的值分割当前通信域,以当前my_rank为key
MPI_Comm_split(MPI_COMM_WORLD,Color,my_rank,&SplitWorld)
分组实验
MPI、OpenMP混合编程:
所选试验为第21章的求解矩阵最大特征向量值的乘幂法。
给出一个处理500x500矩阵的运行结果如下:
加速表如下:
其中A为问题规模,B为OpenMP进程数目,C为MPI分配节点数目。
表中数据为并行计算的时间,已经去除了读取、输出的时间,单位为秒。
OpenMP中Chunk值设50。
C
2
4
B
A
2
4
8
2
4*
8
500
0.019531
0.011719
0.277344
0.011719
0.007812
0.265625
1000
0.050781
0.035166
0.222656
0.031250
0.023438
0.234375
2000
0.187500
0.105469
0.273438
0.101562
0.062500
0.261719
从上述加速数据表可以看出:
随问题规模增大,当节点数、线程数不变的时候计算时间逐渐变大。
MPI并行(进程级)与OpenMP并行(线程级)可以获得比单一方法更为有效的计算结果,运算时间缩短非常明显。
当规模不变的时候,对于固定线程数,随节点数目上升运行时间下降,但节点数目过多的时候由于通信消耗过多,时间不会一直下降,甚至可能回升;对于固定节点数目,一定范围内,随线程数增加运行时间逐渐缩短。
但当线程数目过多的时候,由于单个处理器运行能力和资源都有限,过多的线程造成的调度等消耗过大,计算时间反而会提高。
通过这个表格我们也可以知道,对于并行算法,不是利用的处理器个数越多效果越好,因为存在通信开销;同样,对于单个芯片上的并行计算,不是线程数越多越好,当超过处理器计算能力,调配等带来的开销可能比并行计算带来的时间减少更多。
针对本次实验环境,最好的搭配应该是4个节点、4个线程。
(图中打*号、用黄色标记)
学号:
SC11011033
在曙光机上的文件夹截图如下:
文件夹中有实验的所有源程序、可执行程序及生成随机矩阵用以求最大特征值的程序
RandomMatrix和生成可以LU分解的随机矩阵用以验证LU分解程序的程序
RandomLUMatrix。
data4eig.txt为RandomMatrix给出的随机矩阵结果。
data4lu.txt为RandomLUMatrix给出的可LU分解的随机矩阵结果。