openMP实验总结报告43845.pdf
openMP 实验报告 目录 openMP 实验报告.错误!未定义书签。OpenMP 简介.错误!未定义书签。实验一.错误!未定义书签。实验二.错误!未定义书签。实验三.错误!未定义书签。实验四.错误!未定义书签。实验五.错误!未定义书签。实验六.错误!未定义书签。实验七.错误!未定义书签。实验八.错误!未定义书签。实验总结.错误!未定义书签。在学习了 MPI 之后,我们又继续学习了有关 openMP 的并行运算,通过老师的细致讲解,我们对 openMP 有了一个初步的了解:OpenMP 简介 OpenMP 是一种用于共享内存并行系统的多线程程序设计的库(Compiler Directive),特别适合于多核 CPU 上的并行程序开发设计。它支持的语言包括:C语言、C+、Fortran;不过,用以上这些语言进行程序开发时,并非需要特别关注的地方,因为现如今的大多数编译器已经支持了 OpenMP,例如:Sun Compiler,GNU Compiler、Intel Compiler、Visual Studio 等等。程序员在编程时,只需要在特定的源代码片段的前面加入 OpenMP 专用的#pargma omp 预编译指令,就可以“通知”编译器将该段程序自动进行并行化处理,并且在必要的时候加入线程同步及通信机制。当编译器选择忽略#pargma omp预处理指令时,或者编译器不支持 OpenMP 时,程序又退化为一般的通用串行程序,此时,代码依然可以正常运作,只是不能利用多线程和多核 CPU 来加速程序的执行而已。OpenMP 使得程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,它是一个很好的选择。同时,使用OpenMP 也提供了更强的灵活性,可以较容易的适应不同的并行系统配置。线程粒度和负载平衡等是传统多线程程序设计中的难题,然而,在 OpenMP 中,OpenMP库从程序员手中接管了部分这两方面的工作,从而使得程序员可以更加专注于具体的算法本身,而非如何编程使得代码在 CPU 负载平衡和线程粒度方面做出平衡。但是,作为高层抽象,OpenMP 并不适合需要复杂的线程间同步和互斥的场合。OpenMP 的另一个缺点是不能在非共享内存系统(如计算机集群)上使用。在这样的系统上,MPI 使用较多。实验步骤:通过编写了一些程序,验证了关于 openMP 的一些简单的性质。实验一 代码:#include#include#include int main(int argc,char*argv)int id,numb;omp_set_num_threads(3);#pragma omp parallel private(id,numb)id=omp_get_thread_num();numb=omp_get_num_threads();printf(I am thread%d out of%d n,id,numb);system(pause);return 0;实验结果:可以看到,因为三个进程同步执行,所以输出顺序是乱序的,就是表示运行优先级相同。当把进程数改成 10 的时候,得到下面的结果:与上面的到的结论(并行并行运算)相同。实验二 代码:#include#include#include int main(int argc,char*argv)int id;omp_set_num_threads(2);#pragma omp parallel printf(what will you seen);#pragma omp for for(int i=1;i=5;+i)printf(i=%d of%dn,i,omp_get_thread_num();printf(How many answersn);system(pause);return 0;实验运行结果:可以看到,在设置进程为 2 的情况之下,运算(计算规模)被等可能的分配给各个进程。实验三 代码:#include#include#include int main()#pragma omp parallel sections 实验四 代码:#include#include#include int main()#pragma omp parallel for(int i=0;i 100;+i)std:cout i +std:endl;#pragma omp barrier for(int j=0;j 10;+j)std:cout j -std:endl;system(pause);return 0;运行结果:结果分析:在语句#pragma omp barrier 的作用下,只有当上面所有的进程计算工作全部完成之后,才会继续barrier之后的工作。实验五 代码:#include#include#include#include using namespace std;int main()int sum=0;cout Before:sum endl;#pragma omp parallel for for(int i=0;i 100;i+)#pragma omp critical(a)sum+=i;sum+=i*2;cout After:sum endl;system(pause);return 0;运行结果:结果分析:CRITICAL 指令指定一块同一时间只能被一条线程执行的代码区域 各个线程还是并行执行 for 里面的语句,但当你们执行到 critical 里面时,要注意有没有其他线程正在里面执行,如果有的话,要等其他线程执行完再进去执行。实验六 代码:#include#include#include#include using namespace std;#define NUM_THREADS 2 static long num_steps=100000;int main()int i,id;double x,pi,sum=;double step=/(double)num_steps;omp_set_num_threads(NUM_THREADS);#pragma omp parallel private(x,i,id)reduction(+:sum)id=omp_get_thread_num();for(i=id+1;i=num_steps;i=i+NUM_THREADS)x=(i-*step;sum+=/+x*x);pi=sum*step;printf(pi=%.12fn,pi);system(pause);return 0;运行结果:结果分析:很简单,通过并行运算,发挥计算机多核的优势,自然能够较单核计算更快的得出计算结果,但是要注意计算机的核数是有限制的,不能无限扩大并行计算线程。实验七 代码:#include#include#include#include using namespace std;int i=0,sum1,sum2,sum3,sum;int main()#pragma omp parallel sections num_threads(3)#pragma omp section for(i=0;i 100;i+)sum1+=i;#pragma omp section for(i=100;i 200;i+)sum2+=i;#pragma omp section for(i=200;i 300;i+)sum3+=i;sum=sum1+sum2+sum3;printf(sum=%dn,sum);system(pause);return 0;运行结果:结果分析:这里需要将累计求和值得部分和分配给几个变量的原因是:当多个线程并行执行时,有可能多个线程同时对某变量进行了读写操作,从而导致不可预知的结果,因为多线程计算如果只设置一个 sum,每次增加的值可能是不同进程的,从而导致运算结果混乱,但是如果把不同进程的计算结果分别保存,这样就不会出现结算结果错误的问题。实验八 将 openMP 与之前学习过的 MPI 实验进行综合,通过计算 PI 的运算时间的比较得出结论 代码:#include#include#include staticlong num_steps=100000;#define NUM_THREADS 4 void main(int argc,char*argv)int i_start,i_end,i,myid,numprocs;double pi,mypi,x,step,sum=;double start,end;MPI_Init(&argc,&argv);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);if(myid=0)start=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=/(double)num_steps;omp_set_num_threads(NUM_THREADS);#pragma omp parallel private(x,i)reduction(+:sum)for(i=i_start;i i_end;i+=NUM_THREADS)x=(i+*step;sum=sum+/+x*x);mypi=step*sum;MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);if(myid=0)printf(Pi=%fn,pi);end=MPI_Wtime();printf(Run time is:%.10fn,end-start);fflush(stdout);MPI_Finalize();实验结果:实验结果分析:MPI 与 openMP 的主要区别在于:OpenMP:线程级(并行粒度);共享存储;隐式(数据分配方式),可扩展性差,MPI:进程级;分布式存储;显式;可扩展性好。在这里,我们将 MPI 作为一个消息传递机制,在计算机集群之间传递不同进程计算的结果的值,在集群中的单台计算机上使用 openMP 进行多线程编程,即通过 MPI 的分布式有点综合 openMP 的共享内存计算方式来共同结合,从而提高运算效率。由实验结果我们可以得知,如果仅仅是使用 MPI 或者仅仅使用 opnMP的情况下,都只能部分程度上达到并行计算的效果,而两者进行综合的话,就可以尽最大可能的发挥计算机集群的运算威力。实验总结 这次实验,是我们在之前学习过的MPI 的基础之上,通过对 openMP 的学习,进一步了解了关于计算机多核多进程计算的概念。实验过程中,遇到各种各样的问题,老师耐心的予以一一解答。关于 MPI 与 openMP,具体来说,在 OpenMp 并行编程中,主要针对细粒度的循环级并行,主要是在循环中将每次循环分配给各个线程执行,主要应用在一台独立的计算机上;在 MPI 并行编程中,采用粗粒度级别的并行,主要针对分布式计算机进行的,它将任务分配给集群中的所有电脑,来达到并行计算;OpenMp+MPI 混合编程,多台机器间采用 MPI 分布式内存并行且每台机器上只分配一个 MPI 进程,而各台机器又利用 OpenMP 进行多线程共享内存并行。感觉这些实验能够是我们对于计算机的高性能计算的一些方式有了一个初步的了解,眼下大数据集中爆发的时代,这种高性能计算的人门式教育更加显得有必要。