姓名: 学号:
一、实验目的
通过本次试验,了解使用OpenMP编程的基本方法和MPI的编程方法,通过实践实现的基本程序,掌握基本的线程及进程级并行应用开发技术,能够分析并行性能瓶颈及相应优化方法。
二、实验环境
Linux操作系统,mpi库,多核处理器
三、实验设计与实现
(一)MPI并行程序设计
用MPI编写一个greeting程序,编号为0的进程接受其它各进程的“问候”,并在计算机屏幕上显示问候情况。
用MPI编写一个多进程求积分的程序,并通过积分的方法求的值,结果与的25位精确值比较。 (二)多线程程序设计
用Pthreads或OpenMP编写通过积分的方法求的程序。把该程序与相应的MPI程序比较。
用Pthreads或OpenMP编写编写矩阵相乘的程序,观察矩阵增大以及线程个数增减时的情形。
四、实验环境安装
(一)MPI环境安装
1.安装kylin操作系统的虚拟机(用VirtualBox)
2.安装增强功能,使之与windows主机能够文件共享。
3.拷贝mpich-3.0.4.tar.gz到/root/myworkspace/目录下,并解压(tar xzf mpich-3.0.4.tar.gz)
4.下面开始安装
mkdir /root/myworkspace/mpi
./configure --prefix=/root/myworkspace/mpi --disable-f77 --disable-fc
make
make install
5.配置环境变量
打开/root/.bashrc文件,在文件的末尾加上两行:
PATH=$PATH:/root/myworkspace/mpi/bin export PATH
保存退出,然后执行命令
source /root/.bashrc
(二)openMP实验环境安装
Visual Studio中修改:项目->属性->c/c++->语言,将“OpenMP支持”改成“是”:
五、实验结果及分析
(一)MPI并行程序设计
实验一:问候发送与接收
非零号进程将问候的信息发送给0号进程,0号进程依次接收其它进程发送过来的消息并将其输出。结果如下图:
实验二:多进程通过积分求π,并与精确值比较
由公式:
4dx2, 01x1得π的近似值为:
4NfNi1i0.5 N将0到1的区间分成多份,每个进程负责其中几份的积分运算,最后非零进程将结果传至零号进程,由零号进程负责将各个进程的积分结果求和并与精确值作比较。结果如下图:
(二)OpenMP并行程序设计
实验一:多线程积分求π
由公式:
4dx201x,
1得π的近似值为:
4Ni0.5fNi1N
在for循环之前添加OpenMP的引导语句“#pragma omp parallel for private(x) reduction (+:sum)”,将整个for循环分配到各个线程中去执行,并通过reduction操作将各自的sum和相加得到整个for循环求积分的结果。
一个线程运行时:
五个线程运行时:
十个线程运行时:
实验二:多线程求矩阵乘运算
随着矩阵规模的增加,运行的时间变长。在规模小时,增大线程数时,时间减少不明显,有时还会出现时间增多的情况。规模大时,增大线程数会明显减少运行的时间,但是并不是线性的。当线程数超过最大的节点核数时,随着线程的增多,总的运行时间会变大。
一个线程运行时:
五个线程运行时:
五、实验心得体会
在本次试验中,清楚的掌握了MPI和openMP的基本概念,通过对环境的安装,对两种环境又有了很好的认识。通过在两种环境中的编程实验,对MPI和openMP的并行编程技术有了基本的了解。但是因为时间有限,对两种编程方式还没有很深刻和熟悉的把握,也将在以后工作中继续学习,并掌握进程线程都并行的方法。
六、实验源代码
(一)MPI并行程序设计
实验一:问候发送与接收(mpi_1.cpp)
#include int main(intargc,char**argv) { char message[30]; intrank,size; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&size); if(rank!=0) { sprintf(message,\"greeting from %d.\",rank); MPI_Send(message,strlen(message),MPI_CHAR,0,10,MPI_COMM_WORLD); } if(rank==0) { for(inti=1;i printf(\"Received all, from process %d\\n\",rank); } MPI_Finalize(); return0; } 实验二:多进程通过积分求π,并与精确值比较(mpi_2.cpp) #include #define LENG_PER_PRO 10000 #define PI 3.1415926535897932384626433 int main(intargc,char**argv) { intrank,size; intnum=LENG_PER_PRO; double sum=0,block,all,diff; double pi=PI; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&size); block=1/((double)(num*size)); for(inti=0;i if(rank==0) {for(int j=1;j printf(\"PI is %1.20f \\n\",sum); diff=((sum-pi))/pi; printf(\"difference is %1.20f\\n\",diff); } else { MPI_Send(&sum,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD); } MPI_Finalize(); return0; } (二)OpenMP并行程序设计 实验一:多线程积分求π(openMP_1.cpp) #include #define PI 3.1415926535897932384626433 #define NUM_THREADS 10 int main() { doublex,sum=0.0,diff; double pi=PI; double block=1/((double)STEPS); omp_set_num_threads(NUM_THREADS); #pragma omp parallel for private(x) reduction (+:sum) for(inti=0;i } printf(\"PI is %1.20f .\\n\",sum*block); diff=((sum*block-pi))/pi; printf(\"difference is %1.20f\\n\",diff); return0; } 实验二:多线程求矩阵乘运算(openMP_2.cpp) #include int z=size; int a[z][z],b[z][z],c[z][z]; structtimevalstart,end; floatall_time; for(int x=0;x gettimeofday(&start,NULL); omp_set_num_threads(NUM_THREADS); #pragma omp parallel for for(inti=0;i gettimeofday(&end,NULL); all_time=(end.tv_sec-start.tv_sec)+(float)(end.tv_usec-start.tv_usec)/1000000.0; for(inti=0;i printf(\"run time:\%f s\\n\",all_time); return0; } 因篇幅问题不能全部显示,请点此查看更多更全内容