openMP实验报告目录实验报告 ..............................................错误!未定义书签。OpenMP简介..............................................错误!未定义书签。实验一...................................................错误!未定义书签。实验二...................................................错误!未定义书签。实验三...................................................错误!未定义书签。实验四...................................................错误!未定义书签。实验五...................................................错误!未定义书签。实验六...................................................错误!未定义书签。实验七...................................................错误!未定义书签。实验八...................................................错误!未定义书签。实验总结.................................................错误!未定义书签。在学习了MPI之后,我们又继续学习了有关 的并行运算,通过老师的致讲解,我们对 有了一个初步的了解:简介是一种用于共享内存并行系统的多线程程序设计的库 (CompilerDirective), 特别适合于多核上的并行程序开发设计。它支持的语言包括:语言、、Fortran;不过,用以上这些语言进行程序开发时,并非需要特别关注的地方,因为现如今的大多数编译器已经支持了 OpenM,例如:Compiler,GNUCompiler、IntelCompiler 、VisualStudio 等等。程序员在编程时,只需要在特定的源代码片段的前面加入 专用的#pargmaomp预编译指令,就可以“通知”编译器将该段程序自动进行并行化处理, 并且在必要的时候加入线程同步及通信机制。当编译器选择忽略 #pargmaomp预处理指令时,或者编译器不支持 OpenM时,程序又退化为一般的通用串行程序,此时,代码依然可以正常运作,只是不能利用多线程和多核 来加速程序的执行而已。OpenMOpenM使得程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,它是一个很好的选择。同时,使用也提供了更强的灵活性,可以较容易的适应不同的并行系统配置。线程粒度和负载平衡等是传统多线程程序设计中的难题, 然而在OpenM中OpenMP库从程序员手中接管了部分这两方面的工作, 从而使得程序员可以更加专注于具体的算法本身,而非如何编程使得代码在CPU负载平衡和线程粒度方面做出平衡。但是,作为高层抽象, 并不适合需要复杂的线程间同步和互斥的场合。OpenMP的另一个缺点是不能在非共享内存系统这样的系统上,MPI使用较多。上使用。在实验步骤:通过编写了一些程序,验证了关于 的一些简单的性质实验一代码:#include""#include<cstdio>#include<cstdlib>intmain(intargc,char*argv[]){intid,numb;omp_set_num_threads(3);#pragmaompparallelprivate(id,numb){id=omp_get_thread_num();numb=omp_get_num_threads();printf("Iamthread%doutof%d\n",id,numb);}system("pause");return0;}实验结果:可以看到,因为三个进程同步执行,所以输出顺序是乱序的,就是表示运优先级相同。当把进程数改成 10的时候,得到下面的结果:与上面的到的结论(并行并行运算)相同。实验二代码:#include""#include<cstdio>#include<cstdlib>intmain(intargc,char*argv[]){intid;omp_set_num_threads(2);#pragmaompparallel{printf("whatwillyousee\n");#pragmaompforfor(inti=1;i<=5;++i){printf("i=%dof%d\n",i,omp_get_thread_num());printf("Howmanyanswers\n");}}system("pause");return0;}实验运行结果:可以看到,在设置进程为 2的情况之下,运算(计算规模)被等可能的分配给个进程。实验三代码:#include<iostream>#include<cstdlib>#include<>intmain(){#pragma omp parallel sections实验四代码:#include <cstdlib>#include #include <>int main(){#pragmaompparallel{for (int i=0;i<100;++i){std::cout<<i<< "+" <<std::endl;}#pragmaompbarrierfor (int j=0;j<10;++j){std::cout<<j<< "-" <<std::endl;}}system("pause"return 0;}运行结果:结果分析:在语句#pragmaompbarrier 的作用下,只有当上面所有的进程计算工作全完成之后,才会继续barrier 之后的工作。实验五代码:#include<cstdlib>#include<iostream>#include<cstdlib>#include<>usingnamespacestd;intmain(){intsum=0;cout<<"Before:"<<sum<<endl;#pragmaompparallelforfor(inti=0;i<100;i++){#pragmaompcritical(a){sum+=i;sum+=i*2;}}cout<<"After:"<<sum<<endl;system("pause");return0;}运行结果:结果分析:结果分析:CRITICAL指令指定一块同一时间只能被一条线程执行的代码区域各个线程还是并行执行 for 里面的语句,但当你们执行到里面时,要注意有没有其他线程正在里面执行, 如果有的话,要等其他线程执行完再进去执行。实验六代码:#include <cstdlib>#include #include <cstdlib>#include <>using #define NUM_THREADS2static longnum_steps=100000;int main(){int i,id;doublex,pi,sum=;doublestep= /( double)num_steps;#pragmaompparallel 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*}}pi=sum*step;printf( "pi=%.12f\n" ,system("pause");return 0;}运行结果:结果分析:很简单, 通过并行运算,发挥计算机多核的优势,自然能够较单核计算更快的得出计算结果,但是要注意计算机的核数是有限制的, 不能无限扩大并行计算程。实验七代码:#include <cstdlib>#include #include <cstdlib>#include <>using int i=0,sum1,sum2,sum3,sum;int main(){#pragmaompparallelsectionsnum_threads(3){#pragmaompsectionfor(i=0;i<100;i++)sum1+=i;#pragmaompsectionfor(i=100;i<200;i++)sum2+=i;#pragmaompsectionfor(i=200;i<300;i++)sum3+=i;}sum=sum1+sum2+sum3;printf( "sum=%d\n",system("pause");return 0;}运行结果:结果分析:这里需要将累计求和值得部分和分配给几个变量的原因是: 当多个线程并行执时,有可能多个线程同时对某变量进行了读写操作,从而导致不可预知的结果,因为多线程计算如果只设置一个 sum,每次增加的值可能是不同进程的,从而导致运算结果混乱,但是如果把不同进程的计算结果分别保存, 这样就不会出现算结果错误的问题。实验八将openMP与之前学习过的 MPI实验进行综合,通过计算 PI的运算时间的比得出结论代码:#include<>#include<>#include""staticlong num_steps=100000;#define NUM_THREADS4void main(int argc, char*argv[]){inti_start,i_end,i,myid,numprocs;doublepi,mypi,x,step,sum=;doublestart,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);#pragmaompparallel 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=%f\n" ,pi);end=MPI_Wtime();printf( "Runtimeis:%.10f\n" ,end-start);fflush(stdout);}MPI_Finalize();}实验结果:实验结果分析:MPI
程级(并行粒度);共享存储;隐式(数据分配方式),可扩展性差,MPI:进程级;分布式存储;显式;可扩展性好。在这里,我们将MPI作为一个消息传递机制,在计算机集群之间传递不同进程计算的结果的值,在集群中的单台计算机上使用 进行多线程编程,通过MPI的分布式有点综合 的共享内存计算方式来共同结合,从而提高运算效率。由实验结果我们可以得知,如果仅仅是使用 MPI或者仅仅使用的情况下,都只能部分程度上达到并行计算的效果, 而两者进行综合的话,就可以尽最大可能的发挥计算机集群的运算威力。实验总结这次实验,是我们在之前学习过的 MPI的基础之上,通过对的学习进一步了解了关于计算机多核多进