ImageVerifierCode 换一换
格式:PPT , 页数:105 ,大小:526.52KB ,
资源ID:1465582      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.docduoduo.com/d-1465582.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第 四 章openmp编程基础 主讲人: 谢银波.ppt)为本站会员(天天快乐)主动上传,道客多多仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知道客多多(发送邮件至docduoduo@163.com或直接QQ联系客服),我们立即给予删除!

第 四 章openmp编程基础 主讲人: 谢银波.ppt

1、第 四 章OpenMP 编 程 基 础,武汉大学多核架构及编程技术教学课程之,主讲人: 谢银波,OpenMP,提供一种快捷简单的多线程编程方法形成于1997年,是一种应用程序接口对编程人员:无需进行复杂的线程创建、同步、负载平衡和销毁工作。只需要认真考虑哪些循环应该以多线程方式运行。Intel编译器提供对OpenMP的支持。http:/www.openmp.org,OpenMP概述,OpenMP应用编程接口API是在共享存储体系结构上的一个编程模型包含编译制导(Compiler Directive)、运行库例程(Runtime Library)和环境变量(Environment Variabl

2、es) 支持增量并行化(Incremental Parallelization),什么是OpenMP,什么是OpenMP应用编程接口API(Application Programming Interface )由三个基本API部分(编译指令、运行部分和环境变量)构成 是C/C+ 和Fortan等的应用编程接口已经被大多数计算机硬件和软件厂家所标准化OpenMP不包含的性质不是建立在分布式存储系统上的 不是在所有的环境下都是一样的 不是能保证让多数共享存储器均能有效的利用,OpenMP的历史,1994年,第一个ANSI X3H5草案提出,被否决 1997年,OpenMP标准规范代替原先被否决的A

3、NSI X3H5,被人们认可1997年10月公布了与Fortran语言捆绑的第一个标准规范 FORTRAN version 1.0 1998年11月9日公布了支持C和C+的标准规范C/C+ version 1.0 2000年11月推出FORTRAN version 2.0 2002年3月推出C/C+ version 2.0 2005年5月OpenMP2.5将原来的Fortran和C/C+ 标准规范相结合相关的规范可在http:/www.openmp.org/drupal/node/view/8中下载,OpenMP的目标,标准性 简洁实用 使用方便 可移植性,OpenMP并行编程模型,基于线程的

4、并行编程模型(Programming Model) OpenMP使用Fork-Join并行执行模型,编译制导,OpenMP的#pragma语句的格式为 #pragma omp directive_name ,编译制导,作用域静态扩展文本代码在一个编译制导语句之后,被封装到一个结构块中 孤立语句一个OpenMP的编译制导语句不依赖于其它的语句 动态扩展 包括静态范围和孤立语句,作用域,并行域结构,并行域中的代码被所有的线程执行具体格式#pragma omp parallel clause,clausenewlineclause=if(scalar-expression)private(list)

5、firstprivate(list)default(shared | none)shared(list)copyin(list)reduction(operator: list)num_threads(integer-expression),共享任务结构,共享任务结构将它所包含的代码划分给线程组的各成员来执行并行for循环并行sections串行执行,for编译制导语句,for语句指定紧随它的循环语句必须由线程组并行执行;语句格式#pragma omp for clause,clause newlineclause=Schedule(type ,chunk) orderedprivate (l

6、ist)firstprivate (list)lastprivate (list)shared (list)reduction (operator: list)nowait,for编译制导语句,schedule子句描述如何将循环的迭代划分给线程组中的线程如果没有指定chunk大小,迭代会尽可能的平均分配给每个线程type为static,循环被分成大小为 chunk的块,静态分配给线程type为dynamic,循环被动态划分为大小为chunk的块,动态分配给线程,Sections编译制导语句,sections编译制导语句指定内部的代码被划分给线程组中的各线程不同的section由不同的线程执行S

7、ection语句格式:#pragma omp sections clause,clause newline #pragma omp section newline #pragma omp section newline ,Sections编译制导语句,clause=private (list) firstprivate (list)lastprivate (list)reduction (operator: list)nowait 在sections语句结束处有一个隐含的路障,使用了nowait子句除外,Sections编译制导语句,#include #define N 1000int mai

8、n ()int i;float aN, bN, cN;for (i=0; i N; i+) /* Some initializations */ai = bi = i * 1.0;#pragma omp parallel shared(a,b,c) private(i) #pragma omp sections nowait #pragma omp section for (i=0; i N/2; i+) ci = ai + bi; #pragma omp section for (i=N/2; i N; i+) ci = ai + bi; /* end of sections */ /* e

9、nd of parallel section */,single编译制导语句,single编译制导语句指定内部代码只有线程组中的一个线程执行。线程组中没有执行single语句的线程会一直等待代码块的结束,使用nowait子句除外语句格式:#pragma omp single clause,clause newlineclause=private(list)firstprivate(list)nowait,组合的并行共享任务结构,parallel for编译制导语句parallel sections编译制导语句,parallel for编译制导语句,Parallel for编译制导语句表明一个并

10、行域包含一个独立的for语句语句格式#pragma omp parallel for 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),parallel for编译制导语句,#include #define N 1000#define CHUNKSI

11、ZE 100int main () int i, chunk;float aN, bN, cN;for (i=0; i N; i+) /* Some initializations */ai = bi = i * 1.0;chunk = CHUNKSIZE;#pragma omp parallel for shared(a,b,c,chunk) private(i) schedule(static,chunk) for (i=0; i n; i+) ci = ai + bi;,parallel sections编译制导语句,parallel sections编译制导语句表明一个并行域包含单独的

12、一个sections语句语句格式#pragma omp parallel sections clause newlineclause=default (shared | none)shared (list)private (list)firstprivate (list)lastprivate (list)reduction (operator: list)copyin (list)ordered,parallel sections编译制导语句,线程同步 数据竞争问题,串行程序 - 寻找一个正整数数组中最大的元素(假设数组为ar,数组元素的数目为n )int I;int max_num=-1;

13、for(i=0;imax_num)max_num=ari;,并行程序 ?(能否起到预期的并行效果)int I;int max_num=-1;#progma omp parallel forfor(i=0;imax_num)max_num=ari;,产生错误原因:超过两个线程同时访问一个内存区域,并且至少有一个线程的操作时写操作,这就是所谓的数据竞争。,同步方式,master 制导语句critical制导语句barrier制导语句atomic制导语句flush制导语句ordered制导语句运行时库函数,master 制导语句,master制导语句指定代码段只有主线程执行语句格式#pragma o

14、mp master newline,master 制导语句,/ omp_master.cppint main( ) int a5, i; #pragma omp parallel #pragma omp for for (i = 0; i 5; i+) ai = i * i; #pragma omp master for (i = 0; i 5; i+) printf_s(a%d = %dn, i, ai); #pragma omp barrier / Wait. #pragma omp for / Continue with the computation. for (i = 0; i ma

15、x_num_y)max_num_x=arxi; ,barrier制导语句,barrier制导语句用来同步一个线程组中所有的线程先到达的线程在此阻塞,等待其他线程barrier语句最小代码必须是一个结构化的块语句格式#pragma omp barrier newline,barrier制导语句,barrier正确与错误使用比较,barrier制导语句举例,atomic制导语句,atomic制导语句指定特定的存储单元将被原子更新语句格式#pragma omp atomic newline expression-stmtexpression statement使用的格式,Atomic使用举例,#in

16、clude #include #define MAX 10 int main() int count = 0; #pragma omp parallel num_threads(MAX) #pragma omp atomic count+; printf_s(Number of threads: %dn, count); ,Critical和Atomic使用区别,Critical:能够作用在任意的代码块上Atomic:智能作用在语言内建的基本数据结构中。注意:1、能够使用原子语句的前提条件是相应的语句块能够被转化成一条机器指令,使得相应的功能能够一次执行完毕而不被打断。2、当一个数据进行原子操

17、作保护时,不能对数据进行临界区的保护,这是两种完全不同的保护机制。,flush制导语句,flush制导语句用以标识一个同步点,用以确保所有的线程看到一致的存储器视图语句格式#pragma omp flush (list) newline flush将在下面几种情形下隐含运行,nowait子句除外,barriercritical:进入与退出部分ordered:进入与退出部分parallel:退出部分for:退出部分sections:退出部分single:退出部分,ordered制导语句,ordered制导语句指出其所包含循环的执行任何时候只能有一个线程执行; 被ordered所限定部分只能出现在

18、for或者parallel for语句的动态范围中。语句格式:#pragma omp ordered newline,threadprivate编译制导语句,threadprivate语句使一个全局文件作用域的变量在并行域内变成每个线程私有每个线程对该变量复制一份私有拷贝语句格式:#pragma omp threadprivate (list) newline,threadprivate编译制导语句,int alpha10, beta10, i;/eg3#pragma omp threadprivate(alpha) int main () /* First parallel region *

19、/#pragma omp parallel private(i,beta) for (i=0; i 10; i+) alphai = betai = i;/* Second parallel region */#pragma omp parallel printf(alpha3= %d and beta3=%dn,alpha3,beta3);,数据域属性子句,变量作用域范围数据域属性子句private子句shared子句default子句firstprivate子句lastprivate子句copyin子句reduction子句nowait子句,private子句,private子句表示它列出

20、的变量对于每个线程是局部的 。语句格式private(list)private和threadprivate区别,private子句,int counter=0;#progma omp threadprivate(counter)Void inc_counter()counter+;Int _tmain(int argc, THCAR * argv )#progma omp parallelfor(int i=0;i10000;i+)inc_counter();printf(“counter=%dn”,counter);Return 0,如果没有threadprivate,Counter值将不可

21、预知,shared子句,shared子句表示它所列出的变量被线程组中所有的线程共享所有线程都能对它进行读写访问语句格式shared (list),default子句,default子句让用户自行规定在一个并行域的静态范围中所定义的变量的缺省作用范围语句格式default (shared | none),firstprivate子句,firstprivate子句是private子句的超集对变量做原子初始化语句格式: firstprivate (list),lastprivate子句,lastprivate子句是private子句的超集将变量从最后的循环迭代或段复制给原始的变量语句格式lastpr

22、ivate (list),copyin子句,copyin子句用来为线程组中所有线程的threadprivate变量赋相同的值主线程该变量的值作为初始值语句格式copyin(list),reduction子句,reduction子句使用指定的操作对其列表中出现的变量进行规约初始时,每个线程都保留一份私有拷贝在结构尾部根据指定的操作对线程中的相应变量进行规约,并更新该变量的全局值语句格式reduction (operator: list),reduction子句,#include int main () int i, n, chunk;float a100, b100, result;n = 10

23、0; /* Some initializations */chunk = 10;result = 0.0;for (i=0; i n; i+) ai = i * 1.0; bi = i * 2.0; #pragma omp parallel for default(shared) private(i) schedule(static,chunk) reduction(+:result) for (i=0; i n; i+) result = result + (ai * bi);printf(Final result= %fn,result);,reduction子句,Reduction子句的

24、格式,x=x op exprx = expr op x (except subtraction)x binop = exprx+xx-x,x是一个标量expr是一个不含对x引用的标量表达式,且不被重载binop是+,*,-,/,&,|之一,且不被重载op是+,*,-,/,&,|,&,or|之一,且不被重载,Implicit Barriers,Several OpenMP constructs have implicit barriers parallel for single Suppress implicit barriers, when safe, with the nowaitclaus

25、e,Nowait子句,If there are multiple independent loops within a parallel region, you can use the nowait clause to avoid the implied barrier at the end of the for directive,子句/编译制导语句总结,运行时库函数的互斥锁支持,语句绑定和嵌套规则,语句绑定语句DO/for、SECTIONS、SINGLE、MASTER和BARRIER绑定到动态的封装PARALLEL中,如果没有并行域执行,这些语句是无效的;语句ORDERED指令绑定到动态D

26、O/for封装中;语句ATOMIC使得ATOMIC语句在所有的线程中独立存取,而并不只是当前的线程;语句CRITICAL在所有线程有关CRITICAL指令中独立存取,而不是只对当前的线程;在PARALLEL封装外,一个语句并不绑定到其它的语句中。,语句绑定和嵌套规则,语句嵌套PARALALL 语句动态地嵌套到其它地语句中,从而逻辑地建立了一个新队列,但这个队列若没有嵌套地并行域执行,则只包含当前的线程;DO/for、SECTION和SINGLE语句绑定到同一个PARALLEL 中,则它们是不允许互相嵌套的;DO/for、SECTION和SINGLE语句不允许在动态的扩展CRITICAL、ORD

27、ERED和MASTER域中;CRITICAL语句不允许互相嵌套;BARRIER语句不允许在动态的扩展DO/for、ORDERED、SECTIONS、SINGLE、MASTER和CRITICAL域中;MASTER语句不允许在动态的扩展DO/for、SECTIONS和SINGLE语句中;ORDERED语句不允许在动态的扩展CRITICAL域中;任何能允许执行到PARALLEL 域中的指令,在并行域外执行也是合法的。当执行到用户指定的并行域外时,语句执行只与主线程有关。,运行库例程与环境变量,运行库例程OpenMP标准定义了一个应用编程接口来调用库中的多种函数 对于C/C+,在程序开头需要引用文件“

28、omp.h” 环境变量OMP_SCHEDULE:只能用到for,parallel for中。它的值就是处理器中循环的次数 OMP_NUM_THREADS:定义执行中最大的线程数OMP_DYNAMIC:通过设定变量值TRUE或FALSE,来确定是否动态设定并行域执行的线程数OMP_NESTED:确定是否可以并行嵌套,OpenMP计算实例,矩形法则的数值积分方法估算Pi的值,OpenMP计算实例,/* Seriel Code */static long num_steps = 100000; double step; void main () int i; double x, pi, sum =

29、0.0; step = 1.0/(double) num_steps; for (i=0;i num_steps; i+) x = (i+0.5)*step; sum = sum + 4.0/(1.0+x*x); pi = step * sum; ,OpenMP计算实例,使用并行域并行化的程序#include static long num_steps = 100000;double step; #define NUM_THREADS 2 void main () int i; double x, pi, sumNUM_THREADS; step = 1.0/(double) num_step

30、s; omp_set_num_threads(NUM_THREADS); / #pragma omp parallel double x; int id; id = omp_get_thread_num(); for (i=id, sumid=0.0;i num_steps; i=i+NUM_THREADS) x = (i+0.5)*step; sumid += 4.0/(1.0+x*x); for(i=0, pi=0.0;iNUM_THREADS;i+)pi += sumi * step; ,OpenMP计算实例,使用共享任务结构并行化的程序 /2#include static long n

31、um_steps = 100000;double step; #define NUM_THREADS 2 void main () int i; double x, pi, sumNUM_THREADS; step = 1.0/(double) num_steps; omp_set_num_threads(NUM_THREADS) ;/* #pragma omp parallel /* double x; int id; id = omp_get_thread_num(); sumid = 0; /*#pragma omp for/* for (i=0;i num_steps; i+) x =

32、 (i+0.5)*step; sumid += 4.0/(1.0+x*x); for(i=0, pi=0.0;iNUM_THREADS;i+)pi += sumi * step; ,OpenMP计算实例,使用private子句和critical部分并行化的程序 #include static long num_steps = 100000;double step;#define NUM_THREADS 2 void main () int i; double x, sum, pi=0.0; step = 1.0/(double) num_steps; omp_set_num_threads(N

33、UM_THREADS) #pragma omp parallel private (x, sum) id = omp_get_thread_num(); for (i=id,sum=0.0;i num_steps;i=i+NUM_THREADS) x = (i+0.5)*step; sum += 4.0/(1.0+x*x); #pragma omp critical pi += sum ,OpenMP计算实例,使用并行归约得出的并行程序 #include static long num_steps = 100000;double step; #define NUM_THREADS 2 void

34、 main () int i; double x, pi, sum = 0.0; step = 1.0/(double) num_steps; omp_set_num_threads(NUM_THREADS) #pragma omp parallel for reduction(+:sum) private(x) for (i=0;i= loop_invariant_integerfor的循环步长必须是整数加或减操作,加减的数值必须是一个循环不变量。如果比较操作是,=,循环变量的值在每个迭代是必须是增加,反之,必须是减少。循环必须是单入口,单出口。exit()语句除外。,使用OpenMP提高应

35、用程序性能,1 将循环多线程化所面临的挑战2 降低线程开销3 提高程序性能的方法4 OpenMP库函数5 OpenMP环境变量6 编译7 调试8 性能,1、将循环多线程化所面临的挑战,循环迭代相关数据竞争管理共享数据和私有数据循环调度与分块有效地使用规约,循环迭代相关,对语句S1、S2和某一存储单元L:相关的产生:循环迭代相关(loop carried dependence):S1在循环的第一次迭代中访问L,而S2在随后的一次迭代中也访问L。非循环迭代相关(loop-independence dependence) :S1和S2在同一循环迭代捉拿嘎访问L,但S1的执行在S2之前。流相关:S1先

36、写L,S2然后读L。输出相关:两个语句同时写L。反相关:其中一个先读,然后另一个再写。,x0 = 0;y0 = 0;#pragma omp parallel forfor(k=1;K100;K+)xk = yk-1 + 1; /S1yk = xk-1 + 1; /S2,错误代码:存在循环迭代相关,解决办法:采用循环分块技术,x0 = 0;y0 = 0;x49 = 74;y49 = 74;#pragma omp parallel for private(m,k)for(m=0;m2;m+)for(k=m*49+1;Km*50+1;K+)xk = yk-1 + 1; /S1yk = xk-1 +

37、1; /S2,数据竞争,数据竞争可能由输出相关产生解决办法:,#pragma omp parallel for private(x)for (int i=0;i60) x=x%60+1;printf(x %d = %dn,k,x);,管理共享数据和私有数据,避免数据竞争分清共享数据区域与私有数据区域默认:并行区的变量是共享的。三个例外:在parallel for性能中,迅捷索引是私有的;并行区的局部变量是私有的;所有在private、firstprivate、lastprivate、reduction子句中列出的变量是私有的。,#pragma omp parallel forfor (int

38、k=0;k100;k+)x = arrayk;arrayk = do_work(x);,错误代码,#pragma omp parallel for private(x)for (int k=0;k100;k+)x = arrayk;arrayk = do_work(x);,改正:,#pragma omp parallel for for (int k=0;k100;k+)int x;x = arrayk;arrayk = do_work(x);,循环调度与分块,为了更好地实现负载平衡保持核尽可能在大部分时间内保持忙碌状态。将上下文切换、调度开销、同步开销降到最低。四种方案:staticdyna

39、micruntimeguided,四种调度策略的比较,有效地使用规约,OpenMP规约操作符及规约变量的初值,2、降低线程开销,在利用OpenMP后,可以进一步降低开销。来源与对并行结构的了解和对算法的理解。,#pragma omp parallel for for (int k=0;km;k+)fn1(k);fn2(k);#pragma omp parallel for for (int k=0;km;k+)fn3(k);fn4(k);,#pragma omp parallel#pragma omp forfor (int k=0;km;k+)fn1(k);fn2(k);#pragma om

40、p forfor (int k=0;km;k+)fn3(k);fn4(k);,任务分配区,在parallel sections中的创建和合并线程的开销可以消除。,#pragma omp parallel #pragma omp forfor (int k=0;km;k+)fn1(k);fn2(k);#pragma omp sections private(y,z)#pragma omp section y = sectionA(x);fn7(y);#pragma omp section z = sectionB(x);fn8(z);,3、提高程序性能的方法,使用栅障Barrier和nowait

41、单线程和多线程交替执行数据的“复制进”和“复制出”,使用nowait消除parallel、for、sections、single结构最后隐式的栅障,#pragma omp parallel#pragma omp for nowaitfor (int k=0;km;k+)fn1(k);fn2(k);#pragma omp sections private(y,z)#pragma omp section y = sectionA(x);fn7(y);#pragma omp section z = sectionB(x);fn8(z);,4、OpenMP库函数,出来编译指导外,OpenMP提供了一组

42、函数调用和环境变量。编译时必须加上:,#include #ifdef _OPENMPomp_set_num_threads(4);#endif,常用的OpenMP库函数,5、OpenMP环境变量,6、编译,OpenMP的编译开关,7、调试,通过启用和禁止程序中的OpenMP指导,使用二分搜索法找出引发故障等待必须结构。关闭/Qopenmp编译开关,使用/Qopenmp_stub开关来编译引发错误的子程序;然后检查代码中的故障是否发生在串行执行的过程中,如果是,就进行串行调试。使用/Qopenmp开放编译引发错误的子程序,并设置环境变量OMP_NUM_THREADS=1,然后检查故障是否发生在串行执行的过程中,如果是,就进行多线程代码的单线程调试。使用/Qopenmp以及/Od,/O1,/O2,/O3或/Qipo中的某一个编译开关编译代码,在最低优化等级上找出故障场景。检查错误的代码段,定位问题。如果不能定位,使用/Qtcheck开关编译代码进行OpenMP代码插桩,并在Intel线程检查器中运行插桩的代码。,

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报