openMP实验总结报告.docx
- 文档编号:5026187
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:15
- 大小:123.89KB
openMP实验总结报告.docx
《openMP实验总结报告.docx》由会员分享,可在线阅读,更多相关《openMP实验总结报告.docx(15页珍藏版)》请在冰豆网上搜索。
openMP实验总结报告
openMP实验报告
在学习了MPI之后,我们又继续学习了有关openMP的并行运算,通过老师的细致讲解,我们对openMP有了一个初步的了解:
OpenMP简介
OpenMP是一种用于共享内存并行系统的多线程程序设计的库(CompilerDirective),特别适合于多核CPU上的并行程序开发设计。
它支持的语言包括:
C语言、C++、Fortran;不过,用以上这些语言进行程序开发时,并非需要特别关注的地方,因为现如今的大多数编译器已经支持了OpenMP,例如:
SunCompiler,GNUCompiler、IntelCompiler、VisualStudio等等。
程序员在编程时,只需要在特定的源代码片段的前面加入OpenMP专用的#pargmaomp预编译指令,就可以“通知”编译器将该段程序自动进行并行化处理,并且在必要的时候加入线程同步及通信机制。
当编译器选择忽略#pargmaomp预处理指令时,或者编译器不支持OpenMP时,程序又退化为一般的通用串行程序,此时,代码依然可以正常运作,只是不能利用多线程和多核CPU来加速程序的执行而已。
OpenMP使得程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。
对基于数据分集的多线程程序设计,它是一个很好的选择。
同时,使用OpenMP也提供了更强的灵活性,可以较容易的适应不同的并行系统配置。
线程粒度和负载平衡等是传统多线程程序设计中的难题,然而,在OpenMP中,OpenMP库从程序员手中接管了部分这两方面的工作,从而使得程序员可以更加专注于具体的算法本身,而非如何编程使得代码在CPU负载平衡和线程粒度方面做出平衡。
但是,作为高层抽象,OpenMP并不适合需要复杂的线程间同步和互斥的场合。
OpenMP的另一个缺点是不能在非共享内存系统(如计算机集群)上使用。
在这样的系统上,MPI使用较多。
实验步骤:
通过编写了一些程序,验证了关于openMP的一些简单的性质。
实验一
代码:
#include"omp.h"
#include
#include
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"omp.h"
#include
#include
intmain(intargc,char*argv[])
{
intid;
omp_set_num_threads
(2);
#pragmaompparallel
{
printf("whatwillyousee?
\n");
#pragmaompfor
for(inti=1;i<=5;++i)
{
printf("i=%dof%d\n",i,omp_get_thread_num());
printf("Howmanyanswers?
\n");
}
}
system("pause");
return0;
}
实验运行结果:
可以看到,在设置进程为2的情况之下,运算(计算规模)被等可能的分配给各个进程。
实验三
代码:
#include
#include
#include
intmain()
{
#pragmaompparallelsections//声明该并行区域分为若干个section,section之间的运行顺序为并行的关系
{
#pragmaompsection
for(inti=0;i<5;++i)
{
std:
:
cout<
:
endl;
}
#pragmaompsection
for(intj=0;j<5;++j)
{
std:
:
cout< : endl; } } system("pause"); return0; } 运行结果: 结果分析: 语句”#pragmaompparallelsections”声明该并行区域分为若干个section,section之间的运行顺序为并行的关系. 实验四 代码: #include #include #include intmain() { #pragmaompparallel { for(inti=0;i<100;++i) { std: : cout< : endl; } #pragmaompbarrier for(intj=0;j<10;++j) { std: : cout< : endl; } } system("pause"); return0; } 运行结果: 结果分析: 在语句#pragmaompbarrier的作用下,只有当上面所有的进程计算工作全部完成之后,才会继续barrier之后的工作。 实验五 代码: #include #include #include #include usingnamespacestd; intmain() { intsum=0; cout<<"Before: "< #pragmaompparallelfor for(inti=0;i<100;i++) { #pragmaompcritical(a) { sum+=i; sum+=i*2; } } cout<<"After: "< system("pause"); return0; } 运行结果: 结果分析: CRITICAL指令指定一块同一时间只能被一条线程执行的代码区域 各个线程还是并行执行for里面的语句,但当你们执行到critical里面时,要注意有没有其他线程正在里面执行,如果有的话,要等其他线程执行完再进去执行。 实验六 代码: #include #include #include #include usingnamespacestd; #defineNUM_THREADS2 staticlongnum_steps=100000; intmain() { inti,id; doublex,pi,sum=0.0; doublestep=1.0/(double)num_steps; omp_set_num_threads(NUM_THREADS); #pragmaompparallelprivate(x,i,id)reduction(+: sum) { id=omp_get_thread_num(); for(i=id+1;i<=num_steps;i=i+NUM_THREADS) { x=(i-0.5)*step; sum+=4.0/(1.0+x*x); } } pi=sum*step; printf("pi=%.12f\n",pi); system("pause"); return0; } 运行结果: 结果分析: 很简单,通过并行运算,发挥计算机多核的优势,自然能够较单核计算更快的得出计算结果,但是要注意计算机的核数是有限制的,不能无限扩大并行计算线程。 实验七 代码: #include #include #include #include usingnamespacestd; inti=0,sum1,sum2,sum3,sum; intmain() { #pragmaompparallelsectionsnum_threads(3) { #pragmaompsection for(i=0;i<100;i++) sum1+=i; #pragmaompsection for(i=100;i<200;i++) sum2+=i; #pragmaompsection for(i=200;i<300;i++) sum3+=i; } sum=sum1+sum2+sum3; printf("sum=%d\n",sum); system("pause"); return0; } 运行结果: 结果分析: 这里需要将累计求和值得部分和分配给几个变量的原因是: 当多个线程并行执行时,有可能多个线程同时对某变量进行了读写操作,从而导致不可预知的结果,因为多线程计算如果只设置一个sum,每次增加的值可能是不同进程的,从而导致运算结果混乱,但是如果把不同进程的计算结果分别保存,这样就不会出现结算结果错误的问题。 实验八 将openMP与之前学习过的MPI实验进行综合,通过计算PI的运算时间的比较得出结论 代码: #include #include #include"mpi.h" staticlongnum_steps=100000; #defineNUM_THREADS4 voidmain(intargc,char*argv[]) { inti_start,i_end,i,myid,numprocs; doublepi,mypi,x,step,sum=0.0; 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=1.0/(double)num_steps; omp_set_num_threads(NUM_THREADS); #pragmaompparallelprivate(x,i)reduction(+: sum) 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); end=MPI_Wtime(); printf("Runtimeis: %.10f\n",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进行多线程共享内存并行。 感觉这些实验能够是我们对于计算机的高性能计算的一些方式有了一个初步的了解,眼下大数据集中爆发的时代,这种高性能计算的人门式教育更加显得有必要。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- openMP 实验 总结报告