2011-03-17于策ChinaResearchLaboratory2011-03-17OpenMP概述编译制导语句运行时库函数环境变量实例ChinaResearchLaboratory2011-03-17OpenMP概述编译制导语句运行时库函数环境变量实例ChinaResearchLaboratory2011-03-17概述OpenMP是一种面向共享内存以及分布式共享内存的多处理器多线程并行编程语言。OpenMP是一种能够被用于显式制导多线程、共享内存并行的应用程序编程接口(API)。OpenMP标准诞生于1997年,目前其结构审议委员会(ArchitectureReviewBoard,ARB)已经制定并发布OpenMP3.0版本。发展历程OpenMPFortran1.1OpenMPFortran1.1OpenMPC/C++1.0OpenMPC/C++1.0OpenMPFortran2.0OpenMPFortran2.0OpenMPC/C++2.0OpenMPC/C++2.01998200019992002OpenMPFortran1.0OpenMPFortran1.01997OpenMPF/C/C++2.5OpenMPF/C/C++2.52005OpenMPF/C/C++3.0OpenMPF/C/C++3.02008ChinaResearchLaboratory2011-03-17编程模型:Fork-JoinFork-Join执行模式在开始执行的时候,只有主线程程存在。主线程在运行过程中,当遇到需要进行并行计算的时候,派生出(Fork)线程来执行并行任务。在并行执行的时候,主线程和派生线程共同工作。在并行代码结束执行后,派生线程退出或者挂起,不再工作,控制流程回到单独的主线程中(Join)。ChinaResearchLaboratory2011-03-17的实现编译制导语句运行时库函数环境变量ChinaResearchLaboratory2011-03-17OpenMP概述编译制导语句运行时库函数环境变量实例ChinaResearchLaboratory2011-03-17编译制导语句(CompilerDirective)并行域共享任务同步数据域–数据共享属性子句–threadprivate子句–数据拷贝子句ChinaResearchLaboratory2011-03-17编译制导语句(CompilerDirective)编译制导语句的含义是在编译器编译程序的时候,会识别特定的注释,而这些特定的注释就包含着OpenMP程序的一些语义。–在C/C++程序中,用#pragmaompparallel来标识一段并行程序块。在一个无法识别OpenMP语义的普通编译器中,这些特定的注释会被当作普通的注释而被忽略。ChinaResearchLaboratory2011-03-17编译制导语句(CompilerDirective)voidmain(){doubleRes[1000];for(inti=0;i1000;i++){do_huge_comp(Res[i]);}}#include“omp.h”voidmain(){doubleRes[1000];#pragmaompparallelforfor(inti=0;i1000;i++){do_huge_comp(Res[i]);}}将循环拆分到多个线程执行将循环拆分到多个线程执行并行代码并行代码串行代码串行代码ChinaResearchLaboratory2011-03-17编译制导语句(CompilerDirective)并行域共享任务同步数据域–threadprivate–数据域属性子句ChinaResearchLaboratory2011-03-17并行域(parallelregion)ChinaResearchLaboratory2011-03-17并行域并行域中的代码被所有的线程执行具体格式–#pragmaompparallel[clause[[,]clause]…]newline–clause=•if(scalar-expression)•private(list)•firstprivate(list)•default(shared|none)•shared(list)•copyin(list)•reduction(operator:list)•num_threads(integer-expression)ChinaResearchLaboratory2011-03-17并行域示例#includeomp.hmain(){intnthreads,tid;/*Forkateamofthreadsgivingthemtheirowncopiesofvariables*/#pragmaompparallelprivate(tid){/*Obtainandprintthreadid*/tid=omp_get_thread_num();printf(HelloWorldfromthread=%d\n,tid);/*Onlymasterthreaddoesthis*/if(tid==0){nthreads=omp_get_num_threads();printf(Numberofthreads=%d\n,nthreads);}}/*Allthreadsjoinmasterthreadandterminate*/}ChinaResearchLaboratory2011-03-17编译制导语句并行域共享任务同步数据域–数据共享属性子句–threadprivate子句–数据拷贝子句ChinaResearchLaboratory2011-03-17共享任务共享任务结构将它所包含的代码划分给线程组的各成员来执行–并行for循环–并行sections–串行执行FORKFORKFORKJOINJOINJOIN主线程主线程线程列主线程主线程线程列主线程主线程线程列SECTIONSSINGLEDO/forloopChinaResearchLaboratory2011-03-17编译制导语句for语句指定紧随它的循环语句必须由线程组并行执行;语句格式–#pragmaompfor[clause[[,]clause]…]newline–[clause]=•Schedule(type[,chunk])•ordered•private(list)•firstprivate(list)•lastprivate(list)•shared(list)•reduction(operator:list)•nowaitChinaResearchLaboratory2011-03-17编译制导语句schedule子句描述如何将循环的迭代划分给线程组中的线程如果没有指定chunk大小,迭代会尽可能的平均分配给每个线程type为static,循环被分成大小为chunk的块,静态分配给线程type为dynamic,循环被动态划分为大小为chunk的块,动态分配给线程ChinaResearchLaboratory2011-03-17示例#includeomp.h#defineCHUNKSIZE100#defineN1000main(){inti,chunk;floata[N],b[N],c[N];/*Someinitializations*/for(i=0;iN;i++)a[i]=b[i]=i*1.0;chunk=CHUNKSIZE;#pragmaompparallelshared(a,b,c,chunk)private(i){#pragmaompforschedule(dynamic,chunk)nowaitfor(i=0;iN;i++)c[i]=a[i]+b[i];}/*endofparallelsection*/}ChinaResearchLaboratory2011-03-17编译制导语句sections编译制导语句指定内部的代码被划分给线程组中的各线程不同的section由不同的线程执行Section语句格式:#pragmaompsections[clause[[,]clause]…]newline{[#pragmaompsectionnewline]…[#pragmaompsectionnewline]…}ChinaResearchLaboratory2011-03-17编译制导语句clause=–private(list)–firstprivate(list)–lastprivate(list)–reduction(operator:list)–nowait在sections语句结束处有一个隐含的路障,使用了nowait子句除外ChinaResearchLaboratory2011-03-17编译制导语句#includeomp.h#defineN1000main(){inti;floata[N],b[N],c[N],d[N];/*Someinitializations*/for(i=0;iN;i++)a[i]=i*1.5;b[i]=i+22.35;#pragmaompparallelshared(a,b,c,d)private(i){#pragmaompsectionsnowait{#pragmaompsectionfor(i=0;iN;i++)c[i]=a[i]+b[i];#pragmaompsectionfor(i=0;iN;i++)d[i]=a[i]*b[i];}/*endofsections*/}/*endofparallelsection*/}ChinaResearchLaboratory2011-03-17