基于C++实现多核平台下的并行计算课程实验

多核平台下的并行计算课程实验报告

1.填写下表,给出所使用的软硬件环境参数

操作系统版本

Ubuntu 16.04

并行编程模型

MPICH-3.2

编译器版本

gcc 5.4.0

CPU 型号、主频及核数

Intel(R) Core(TM) i5-4200H CPU @ 2.80GHz

内存型号,大小及主频

FPM EDO DIMM SDRAM;1024

2.综合题目 1 和题目 2,在提交的报告中需要给出至少四个如下表 格记录计算时间和加速比:(也可以自己设计图表描述不同线程数 时程序的运行时间及加速比)

3000X3000 (使用常数 d)

线程数目

运行时间(秒)

加速比

1

334.08

461.95/334.08=1.382

2

269.34

461.95/269.34=1.715

4

223.69

461.95/223.69=2.065

8

309.13

461.95/309.13=1.494

16

652.20

461.95/652.20=0.708

……

……

……

3000X3000 使用((i-k)2和(j-k)2)

线程数目

运行时间(秒)

加速比

1

303.99

360.81/303.99=1.187

2

289.15

360.81/289.15=1.248

4

268.84

360.81/268.84=1.342

8

380.04

360.81/380.04=0.949

16

778.66

360.81/778.66=0.463

……

……

……

5000X5000(使用常数 d)

线程数目

运行时间(秒)

加速比

1

1818.32

1947.51/1818.32=1.071

2

3685.13

1947.51/3685.13=0.529

4

3291.24

1947.51/3291.24=0.592

8

7441.92

1947.51/7441.92=0.262

16

时间太长,死机

根据规律,低于0.262

……

……

……

5000X5000使用(i-k)2和(j-k)2)

线程数目

运行时间(秒)

加速比

1

1778.46

4991.53/1778.46=2.807

2

3791.12

4991.53/3791.12=1.317

4

3323.69

4991.53/3323.69=1.502

8

8241.85

4991.53/8241.85=0.606

16

时间太长

根据规律,低于0.606

……

……

……

3.并行算法设计和优化思路

算法设计过程

1.首先写出串行实现的代码

基本是十分简单的逐行计算

int one(int i,int j,int **M,int S[26][26],char *X,char *Y);

计算M(i-1,j-1)+S(Xi,Yj)

int two(int i,int j,int **M,int d);

计算M(k,j)+d

int three(int i,int j,int **M,int d);

计算M(i,k)+d

int max(int i,int j,int **M,int S[26][26],int d,char *X,char *Y);

计算 M(i,j)

随后逐行逐列计算M(i,j)

2.改成并行

算法思路:由于矩阵中每一个数都依赖于它左、右和斜上方的值,斜向行列之间的关联却不强,由此可以设计出一个算法。

将矩阵M分成适当的小块,当第(0,0)块计算完成时,第(1,0),(0,1)块就变得可以计算,这两块结束后,(2,0),(1,1),(0,2)变得可以计算。

将这个思路延续下去,我们利用多开的核来计算斜方向上互不相干的数据块,再利用MPI的消息传递汇拢至0号进程,循环往复,最终实现程序的并行。

3.Block类

用c语言写的代码不能创建class 将文件改为c++语言即可使用class类

同时发现mpicc不能编译c++  则将makefile中编译指令改为mpicxx

Block类中有参数int row_begin,row_end,col_begin,col_end分别代表所分成小块的行数起止和列数起止,int block代表用一维数组存放的数据块,int calculate()方法用来计算数据。

4.计算过程

a.算第一小块(0,0),每个进程都具有的第一步

b.计算左上分块,即斜对角线以上的所有块。利用循环,每次调用几个进程计算一条斜线列,将结果返回到0进程,并由0号进程将数据安放至M内

c.计算右下分块,即斜对角线以下的所有块,循环同b

例:

block_x=block_line-rank;
block_y=rank;
local_block=blocks[block_x][block_y];

上述三行代码是过程b中用于确定分块位置与进程关系的,即本进程应该被分配到哪一块数据块。

d.分块为正方形,可能矩阵M中会有没有分成块的剩余行列,由进程0在最后单独计算,完成矩阵M。

5.获取命令行参数dimension 和M 的行号 row_number

条件:int main (int argc, char **argv)中 argv储存了命令行输入的参数,argv[0]是./main命令本身,argv[1]为dimension,argv[2]为row_number

Atoi()用于将字符串转为整型数

1.获取dimension

dimension=atoi(argv[1]);  
dimensionx=dimension+1; //实际的矩阵比输入的行列大一圈

2.获取row_number

row_number=atoi(argv[2]);

6.消息传递

MPI_Bcast(M_storage,LX*LY,MPI_INT,0,MPI_COMM_WORLD);

用于将0号进程内的M矩阵散播给各个进程,更新它们的数据

MPI_Barrier(MPI_COMM_WORLD);

每个进程运行到此处都会停下,直到所有进程都调用到了这个方法,用于同步进程。

点对点通信

if(rank!=0){
    MPI_Send(&row_begin,1,MPI_INT,0,1,MPI_COMM_WORLD);
    MPI_Send(&col_begin,1,MPI_INT,0,2,MPI_COMM_WORLD);
    MPI_Send(bloc,length*length,MPI_INT,0,3,MPI_COMM_WORLD); 
}

除0号之外的进程将本身计算完毕的数据块发送给0

for(int c=1;c<=block_line;c++){
    MPI_Recv(&row_begin,1,MPI_INT,c,1,MPI_COMM_WORLD,MPI_STATUS_IGNORE);  
    MPI_Recv(&col_begin,1,MPI_INT,c,2,MPI_COMM_WORLD,MPI_STATUS_IGNORE); 
    MPI_Recv(bloc,length*length,MPI_INT,c,3,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
}

0号进程接收每一个进程的数据并放入M内

测试时间

单独创建time.cc,用于测试main.cc的运行速度0

使用MPI_Wtime()方法记录时间,并调用system()运行待测试程序

例:./time 3 main 200 7

./time是测试时间的程序,3是运行的核数,main为并行计算程序,200是维度数dimension,7为希望输出的行数row_number 将会输出程序运行时间

优化

1.代码中

由于类Block中int* calculate()方法内计算数据块时已经随时更新了矩阵M中的数值,所以在进程0中就不必将自己bloc块中的数字复制到M上去了,只需要接收从其他进程传来的bloc数组,将他们的数据放进M里

2.算法上

广播矩阵M

由于M是个二维数组,每一行的地址是不连续的,所以没办法用一个MPI_Bcast()就广播出去。

int* M_storage=new int[dimensionx*dimensionx];
int** M=(int**)malloc(sizeof(int*)*dimensionx);  
for(i=0;i<dimensionx;i++)  
	M[i]=&M_storage[i*dimensionx];

如上,指定一个一维数组M_storage,一个二维数组M,将二者的地址联系起来,如此M的行与行之间就连续了。

M_storage专门用来广播,M用来作二维数组调用

3.编译时

-O2     提供更加高级的代码优化,会占用更长的编译时间

在Makefile的编译语句中加入-O2,注意O为大写

经测试,的确提升了程序运行速度

说明

并行计算

在“源程序“文件夹中有”题目1并行版本“,”题目1串行版本“,”题目2并行版本“,”题目2串行版本“等文件夹

每个文件夹中都有相应的源程序代码和 Makefile,ReadMe等,里面有单独的执行命令

执行命令在此总览如下

main为计算程序

time为测试运行时间程序

使用make命令编译

以下为命令行指令

并行

mpirun -np 核数 ./main dimension row_number

例:  mpirun -np 3 ./main 7 5

意为:用3个核进行计算,执行main程序,维度为7,输出第5行的结果

检测并行计算时间

./time 核数 main dimension row_number

例:  ./time 3 main 200 7

意为:用3个核进行计算,执行main程序,维度为200,输出第7行的结果,并输出程序运行时间

串行

./mainchuanxing dimension row_number

例:  ./mainchuanxing 200 7

意为:执行main程序,维度为200,输出第7行的结果

检测串行时间

./timechuanxing mainchuanxing dimension row_number

例:  ./timechuanxing mainchuanxing 200 7

意为:执行main程序,维度为200,输出第7行的结果,并输出程序运行时间

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神仙别闹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值