并行程序设计实验报告.docx

上传人:b****2 文档编号:2556494 上传时间:2023-05-04 格式:DOCX 页数:12 大小:258.53KB
下载 相关 举报
并行程序设计实验报告.docx_第1页
第1页 / 共12页
并行程序设计实验报告.docx_第2页
第2页 / 共12页
并行程序设计实验报告.docx_第3页
第3页 / 共12页
并行程序设计实验报告.docx_第4页
第4页 / 共12页
并行程序设计实验报告.docx_第5页
第5页 / 共12页
并行程序设计实验报告.docx_第6页
第6页 / 共12页
并行程序设计实验报告.docx_第7页
第7页 / 共12页
并行程序设计实验报告.docx_第8页
第8页 / 共12页
并行程序设计实验报告.docx_第9页
第9页 / 共12页
并行程序设计实验报告.docx_第10页
第10页 / 共12页
并行程序设计实验报告.docx_第11页
第11页 / 共12页
并行程序设计实验报告.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

并行程序设计实验报告.docx

《并行程序设计实验报告.docx》由会员分享,可在线阅读,更多相关《并行程序设计实验报告.docx(12页珍藏版)》请在冰点文库上搜索。

并行程序设计实验报告.docx

并行程序设计实验报告

并行程序设计实验报告

公共部分

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分解的随机矩阵结果。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 教学研究 > 教学计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2