教案-并行程序设计ch7openmp编程指南_第1页
教案-并行程序设计ch7openmp编程指南_第2页
教案-并行程序设计ch7openmp编程指南_第3页
教案-并行程序设计ch7openmp编程指南_第4页
教案-并行程序设计ch7openmp编程指南_第5页
已阅读5页,还剩54页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

并行算法实践上篇并行程序设计导论国家高性能计算中心(合肥)22023/1/23并行算法实践

上篇并行程序设计导论单元I并行程序设计基础单元II并行程序编程指南单元III并行程序开发方法国家高性能计算中心(合肥)32023/1/23单元II并行程序编程指南第四章MPI编程指南第五章PVM编程指南第六章HPF编程指南第七章OpenMP编程指南国家高性能计算中心(合肥)42023/1/23第七章OpenMP编程指南7.1OpenMP概述7.2OpenMP编程风络7.3OpenMP编程简介7.4运行库例程与环境变量7.5OpenMP计算实例国家高性能计算中心(合肥)52023/1/23OpenMP概述OpenMP应用编程接口API是在共享存储体系结构上的一个编程模型包含编译制导(CompilerDirective)、运行库例程(RuntimeLibrary)和环境变量(EnvironmentVariables)支持增量并行化(IncrementalParallelization)国家高性能计算中心(合肥)62023/1/23

OpenMP体系结构国家高性能计算中心(合肥)72023/1/23什么是OpenMP什么是OpenMP应用编程接口API(ApplicationProgrammingInterface)由三个基本API部分(编译指令、运行部分和环境变量)构成是C/C++和Fortan等的应用编程接口已经被大多数计算机硬件和软件厂家所标准化OpenMP不包含的性质不是建立在分布式存储系统上的不是在所有的环境下都是一样的不是能保证让多数共享存储器均能有效的利用国家高性能计算中心(合肥)82023/1/23OpenMP的历史1994年,第一个ANSIX3H5草案提出,被否决1997年,OpenMP标准规范代替原先被否决的ANSIX3H5,被人们认可1997年10月公布了与Fortran语言捆绑的第一个标准规范1998年11月9日公布了支持C和C++的标准规范目前Fortran77、Fortran90、C、C++语言的实现规范已经完成国家高性能计算中心(合肥)92023/1/23OpenMP的目标标准性简洁实用使用方便可移植性国家高性能计算中心(合肥)102023/1/23OpenMP并行编程模型基于线程的并行编程模型(ProgrammingModel)OpenMP使用Fork-Join并行执行模型国家高性能计算中心(合肥)112023/1/23OpenMP程序结构基于Fortran语言的OpenMP程序的结构

PROGRAMHELLO

INTEGERVAR1,VAR2,VAR3

!Serialcode

!Beginningofparallelsection.Forkateamofthreads.

!Specifyvariablescoping

!$OMPPARALLELPRIVATE(VAR1,VAR2)SHARED(VAR3)

!Parallelsectionexecutedbyallthreads

!Allthreadsjoinmasterthreadanddisband

!$OMPENDPARALLEL

!Resumeserialcode

END

国家高性能计算中心(合肥)122023/1/23OpenMP程序结构基于c/c++语言的OpenMP程序的结构

#include<omp.h> main(){ intvar1,var2,var3;

/*Serialcode*/ … /*Beginningofparallelsection.Forkateamofthreads*/ /*Specifyvariablescoping*/ #pragmaompparallelprivate(var1,var2)shared(var3) { /*Parallelsectionexecutedbyallthreads*/ … /*Allthreadsjoinmasterthreadanddisband*/ } /*Resumeserialcode*/ … }国家高性能计算中心(合肥)132023/1/23一个简单的OpenMP程序实例基于C/C++语言的OpenMP程序结构的一个具体实现

#include"omp.h"intmain(intargc,char*argv[]){intnthreads,tid;intnprocs;charbuf[32];/*Forkateamofthreads*/#pragmaompparallelprivate(nthreads,tid){/*Obtainandprintthreadid*/tid=omp_get_thread_num();printf("HelloWorldfromOMPthread%d\n",tid);/*Onlymasterthreaddoesthis*/if(tid==0){nthreads=omp_get_num_threads();printf("Numberofthreads%d\n",nthreads);}}return0;}国家高性能计算中心(合肥)142023/1/23一个简单的OpenMP程序实例运行结果(setenvOMP_NUM_THREADS8)HelloWorldfromOMPthread0Numberofthreads8HelloWorldfromOMPthread4HelloWorldfromOMPthread5HelloWorldfromOMPthread6HelloWorldfromOMPthread7HelloWorldfromOMPthread2HelloWorldfromOMPthread1HelloWorldfromOMPthread3国家高性能计算中心(合肥)152023/1/23编译制导语句格式#pragmaompdirective-name[clause,...]newline制导指令前缀。对所有的OpenMP语句都需要这样的前缀。OpenMP制导指令。在制导指令前缀和子句之间必须有一个正确的OpenMP制导指令。子句。在没有其它约束条件下,子句可以无序,也可以任意的选择。这一部分也可以没有。换行符。表明这条制导语句的终止。国家高性能计算中心(合肥)162023/1/23编译制导作用域静态扩展文本代码在一个编译制导语句之后,被封装到一个结构块中孤立语句一个OpenMP的编译制导语句不依赖于其它的语句动态扩展包括静态范围和孤立语句国家高性能计算中心(合肥)172023/1/23作用域动态范围静态范围for语句出现在一个封闭的并行域中孤立语句critical和sections语句出现在封闭的并行域之外

#pragmaompparallel{

…#pragmaompforfor(…){

…sub1();

…}

…sub2();

…}voidsub1(){

…#pragmaompcritical

…}voidsub2(){

…#pragmaompsections

…}国家高性能计算中心(合肥)182023/1/23并行域结构并行域中的代码被所有的线程执行具体格式#pragmaompparallel[clause[[,]clause]…]newlineclause=if(scalar_expression)private(list)shared(list)default(shared|none)firstprivate(list)reduction(operator:list)copyin(list)国家高性能计算中心(合肥)192023/1/23共享任务结构共享任务结构将它所包含的代码划分给线程组的各成员来执行并行for循环并行sections串行执行国家高性能计算中心(合肥)202023/1/23for编译制导语句for语句指定紧随它的循环语句必须由线程组并行执行;语句格式#pragmaompfor[clause[[,]clause]…]newline[clause]=Schedule(type[,chunk])orderedprivate(list)firstprivate(list)lastprivate(list)shared(list)reduction(operator:list)nowait国家高性能计算中心(合肥)212023/1/23for编译制导语句schedule子句描述如何将循环的迭代划分给线程组中的线程如果没有指定chunk大小,迭代会尽可能的平均分配给每个线程type为static,循环被分成大小为chunk的块,静态分配给线程type为dynamic,循环被动态划分为大小为chunk的块,动态分配给线程国家高性能计算中心(合肥)222023/1/23Sections编译制导语句sections编译制导语句指定内部的代码被划分给线程组中的各线程不同的section由不同的线程执行Section语句格式:#pragmaompsections[clause[[,]clause]…]newline{[#pragmaompsectionnewline]…[#pragmaompsectionnewline]…}国家高性能计算中心(合肥)232023/1/23Sections编译制导语句clause=private(list)firstprivate(list)lastprivate(list)reduction(operator:list)nowait在sections语句结束处有一个隐含的路障,使用了nowait子句除外国家高性能计算中心(合肥)242023/1/23Sections编译制导语句#include<omp.h>#defineN1000intmain(){ inti; floata[N],b[N],c[N]; /*Someinitializations*/ for(i=0;i<N;i++) a[i]=b[i]=i*1.0; #pragmaompparallelshared(a,b,c)private(i) { #pragmaompsectionsnowait

{ #pragmaompsection for(i=0;i<N/2;i++) c[i]=a[i]+b[i]; #pragmaompsection for(i=N/2;i<N;i++) c[i]=a[i]+b[i]; }/*endofsections*/ }/*endofparallelsection*/}国家高性能计算中心(合肥)252023/1/23single编译制导语句single编译制导语句指定内部代码只有线程组中的一个线程执行。线程组中没有执行single语句的线程会一直等待代码块的结束,使用nowait子句除外语句格式:#pragmaompsingle[clause[[,]clause]…]newlineclause=private(list)firstprivate(list)nowait国家高性能计算中心(合肥)262023/1/23组合的并行共享任务结构parallelfor编译制导语句parallelsections编译制导语句国家高性能计算中心(合肥)272023/1/23parallelfor编译制导语句Parallelfor编译制导语句表明一个并行域包含一个独立的for语句语句格式#pragmaompparallelfor[clause…]newlineclause=if(scalar_logical_expression)default(shared|none)schedule(type[,chunk])shared(list)private(list)firstprivate(list)lastprivate(list)reduction(operator:list)copyin(list)国家高性能计算中心(合肥)282023/1/23parallelfor编译制导语句#include<omp.h>#defineN1000#defineCHUNKSIZE100intmain(){ inti,chunk; floata[N],b[N],c[N]; /*Someinitializations*/ for(i=0;i<N;i++) a[i]=b[i]=i*1.0; chunk=CHUNKSIZE; #pragmaompparallelfor\ shared(a,b,c,chunk)private(i)\ schedule(static,chunk) for(i=0;i<n;i++) c[i]=a[i]+b[i];}国家高性能计算中心(合肥)292023/1/23parallelsections编译制导语句parallelsections编译制导语句表明一个并行域包含单独的一个sections语句语句格式#pragmaompparallelsections[clause…]newlineclause=default(shared|none)shared(list)private(list)firstprivate(list)lastprivate(list)reduction(operator:list)copyin(list)ordered国家高性能计算中心(合肥)302023/1/23同步结构master制导语句critical制导语句barrier制导语句atomic制导语句flush制导语句ordered制导语句国家高性能计算中心(合肥)312023/1/23master制导语句master制导语句指定代码段只有主线程执行语句格式#pragmaompmasternewline国家高性能计算中心(合肥)322023/1/23critical制导语句critical制导语句表明域中的代码一次只能执行一个线程其他线程被阻塞在临界区语句格式:#pragmaompcritical[name]newline国家高性能计算中心(合肥)332023/1/23critical制导语句#include<omp.h>main(){ intx; x=0; #pragmaompparallelshared(x) { #pragmaompcritical x=x+1; }/*endofparallelsection*/}国家高性能计算中心(合肥)342023/1/23barrier制导语句barrier制导语句用来同步一个线程组中所有的线程先到达的线程在此阻塞,等待其他线程barrier语句最小代码必须是一个结构化的块语句格式#pragmaompbarriernewline国家高性能计算中心(合肥)352023/1/23barrier制导语句错误正确if(x==0)

#pragmaompbarrierif(x==0){#pragmaompbarrier

}barrier正确与错误使用比较国家高性能计算中心(合肥)362023/1/23atomic制导语句atomic制导语句指定特定的存储单元将被原子更新语句格式#pragmaompatomicnewlineatomic使用的格式xbinop=expr

x++

++x

x--

--xx是一个标量expr是一个不含对x引用的标量表达式,且不被重载binop是+,*,-,/,&,^,|,>>,or<<之一,且不被重载国家高性能计算中心(合肥)372023/1/23flush制导语句flush制导语句用以标识一个同步点,用以确保所有的线程看到一致的存储器视图语句格式#pragmaompflush(list)newlineflush将在下面几种情形下隐含运行,nowait子句除外barriercritical:进入与退出部分ordered:进入与退出部分parallel:退出部分for:退出部分sections:退出部分single:退出部分国家高性能计算中心(合肥)382023/1/23ordered制导语句ordered制导语句指出其所包含循环的执行任何时候只能有一个线程执行被ordered所限定部分只能出现在for或者parallelfor语句的动态范围中语句格式:#pragmaomporderednewline国家高性能计算中心(合肥)392023/1/23threadprivate编译制导语句threadprivate语句使一个全局文件作用域的变量在并行域内变成每个线程私有每个线程对该变量复制一份私有拷贝语句格式:#pragmaompthreadprivate(list)newline国家高性能计算中心(合肥)402023/1/23threadprivate编译制导语句intalpha[10],beta[10],i;#pragmaompthreadprivate(alpha)intmain(){ /*Firstparallelregion*/ #pragmaompparallelprivate(i,beta) for(i=0;i<10;i++) alpha[i]=beta[i]=i; /*Secondparallelregion*/ #pragmaompparallel printf("alpha[3]=%dandbeta[3]=%d\n",alpha[3],beta[3]);}国家高性能计算中心(合肥)412023/1/23数据域属性子句变量作用域范围数据域属性子句private子句shared子句default子句firstprivate子句lastprivate子句copyin子句reduction子句国家高性能计算中心(合肥)422023/1/23private子句private子句表示它列出的变量对于每个线程是局部的。语句格式private(list)private和threadprivate区别PRIVATETHREADPRIVATE数据类型变量变量位置在域的开始或共享任务单元在块或整个文件区域的例程的定义上持久么否是扩充性只是词法的-除非有个子程序动态的初始化使用FIRSTPRIVATE使用COPYIN国家高性能计算中心(合肥)432023/1/23shared子句shared子句表示它所列出的变量被线程组中所有的线程共享所有线程都能对它进行读写访问语句格式shared(list)国家高性能计算中心(合肥)442023/1/23default子句default子句让用户自行规定在一个并行域的静态范围中所定义的变量的缺省作用范围语句格式default(shared|none)国家高性能计算中心(合肥)452023/1/23firstprivate子句firstprivate子句是private子句的超集对变量做原子初始化语句格式:firstprivate(list)国家高性能计算中心(合肥)462023/1/23lastprivate子句lastprivate子句是private子句的超集将变量从最后的循环迭代或段复制给原始的变量语句格式lastprivate(list)国家高性能计算中心(合肥)472023/1/23copyin子句copyin子句用来为线程组中所有线程的threadprivate变量赋相同的值主线程该变量的值作为初始值语句格式copyin(list)国家高性能计算中心(合肥)482023/1/23reduction子句reduction子句使用指定的操作对其列表中出现的变量进行规约初始时,每个线程都保留一份私有拷贝在结构尾部根据指定的操作对线程中的相应变量进行规约,并更新改变量的全局值语句格式reduction(operator:list)国家高性能计算中心(合肥)492023/1/23reduction子句#include<omp.h>intmain(){ inti,n,chunk; floata[100],b[100],result; /*Someinitializations*/ n=100; chunk=10; result=0.0; for(i=0;i<n;i++) { a[i]=i*1.0; b[i]=i*2.0; } #pragmaompparallelfor

default(shared)private(i)\ schedule(static,chunk)reduction(+:result) for(i=0;i<n;i++) result=result+(a[i]*b[i]); printf("Finalresult=%f\n",result);}国家高性能计算中心(合肥)502023/1/23reduction子句Reduction子句的格式x=xopexprx=expropx(exceptsubtraction)xbinop=exprx++++xx----xx是一个标量expr是一个不含对x引用的标量表达式,且不被重载binop是+,*,-,/,&,^,|之一,且不被重载op是+,*,-,/,&,^,|,&&,or||之一,且不被重载国家高性能计算中心(合肥)512023/1/23子句/编译制导语句总结子句编译制导PARALLELDO/forSECTIONSSINGLEPARALLEL

DO/forPARALLEL

SECTIONSIF√√√PRIVATE√√√√√√SHARED√√√√DEFAULT√√√FIRSTPRIVATE√√√√√√LASTPRIVATE√√√√REDUCTION√√√√√COPYIN√√√SCHEDULE√√ORDERED√√NOWAIT√√√国家高性能计算中心(合肥)522023/1/23语句绑定和嵌套规则语句绑定语句DO/for、SECTIONS、SINGLE、MASTER和BARRIER绑定到动态的封装PARALLEL中,如果没有并行域执行,这些语句是无效的;语句ORDERED指令绑定到动态DO/for封装中;语句ATOMIC使得ATOMIC语句在所有的线程中独立存取,而并不只是当前的线程;语句CRITICAL在所有线程有关CRITICAL指令中独立存取,而不是只对当前的线程;在PARALLEL封装外,一个语句并不绑定到其它的语句中。

国家高性能计算中心(合肥)532023/1/23语句绑定和嵌套规则语句嵌套PARALALL语句动态地嵌套到其它地语句中,从而逻辑地建立了一个新队列,但这个队列若没有嵌套地并行域执行,则只包含当前的线程;DO/for、SECTION和SINGLE语句绑定到同一个PARALLEL中,则它们是不允许互相嵌套的;DO/for、SECTION和SINGLE语句不允许在动态的扩展CRITICAL、ORDERED和MASTER域中;CRITICAL语句不允许互相嵌套;BARRIER语句不允许在动态的扩展DO/for、ORDERED、SECTIONS、SINGLE、MASTER和CRITICAL域中;MASTER语句不允许在动态的扩展DO/for、SECTIONS和SINGLE语句中;ORDERED语句不允许在动态的扩展CRITICAL域中;任何能允许执行到PARALLEL域中的指令,在并行域外执行也是合法的。当执行到用户指定的并行域外时,语句执行只与主线程有关。国家高性能计算中心(合肥)542023/1/23运行库例程与环境变量运行库例程OpenMP标准定义了一个应用编程接口来调用库中的多种函数对于C/C++,在程序开头需要引用文件“omp.h”

环境变量OMP_SCHEDULE:只能用到for,parallelfor中。它的值就是处理器中循环的次数

OMP_NUM_THREADS:定义执行中最大的线程数OMP_DYNAMIC:通过设定变量值TRUE或FALSE,来确定是否动态设定并行域执行的线程数OMP_NESTED:确定是否可以并行嵌套国家高性能计算中心(合肥)552023/1/23OpenMP计算实例C语言写的串行程序/*SerielCode*/staticlongnum_steps=100000;doublestep;voidmain(){ inti; doublex,pi,sum=0.0; step=1.0/(double)num_steps; for(i=1;i<=num_steps;i++){ x=(i-0.5)*step; sum=sum+4.0/(1.0+x*x); } pi=step*sum;}国家高性能计算中心(合肥)562023/1/23OpenMP计算实例使用并行域并行化的程序#include<omp.h>staticlongnum_steps=100000;doublestep;#defineNUM_THREADS2voidmain(){ inti; doublex,pi,sum[NUM_THREADS]; step=1.0/(double)num_steps; omp_set_num_threads(NUM_THREADS) #pragmaompparallel { doublex; intid; id=omp_get_thraead_num(); for(i=id,sum[id]=0.0;i<num_steps;i=i+NUM_THREADS){ x=(i+0.5)*step; sum[id]+=4.0/(1.0+x*x); } } for(i=0,pi=0.0;i<NUM_THREADS;i++)pi+=sum[i]*step;}国家高性能计算中心(合肥)572023/1/23OpenMP计算实例使用共享任务结构并行化的程序#include<omp.h>staticlongnum_st

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论