编译指导语句运行时函数库环境变量课件_第1页
编译指导语句运行时函数库环境变量课件_第2页
编译指导语句运行时函数库环境变量课件_第3页
编译指导语句运行时函数库环境变量课件_第4页
编译指导语句运行时函数库环境变量课件_第5页
已阅读5页,还剩80页未读 继续免费阅读

下载本文档

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

文档简介

第四章OpenMP多线程编程第四章OpenMP多线程编程1主要内容OpenMP编程简介OpenMP多线程应用程序编程技术主要内容OpenMP编程简介21.OpenMP编程简介1.OpenMP编程简介31.1OpenMP多线程编程发展概况OpenMP是一种面向共享内存多线程并行编程技术OpenMP具有良好的可移植性支持多种编程语言FortranC/C++支持多种平台1.1OpenMP多线程编程发展概况OpenMP是一种面4编译指导语句运行时函数库环境变量课件5OpenMP最初是为共享内存的多处理器系统设计的并行编程方法,这与通过消息传递进行并行编程模型有很大的不同。OpenMP最初是为共享内存的多处理器系统设计的并行编程方法6OpenMP的支持环境Intel的C++和Fortran编译器Microsoft的VisualStudio2005gcc4.2以上版本OpenMP的支持环境71.2OpenMP多线程编程基础OpenMP的编程模型以线程为基础,通过编译制导语句来显示地指导并行化OpenMP的执行模型采用Fork-Join的形式,在开始时,只有一个叫做主线程的运行线程存在;在运行过程中,当遇到需要进行并行计算的时候,派生出(Fork)线程来执行并行任务;在并行代码结束执行,派生线程退出或挂起,控制流程回到单独的主线程中(Join)1.2OpenMP多线程编程基础OpenMP的编程模型8Fork-Join模型并行区域Fork-Join模型并行区域9OpenMP的实现编译制导语句(精髓)运行时库函数环境变量编译指导语句运行时函数库环境变量OpenMP的实现编译制导语句(精髓)编译指导语句运行时函数10编译制导语句在编译器编译程序的时候,会识别特定的注释,而这些注释就包含着OpenMP程序的一些语义在一个无法识别OpenMP语意的普通编译器中,这些注释会被当作普通的注释而被忽略在C/C++程序中,OpenMP所有编译制导语句以#pragmaomp开始,后面跟具体功能指令编译制导语句在编译器编译程序的时候,会识别特定的注释,而这11编译制导语句#pragmaompdirective-name[clause,...]newline制导指令前缀。对所有的OpenMP语句都需要这样的前缀。OpenMP制导指令。在制导指令前缀和子句之间必须有一个正确的OpenMP制导指令.子句。在没有其它约束条件下,子句可以无序,也可以任意的选择。这一部分也可以没有。换行符。表明这条制导语句的终止。编译制导语句#pragmaompdirective-na12编译制导语句Directiveparallel,for,parallelfor,section,sections,single,master,critical,flush,ordered,atomic编译制导语句Directive13运行时库函数OpenMP运行时函数库主要用以设置和获取执行环境相关的信息,它们当中也包含一系列用以同步的API运行时函数库“omp.h”omp_get_thread_num()返回当前线程的号码运行时库函数OpenMP运行时函数库主要用以设置和获取执行环14通过编译制导语句,可以将串行的程序逐步地改造成一个并行程序,达到增量更新程序的目的,减少程序编写人员一定的负担.串行程序和并行程序保持在同一个源代码文件当中,减少了维护负担.编译制导语句,优势体现在编译阶段运行时库函数,支持运行时对并行环境的改变和优化通过编译制导语句,可以将串行的程序逐步地改造成一个并行程序,151.3编写OpenMP程序的准备工作当前的VisualStudio.Net2005完全支持OpenMP2.0标准通过新的编译器选项/openmp来支持OpenMP程序的编译和链接1.3编写OpenMP程序的准备工作当前的Visual16建立一个新的项目建立一个新的项目17配置项目属性配置项目属性18设置环境变量设置环境变量19在OpenMP中,主要通过对循环或一段结构化代码定义并行区域的方式来实现多线程并行。在OpenMP中,主要通过对循环或一段结构化代码定义并行区域20#include"omp.h"int_tmain(intargc,_TCHAR*argv[]){ printf("Hellofromserial.\n"); printf("Threadnumber=%d\n",omp_get_thread_num());#pragmaompparallel { printf("Hellofromparallel.Threadnumber=%d\n",omp_get_thread_num()); } printf("Hellofromserialagain.\n"); getchar(); return0;}#include"omp.h"212.OpenMP多线程应用程序编程技术2.OpenMP多线程应用程序编程技术222.1循环并行化循环并行化是使用OpenMP来并行化程序的最重要的部分在C/C++语言中,循环并行化语句的编译制导语句格式如下:#pragmaompparallelfor[clause[clause…]]for(i=first;i<last;i++){ bodyoftheloop;}2.1循环并行化循环并行化是使用OpenMP来并行化程序23另一种格式:#pragmaompparallel[clause[clause…]]{#pragmaompfor[clause[clause…]]for(i=first;i<last;i++){ bodyoftheloop;}}如果并行的线程需要在循环的开始,或结束时作些工作的话,就只能用parallel与for子句分离的版本。Parallel将紧跟的程序块扩展为若干完全等同的并行区域,每个线程拥有完全相同的并行区域;For将循环中工作分配到线程组中,线程组中的每一个线程完成循环中的一部分。子句用来控制编译制导语句的具体行为。另一种格式:24循环并行化语句的限制并行化的语句必须是for循环语句并具有规范格式能够推测出循环的次数for(index=start;index<end;increment_expr)在循环过程中不能使用break语句不能使用goto和return语句从循环中跳出可以使用continue语句循环并行化语句的限制并行化的语句必须是for循环语句并具有25简单循环并行化各个分量之间没有数据相关性循环计算的过程也没有循环依赖型简单循环并行化26循环依赖性循环迭代相关循环依赖性循环迭代相关27循环迭代相关循环迭代相关28循环分块技术创建无循环迭代相关的循环m循环分块技术创建无循环迭代相关的循环m29编译指导语句运行时函数库环境变量课件30循环并行化编译制导语句的子句循环并行化子句可以包含一个或者多个子句来控制循环并行化的实际执行常见子句有:作用域子句(变量是共享的share还是私有的private)控制线程的调度(schedule)子句动态控制是否并行化(if)子句进行同步的子句(ordered)子句控制变量在串行部分与并行部分传递(copyin)子句循环并行化编译制导语句的子句循环并行化子句可以包含一个或者31循环嵌套可以将嵌套循环的任意一个循环体进行并行化循环并行化编译指导语句可以加在任意一个循环之前,则对应的最近的循环语句被并行化,其它部分保持不变循环嵌套可以将嵌套循环的任意一个循环体进行并行化32编译指导语句运行时函数库环境变量课件33编译指导语句运行时函数库环境变量课件34控制数据的共享属性OpenMP程序在同一个共享内存空间上执行可以任意使用这个共享内存空间上的变量进行线程间的数据传递OpenMP还允许线程保留自己的私有变量不能让其它线程访问到控制数据的共享属性OpenMP程序在同一个共享内存空间上执行35分配在栈上的数据都是私有的全局变量及代码是共享的动态分配的堆空间是共享的threadprivate指明某数据结构是私有的全局变量分配在栈上的数据都是私有的36控制数据的共享属性shared用来指示一个变量的作用域是共享的。privare用来指示一个变量的作用域是私有的。firstprivate对私有变量进行初始化,把串行变量值拷贝到私有变量中(线程开始)lastprivate对私有变量最后终结的操作,把私有变量拷贝到同名串行变量中控制数据的共享属性shared用来指示一个变量的作用域是共享37使用作用域子句的一些规则作用域子句中的变量是已经声明的有名变量作用域子句在作用到类或者结构的时候,只能作用到类或者结构的整体,而不能只作用域类或者结构的一个部分一个编译指导语句能够包含多个数据作用域子句作用域子句只能出现在编译制导语句起作用的语句变量部分默认情况下,并行区域中的所有变量是共享的,三种例外:parallelfor循环中,循环变量是私有的并行区域中的局部变量是私有的Private,firstprivate,lastprivate,reduction子句列出的变量是私有的使用作用域子句的一些规则作用域子句中的变量是已经声明的有名38编译指导语句运行时函数库环境变量课件39规约操作的并行化在规约操作中,会反复将一个二元运算符应用在一个变量和另外一个值上,并把结果保存在原变量中在使用规约操作时,只需在变量前指明规约操作的类型以及规约的变量#pragmaompparallelforprivate(arx,ary,n)reduction(+:a,b)for(i=0;i<n;i++){ a=a+arx[i]; b=b+ary[i];}规约操作的并行化在规约操作中,会反复将一个二元运算符应用在40规约操作并行化的限制能够在OpenMP的C/C++语言中出现的规约操作运算符数据类型默认初始值+整数,浮点0*整数,浮点1-整数,浮点0&整数所有位都开启,~0|整数0^整数0&&整数1||整数0规约操作并行化的限制能够在OpenMP的C/C++语言中出现41私有变量的初始化和终结操作循环并行化开始的时候,私有变量具有主线程中的同名变量的值循环并行化后将私有变量返回给主线程中的同名变量firstprivatelastprivate私有变量的初始化和终结操作循环并行化开始的时候,私有变量具有42编译指导语句运行时函数库环境变量课件43数据相关性与并行化操作并不是所有的循环都能够使用#pragmaompparallelfor来进行并行化必须要保证数据两次循环之间不存在数据相关性数据相关性又被称为数据竞争(DataRace)当两个线程对同一个变量进行操作,并且有一个操作为写操作的时候,就说明这两个线程存在数据竞争数据相关性与并行化操作并不是所有的循环都能够使用#prag44编译指导语句运行时函数库环境变量课件452.2并行区域编程循环并行化实际上是并行区域编程的一个特例并行区域简单的说就是通过编译制导语句使得一段代码能够在多个线程内部同时执行并行区域编写的格式如下:

#pragmaompparallel[clause[clause]…] block

2.2并行区域编程循环并行化实际上是并行区域编程的一个特46parallel编译制导语句的执行过程当程序遇到parallel编译制导语句的时候,就会生成相应数目(根据环境变量)的线程组成一个线程组,并将代码重复地在各个线程内部执行parallel的末尾有一个隐含的同步屏障(barrier),所有线程完成所需的重复任务有,在这个同步屏障出会和(join)parallel编译制导语句的执行过程当程序遇到parall47编译指导语句运行时函数库环境变量课件48线程私有数据threadprivate,copyinthreadprivate指明(全局)变量是线程私有数据copyin对线程私有的全局变量进行初始化线程私有数据threadprivate,copyinthre49线程私有数据与threadprivate,copyin子句线程私有数据与threadprivate,copyin子句50编译指导语句运行时函数库环境变量课件51工作队列工作队列的基本工作过程:为维持一个工作的队列,线程在并行执行的时候,不断从这个队列中取出相应的工作完成,直到队列为空为止工作队列工作队列的基本工作过程:52编译指导语句运行时函数库环境变量课件53编译指导语句运行时函数库环境变量课件54根据线程号分配任务每一个线程在执行的过程中的线程标识号是不同的,可以根据这个线程标识号来分配不同的任务#pragmaompparallelprivate(myid){nthreads=omp_get_num_threads();myid=omp_get_thread_num();get_my_work_done(myid,nthreads);}根据线程号分配任务每一个线程在执行的过程中的线程标识号是不同55使用循环语句分配任务使用循环语句分配任务56工作分区编码工作分区编码572.3线程同步OpenMP支持两种不同类型的线程同步机制:互斥锁:可以用来保护一块共享的存储空间,使得每一次访问这块共享内存空间的线程最多一个,保证了数据的完整性事件通知:这种机制保证了多个线程之间的执行顺序2.3线程同步OpenMP支持两种不同类型的线程同步机制58数据竞争数据竞争59互斥锁机制用来对一块内存进行保护OpenMP提供了三种不同的互斥锁机制:临界区(critical)原子操作(atomic)由库函数来提供同步操作(互斥函数)互斥锁机制用来对一块内存进行保护60临界区(critical)临界区通过编译指导语句对产生数据竞争的内存变量进行保护在程序需要访问可能产生竞争的内存数据的时候,都需要插入相应的临界区代码#pragmaompcritical[(name)] block在执行上述的程序块block之前,必须首先要获得临界区的控制权临界区(critical)临界区通过编译指导语句对产生数据61正整数组最大的元素正整数组最大的元素62原子操作现代体系结构的多处理计算机提供了原子更新一个单一内存单元的方法,提供了一种更高效率的互斥锁机制。通过编译制导可以调用上述方法#pragmaompatomic x++原子操作现代体系结构的多处理计算机提供了原子更新一个单一内63编译指导语句运行时函数库环境变量课件64运行时库函数的互斥锁支持函数名称描述voidomp_init_lock(omp_lock_t*) 初始化一个互斥锁voidomp_destroy_lock(omp_lock_t*)结束一个互斥锁的使用并释放内存voidomp_set_lock(omp_lock_t*) 获得一个互斥锁voidomp_unset_lock(omp_lock_t*)释放一个互斥锁intomp_test_lock(omp_lock_t*)试图获得一个互斥锁,并在成功是返回真(true),失败是返回假(false)运行时库函数的互斥锁支持函数名称描述voidomp_ini65编译指导语句运行时函数库环境变量课件66编译指导语句运行时函数库环境变量课件67编译指导语句运行时函数库环境变量课件68事件同步机制锁:维护一块代码或者一块内存的一致性;事件:用来控制代码的执行顺序,使得某一部分代码必须在其它的代码执行完毕之后才能执行。OpenMP中的事件同步主要包括:同步屏障(barrier)定序区段(orderedsections)主线程执行(master)事件同步机制锁:维护一块代码或者一块内存的一致性;69隐含的同步屏障(barrier)在每一个并行区域都会有一个隐含的同步屏障一个同步屏障要求所有的线程执行到此屏障,然后才能够继续执行下面的代码#pragmaompfor,#pragmaompsingle,#pragmaompsections程序块都包含自己的隐含的同步屏障为了避免在循环过程中不必要的同步屏障,可以增加nowait子句到相应的编译指导语句中隐含的同步屏障(barrier)在每一个并行区域都会有一个70编译指导语句运行时函数库环境变量课件71明确的同步屏障语句在有些情况下,隐含的同步屏障并不能提供有效的同步措施程序员可以在需要的地方插入明确的同步屏障语句#pragmaompbarrier在并行区域的执行过程中,所有的执行线程都会在同步屏障语句上进行同步#pragmaompparallel{ initialization(); #pragmaompbarrier process();}明确的同步屏障语句在有些情况下,隐含的同步屏障并不能提供有72编译指导语句运行时函数库环境变量课件73编译指导语句运行时函数库环境变量课件74循环并行化中的顺序语句(ordered)对于循环并行化中的某些处理需要规定执行的顺序典型的情况:在一次循环的过程中一大部分的工作是可以并行执行的,而其余的工作需要等到前面的工作全部完成之后才能够执行在循环并行化的过程中,可以使用ordered子句使得顺序执行的语句直到前面的循环都执行完毕之后再执行循环并行化中的顺序语句(ordered)对于循环并行化中的75编译指导语句运行时函数库环境变量课件76OpenMP任务调度OpenMP中,任务调度主要用于并行的for循环中,当循环中每次迭代的计算量不相等时,如果简单地给各个线程分配相同次数的迭代的话,会造成各个线程计算负载不均衡,这会使得有些线程先执行完,有些后执行完,造成某些CPU核空闲,影响程序性能。OpenMP任务调度OpenMP中,任务调度主要用于并行的f77inti,j;inta[100][100]={0};for(i=0;i<100;i++){for(j=i;j<100;j++){

a[i][j]=i*j;}}如果将最外层循环并行化的话,比如使用4个线程,如果给每个线程平均分配25次循环迭代计算的话,显然i=0和i=99的计算量相差了100倍,那么各个线程间可能出现较大的负载不平衡情况。inti,j;78for循环并行化的任务调度方案schedule子句的使用格式为:schedule(type[,size])type参数表示调度类型,有四种调度类型如下:·static·dynamic·

guided·

runtime(实际上是根据环境变量来选择前三种中的某中类型。)size参数(可选)size参数表示循环迭代次数,size参数必须是整数。for循环并行化的任务调度方案schedule子句的使用格79静态调度(static)

当parallelfor编译制导语句没有带schedule子句时,大部分系统中默认采用static调度方式,这种调度方式非常简单。假设有n次循环迭代,t个线程,那么给每个线程静态分配大约n/t次迭代计算。不使用size参数时,分配给每个线程的是n/t次连续的迭代静态调度(static)当parallelfor编译制导80#pragmaompparallelforschedule(static)

for(i=0;i<10;i++)

{

printf("i=%d,thread_id=%d\n",i,omp_get_thread_num());}i=0,thread_id=0i=1,thread_id=0i=2,thread_id=0i=3,thread_id=0i=4,thread_id=0i=5,thread_id=1i=6,thread_id=1i=7,thread_id=1i=8,thread_id=1i=9,thread_id=1可以看出线程0得到了0~4次连续迭代,线程1得到5~9次连续迭代。#pragmaompparallelforsched81#pragmaompparallelforschedule(static,2)

for(

温馨提示

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

评论

0/150

提交评论