13281069谢洁MPI实验.docx
《13281069谢洁MPI实验.docx》由会员分享,可在线阅读,更多相关《13281069谢洁MPI实验.docx(19页珍藏版)》请在冰点文库上搜索。
13281069谢洁MPI实验
MPI实验报告
一、MPI实验第一部分
MPICH2具体安装配置过程
1、双击mpich2-1.4-win-ia32.msi安装程序,一直按next直到finish即可完成MPICH2的安装。
2、通过开始à控制面板à用户账户和家庭安全à用户账户à创建密码给电脑管理员帐号设置一个密码。
3、注册用户名,具体操作如下:
开始à所有程序àMPICH2àwmpiregister.exe.该用户名和密码必须为上面所设置的操作系统管理员账户和密码。
4、通过开始à所有程序àMPICH2àwmpiexec.exe打开软件运行面板
MPI程序代码
1.利用microsoftvisualC++6.0编写课件中的HelloWorld工程,在代码的#include语句之前添加#defineMPICH_SKIP_MPICXX语句,程序代码如下图所示:
2.通过ToolsàOptions将MPICH2目录下的\lib和\include文件夹添加到工程中
3.同时拷贝\lib文件夹中的mpi.lib和cxx.lib文件到工程目录下
4.通过ProjectàSettingàLink在Object/librarymodules最后面添加mpi.lib和cxx.lib。
运行结果截屏
编译代码,在工程的debug目录下生成了一个.exe文件。
打开wmpiexec.exe,将刚刚编译产生的.exe文件添加到Application中,将Numberofprocess更改成8或以上,点击Execute,则可看到执行结果如下图:
实验分析总结
分析如下MPI程序代码:
if(myid==2)MPI_Send("HELLO",5,MPI_CHAR,7,1234,MPI_COMM_WORLD);
if(myid==7){
MPI_Recv(string,5,MPI_CHAR,2,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
printf("Got%sfromp%d,tag%d\n",string,status.MPI_SOURCE,status.MPI_TAG);
}
myid变量中所存的为当前进程在给定的通信域中的进程标识号。
进程标志为2的进程为源进程,它将缓存中的数据“HELLO”发送给进程标志号为7的进程;进程标志为7的进程为目的进程,它从源进程中接受数据,并输出数据的内容及源进程标志号。
本实验安装过程中要注意注册的用户名和密码要和所设置的操作系统管理员账户和密码相同,否则不能运行。
二、MPI实验第二部分
程序代码
//shiyan2.cpp:
Definestheentrypointfortheconsoleapplication.
#include"stdafx.h"
#defineMPICH_SKIP_MPICXX
#include"mpi.h"
#include"stdio.h"
staticlongnum_steps=100000;
voidmain(intargc,char*argv[])
{
inti_start,i_end,i,myid,numprocs;
doublepi,mypi,x,step,sum=0.0;
doublestartwtime=0.0,endwtime;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
if(myid==0)startwtime=MPI_Wtime();
MPI_Bcast(&num_steps,1,MPI_INT,0,MPI_COMM_WORLD);
i_start=myid*(num_steps/numprocs);
i_end=i_start+(num_steps/numprocs);
step=1.0/(double)num_steps;
for(i=i_start;i{
x=(i+0.5)*step;
sum=sum+4.0/(1.0+x*x);
}
mypi=step*sum;
MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
if(myid==0)
{
printf("Pi=%f\n",pi);
endwtime=MPI_Wtime();
printf("wallclocktime=%f\n",endwtime-startwtime);
}
MPI_Finalize();
}
运行结果截屏
1、单机运行截图
2、双机运行截图
实验分析总结
1、概念:
粒度是描述模糊不确定对象的工具。
粒度计算是信息处理的一种新的概念和计算范式,覆盖了所有与粒度相关的理论、方法、技术和工具,主要用于不确定、不完整的模糊海量信息的智能处理。
计算负荷也称需要负荷或最大负荷。
计算负荷是一个假想的持续负荷,其热效应与同一时间内实际变动负荷所产生的最大热效应相等
并行度是指指令并行执行的最大条数。
在指令流水中,同时执行多条指令称为指令并行。
并行度有一个显著特点就是可以最大限度的利用到多个CPU,在系统不忙或者是错开高峰期的时候,应该是一个非常不错的选择。
2、分析总结:
本实验用多台计算机、多进程并行计算Pi值,并求出计算所用时间,进行比较。
程序使用MPI_Comm_size(MPI_COMM_WORLD,&numprocs)函数获得该通信域中进程总数存放在numprocs中,并且根据进程数目,通过以下代码为各个进程分配计算任务:
MPI_Bcast(&num_steps,1,MPI_INT,0,MPI_COMM_WORLD);
i_start=myid*(num_steps/numprocs);
i_end=i_start+(num_steps/numprocs);
从而将总的计算任务分为numprocs个部分,每个进程负责一个部分的计算,并且获得每个进程进行循环计算的开始值和终止值。
每个进程通过下面代码
for(i=i_start;i{
x=(i+0.5)*step;
sum=sum+4.0/(1.0+x*x);
}
mypi=step*sum;
计算出所负责的任务部分的结果存入mypi中。
最后程序通过MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD)函数将每个进程缓冲区中的数据按给定的操作进行计算,并将计算结果返回到根进程0的输出缓冲区中。
最后
将所得的Pi值输出。
单机运行截图可知,单台机器计算时,当进程数从1增加至3时,计算所用时间从0.000431减少至0.000172,而后进程数继续增加至5,计算所用时间则从0.000172增加至0.000225,若进程数继续增加,则所用的时间更长,当进程数增加到50时,计算所用的时间达到0.003400。
可见,在一定的范围内(进程数较少时)进程数增加,计算所用的时间减少,但是当进程数增加到一定程度之后,若再继续增加进程,计算时间反而增加。
由双机运行截图可知,双机运行时,在一定的范围内(进程数较少时)进程数增加,计算所用的时间减少,但是当进程数增加到一定程度之后,若再继续增加进程,计算时间反而增加。
当进程数为较少时,双机运算所用的时间与单机运行没有太大的区别,当进程数较大时(如进程数为30,50时)双机运算所用的时间比单机运行所用的时间略小。
三、MPI实验第三部分
MPI程序代码
//shiyan3.cpp:
Definestheentrypointfortheconsoleapplication.
#include"stdafx.h"
#defineMPICH_SKIP_MPICXX
#include"stdio.h"
#include"mpi.h"
intmain(intargc,char*argv[])
{
inttaskid,ntasks;
intierr,i,j,itask;
intbuffsize;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
MPI_Comm_size(MPI_COMM_WORLD,&ntasks);
if(taskid==0){
printf("\n\n\n\n\n");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==0)printf("Hel");
if(taskid==1)printf("lo");
if(taskid==2)printf("Wor");
if(taskid==3)printf("ld!
");
fflush(stdout);
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==0)printf("(Unordered)\n");
if(taskid==0){
printf("Hel");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==1){
printf("lo");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==2){
printf("Wor");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==3){
printf("ld!
");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==0){
printf("(Ordered)\n\n\n\n\n");
}
MPI_Finalize();
return0;
}
运行结果截屏
实验分析总结
1、两个概念
同步路障是在并行系统中,使一组进程取得同步的一种方法。
它在参与障碍同步的每个进程的程序中彼此必须等待的位置设置一个障碍点,当某进程执行到障碍点时暂停,等待所有进程都执行到这个障碍点上,它们才能继续运行。
同步计算分为全同步和部分同步。
全同步:
所有的进程在一些规则的执行点上的同步。
部分同步或局部同步:
在逻辑上相邻的一组进程参与的同步。
2、实验分析总结
本程序的输出两行字符串,其中第一行是无序的(Unordered),第二行是有序的(ordered),执行老师所给的代码,所得的结果如下图所示:
可见两行输出均是无序的,这不符合我们的预期结果。
通过分析我在老师课件上给出的代码上加了两行代码fflush(stdout);(即上面MPI程序代码中蓝色部分),再次运行可见当进程数大于等于4时,第二行输出均为”HelloWorld!
”字符串,为有序的,而第一行输出为无序字符串。
程序调用MPI_Barrier(MPI_COMM_WORLD)语句,该函数使得阻塞通信域内的所有进程,直到它们都达到这个时间,即,所有进程相互同步。
在该调用返回后,可以保证组内的所有进程都已经执行完了调用之前的所有操作,从而可以开始该调用后的操作。
本程序可以分为两个部分,分别对应两行字符串的输出。
第一部分输出的为无序的字符串,分析下面代码:
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==0)printf("Hel");
if(taskid==1)printf("lo");
if(taskid==2)printf("Wor");
if(taskid==3)printf("ld!
");
fflush(stdout);
ierr=MPI_Barrier(MPI_COMM_WORLD);
可知当执行完第一条语句之后,组内所有进程都开始执行该语句后面的语句,因为进程执行的速度不一定,所以四个字符串输出的顺序也是不一定的,所以会输出一串无序的字符串(Unordered)。
之后刷新缓冲区,并且调用MPI_Barrier函数等待所有线程都完成前面操作。
第二部分的输出为有序字符串,分析下面代码:
if(taskid==0){
printf("Hel");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==1){
printf("lo");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==2){
printf("Wor");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
if(taskid==3){
printf("ld!
");
fflush(stdout);
}
ierr=MPI_Barrier(MPI_COMM_WORLD);
此段代码每输出一次都进行一次缓冲区刷新,并且调用MPI_Barrier函数等待其它进程均执行完前面代码。
所以程序会根据taskid的值从小到大一次输出对应的字符串。
所以会输出一串有序的字符串”HelloWorld!
”。