多核程序设计:OpenMP总结及程序演示_第1页
多核程序设计:OpenMP总结及程序演示_第2页
多核程序设计:OpenMP总结及程序演示_第3页
多核程序设计:OpenMP总结及程序演示_第4页
多核程序设计:OpenMP总结及程序演示_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

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

文档简介

1、1OpenMP总结及程序演示2其他的编译指导语句及子句Single子句:用来指定某块程序由一个线程执行在此线程执行期间,其他线程都处于等待状态,直到single语句块结束处隐含的同步屏障格式:#pragma omp singleclause,clause block3#pragma omp parallel num_threads(4) printf(parallel region before single. thread %dn,omp_get_thread_num(); #pragma omp single printf(single region by thread %d.n,omp_

2、get_thread_num(); printf(parallel region after single. thread %d.n,omp_get_thread_num();4其他的编译指导语句及子句Master子句:用于指定一个程序块在主线程中运行没有隐含的同步屏障,主线程在执行master程序块的时候,其他线程可以继续执行,不必等待。5#pragma omp parallel num_threads(4) printf(parallel region before master. thread %dn,omp_get_thread_num(); #pragma omp master pr

3、intf(“master region by thread %d.n,omp_get_thread_num(); printf(parallel region after master. thread %d.n,omp_get_thread_num();6其他的编译指导语句及子句If子句:有条件并行化格式:if(scalar-expression)举例:#pragma omp parallel if(n10) printf(“if clause, ThreadId=%dn”, omp_get_thread_num(); 如果n10,则大括号内代码并行执行;如果n=10,则大括号内代码串行执行7

4、其他的编译指导语句及子句Schedule子句:格式:schedule(type,size)type参数:dynamic/guided/runtime/staticsize参数:表示循环迭代次数,必须为整数。如果type参数为dynamic/guided/static,则size为可选参数如果type参数为runtime,则不需要使用size参数。8其他的编译指导语句及子句Schedule子句:静态调度(static):parallel for语句不带schedule子句,默认为静态调度方式。动态调度(dynamic):没有size参数:将迭代逐个分配到各个线程;使用size参数:每次分配给线程

5、的迭代次数为size次。启发式自调度(guided):开始时每个线程会分配到较大的迭代块,之后分配到的迭代块会递减。迭代块的大小按指数级下降到指定的size大小。如果没有size参数,默认1。96.1 OpenMP编程简介面向共享内存以及分布式共享内存的多处理器多线程并行编程语言。一种编译指导语句,能够显式指导多线程、共享内存并行的应用程序编程接口(API)具有良好的可移植性,支持多种编程语言,如:Fortran77,Fortran90,Fortran95,C/C+支持多种平台大多数的类UNIX系统以及Windows NT系统(Windows 2000,Windows XP,Windows V

6、ista等)。106.1.1 体系结构共享内存多处理器内存是共享的,处理器在访问内存的时候使用的是相同的内存编址空间,某一个处理器写入内存的数据会立刻被其它处理器访问到。分布式共享内存也属于共享内存多处理器结构,将多机的内存资源通过虚拟化的方式形成一个统一的内存空间提供给多机上的处理器使用116.1.2 OpenMP编程基础OpenMP的编程模型以线程为基础,通过编译指导语句来显式地指导并行化,为编程人员提供对并行化的完整控制。OpenMP多线程编程的基础知识OpenMP程序的执行模型OpenMP程序中涉及的编译指导语句和库函数OpenMP程序的执行环境6.1.2 OpenMP编程基础Open

7、MP程序采用Fork-Join的执行模式 Master ThreadParalllRegionNestedParallelRegion13OpenMP的功能由两种形式提供编译指导语句运行时库函数通过环境变量的方式灵活控制程序的运行,例如:通过OMP_NUM_THREADS值来控制运行线程的数目。14编译指导语句在编译器编译程序的时候,会识别特定的注释这些注释就包含着OpenMP程序的一些语义OpenMP的所有编译指导语句以#pragma omp 开始,后面跟具体的功能指令,形式:#pragma omp clause , clause其中directive部分就包含了具体的编译指导语句,包括pa

8、rallel, for, parallel for, section, sections, single, master, critical, flush, ordered和atomic。编译指导语句完成任务分配和同步等功能后面的可选子句clause给出了相应的编译指导语句的参数,子句 可以影响到编译指导语句的具体行为。每一个编译指导语句都有一系列适合它的子句有5个编译指导语句不能跟相应的子句: master, critical, flush, ordered, atomic在无法识别OpenMP语义的普通编译器中,这些注释被忽略OpenMP程序能够同时被普通编译器和支持OpenMP的编译器处

9、理用户可以用同一份代码来编写串行或并行程序方便把串行程序改编为并行程序16运行时库函数OpenMP运行时函数库原本用以设置和获取执行环境相关的信息,它们当中也包含一系列用以同步的APIOpenMP运行时函数库的使用类似于相应编程语言内部的函数调用,在没有库支持的编译器上无法正确识别OpenMP程序。这是库函数和编译指导语句不同的地方。使用运行时库函数所包含的函数,必须在相应的源文件中包含OpenMP头文件omp.h 运行函数库在不同的平台上由不同格式提供支持。Windows平台通过动态链接库提供UNIX平台同时提供动态链接库和静态链接库。17OpenMP程序实例1#include “stdaf

10、x.h”#include “omp.h”int _tmain(int argc, _TCHAR* argv) printf(“Hello from serial.n”); printf(“Thread number = %dn”,omp_get_thread_num(); /串行 #pragma omp parallel /开始并行执行 printf(“Hello from parallel. Thread number=%dn”,omp_get_thread_num();printf(“Hello from serial again.n”);return 0;18OpenMP应用程序构成结合

11、了两种并行编程的方式编译指导语句,在编译过程并行化代码,是OpenMP组成中最重要的部分,也是编写OpenMP程序的关键运行时库函数,在运行时对并行环境支持OpenMP应用程序的组成部分 环境变量是动态函数库中用来控制函数运行的参数19使用Visual Studio 2005编写OpenMP程序当前的Visual Studio .Net 2005完全支持OpenMP 2.0标准,通过编译器选项 /openmp来支持OpenMP程序的编译和链接20在Microsoft Visual Studio .Net 2005环境下面编写OpenMP程序的必要步骤1)生成Console项目;2)配置项目,使

12、之支持OpenMP;3)编写代码,加入#include “omp.h”;4)编写源程序;5)配置环境变量OMP_NUM_THREADS,确定线程数目;6)执行程序。OMP_NUM_THREADS=4OMP_NUM_THREADS=223设置环境OMP_NUM_THREADS的值24使用Visual Studio 2005编写OpenMP程序OpenMP程序使用到的环境变量OMP_NUM_THREADS设置为4默认的情况下OMP_NUM_THREADS=系统中逻辑CPU的数目在双核的系统中OMP_NUM_THREADS=2双核超线程的逻辑CPU的数目为4,256.2 OpenMP编程技术循环并行

13、化编译指导语句的格式#pragma omp parallel for clauseclausefor( index = first ; test_expression ; increment_expr)body of the loop;1 循环并行化:使用OpenMP并行程序的重要部分26循环并行化语句工作原理将for循环中的工作分配到一个线程组中,线程组中的每一个线程将完成循环中的一部分内容;for循环语句要紧跟在parallel for的编译指导语句后面,编译指导语句的功能区域一直延伸到for循环语句的结束;编译指导语句后面的字句(clause)用来控制编译指导语句的具体行为。27循环并行

14、化语句的限制循环并行化语句的限制并行化的语句必须是for循环语句具有规范的格式能够推测出循环的次数循环并行化的语句必须具有如下的形式:for (index = start ; index end ; increment_expr)index必须是一个整数小于号()也可以被其它的比较操作符替代start和end可以是任意的数值表达式,但是在循环的过程中其值不能改变,以保证能够在循环之前就计算出循环的次数。increment_expr形式如下,其中incr是一个在循环过程中不变的数值表达式28简单循环并行化 将两个向量相加,并将计算的结果保存到第三个向量中,向量的维数为n for(int i=0;

15、 in; i+) zi = xi+yi;各个分量之间没有数据相关性循环计算的过程也没有循环依赖性 程序进行循环并行化: #pragma omp parallel for for(int i=0; in; i+) zi = xi+yi;数据相关的概念实例: x0 = 0; y0 = 1; #pragma omp parallel for private(k) for (k = 1; k 100; k+) xk = yk-1 + 1; /S1 yk = xk-1 + 2; /S2 程序段2程序段2运行结果32循环嵌套在一个循环体内经常会包含另外一个循环体,循环产生了嵌套循环并行化编译指导语句可以加

16、在任意一个循环之前对应的最近的循环语句被并行化,其它部分保持不变 int i;int j #pragma omp parallel for private(j) for(i=0;i2;i+) for(j=6;j10;j+) printf(“i=%d j=%dn”,i,j);33循环嵌套比较(程序段3、4)int i;int j#pragma omp parallel for private(j)for(i=0; i2; i+) for(j=6; j10; j+) printf(“ i=%d j=%dn”, i, j);执行结果: i=0 j=6 i=1 j=6 i=0 j=7 i=1 j=7

17、i=0 j=8 i=1 j=8 i=1 j=9 i=0 j=9int i;int j;for(i=0; i2; i+)#pragma omp parallel forfor(j=6; j10; j+) printf(i=%d j=%d n, i, j);执行结果: i=0 j=6 i=0 j=8 i=0 j=9 i=0 j=7 i=1 j=6 i=1 j=8 i=1 j=7 i=1 j=934程序段3、435去掉private子句36控制数据的共享属性 OpenMP程序在同一个共享内存空间上执行可以任意使用这个共享内存空间上的变量进行线程间的数据传递内存分布结构如图每一个线程的栈空间都是私有的

18、全局变量以及程序代码都是全局共享动态分配的堆空间也是共享的通过threadprivate指出的数据结构在每一个线程中都会有一个副本 shared定义变量作用域是共享的private私有的 线程1栈线程2栈堆程序代码程序数据37int gval=8;void funcb(int * x, int *y, int z)static int sv;int u;u=(*y)*gval;*x=u+z;void funca(int * a, int n)int i;int cc=9;#pragma omp parallel forfor(i=0;in;i+)int temp=cc;funcb(&ai,&t

19、emp,i);函数funca调用了funcb,并且在函数funca中使用了OpenMP进行并行化全局变gval是共享的在funca函数的内部,变量i由于是循环控制变量,因此是线程私有的cc在并行化语句外声明,是共享的temp在循环并行化语句内部的自动变量,是线程私有的输入的指针变量a以及n是共享的,都在循环并行化语句之外声明在函数 funcb内部,静态变量sv是共享的,在程序内存空间中只有一份,因此,在这种使用方式下会引起数据冲突变量u是自动变量,由于被并行线程调用,是线程私有的参数x的本身是私有的指针变量,但是*x指向的内存空间是共享的,其实际参数即函数funca中的a数组参数y的本身是私有

20、的指针变量,指向的*y也是私有的,其实际内存空间即私有的temp占用的空间数值参数z是线程私有的。 私有变量的初始化和终结操作循环并行化开始时访问到私有变量在主线程中的同名变量的值,也有可能需要将循环并行化最后一次循环的变量结果返回给主线程中的同名的变量。OpenMP 编译指导语句使用firstprivate和 lastprivate对这两种需求进行支持,使得循环并行开始执行的时候私有变量通过主线程中的变量初始化,同时循环并行结束的时候,将最后一次循环的相应变量赋值给主线程的变量。程序实例: 39私有变量的初始化和终结操作 firstprivate和lastprivate ( 程序段7)int

21、 val=8;#pragma omp parallel for firstprivate(val) lastprivate(val)for(int i=0;i2;i+)printf(i=%d val=%dn,i,val);if(i=1)val=10000;printf(i=%d val=%dn,i,val);printf(val=%dn,val);40程序段7变化 41int val=8;#pragma ompfor(int i=0;i5;i+) printf(i,val,thread); if(i=2) val=10000; if(i=3) val=11111; printf(i,val,t

22、hread);i=0,vali=1,vali=2,val并行i=3,vali=4,valval ? ? ?私有变量需要初始化任务划分方式val环境变量42去掉lastprivate 正常运行结果43去掉firstprivate,lastprivate44使用private子句456.2.2 并行区域编程循环并行化实际上是并行区域编程的一个特例,本节介绍非循环的并行区域编程并行区域简单说就是通过循环并行化编译指导语句使得一段代码能够在多个线程内部同时执行。并行区域编译指导语句的格式 #pragma omp parallel clauseclauseblockblock是需要在多个线程中执行的代码

23、块,每一个线程在遇到并行区域的编译指导语句时,都会同时执行跟随其后的程序代码块。在该语句后面可以跟随一些子句,包括private, shared, default, reduction, if ,copyin6.2.2 并行区域编程parallel编译指导语句的执行过程(程序段9、10)#pragma omp parallelfor(int i=0;i5;i+) printf(hello world i=%dn,i);#pragma omp parallel forfor(int i=0;i5;i+) printf(hello world i=%dn,i);6.2.2 并行区域编程程序段9的执

24、行结果hello world i=0hello world i=0hello world i=1hello world i=1hello world i=2hello world i=2hello world i=3hello world i=3hello world i=4hello world i=4程序段10的执行结果hello world i=0hello world i=3hello world i=1hello world i=4hello world i=26.2.2 并行区域编程并行区域与循环并行化的区别并行区域采用复制的执行方式,将代码在所有的线程内部都执行一次循环并行化采用

25、工作分配的执行方式,将循环所需要所有工作量按照一定的方式分配到各个执行线程中,所有线程执行工作的总和是原先串行执行所完成的工作量。并行区域parallel语句的作用:当程序遇到parallel编译指导语句时,就会生成相应数目(根据环境变量)的线程,且组成一个线程组,并将代码重复地在各个线程内部执行。Parallel的末尾隐含一个同步障碍,所有线程完成各自的任务后将在这个同步障碍汇合。此时,此线程组的主线程(master)继续执行,而相应的子线程(slave)则停止执行。496.2.2 并行区域编程线程私有数据与threadprivate子句(程序段11)使用threadprivate子句用来标

26、明某一个变量是线程私有数据,在程序运行过程中,不能被其它线程访问。int counter=0; /using threadprivate#pragma omp threadprivate(counter)void inc_counter()counter+; int _tmain(int argc, TCHAR * argv)#pragma omp parallel for(int i=0;i10000;i+)inc_counter();printf(counter=%dn,counter); 506.2.2 并行区域编程线程私有数据与copyin子句(程序段12)使用copyin子句对线程私

27、有的全局变量进行初始化。int global=0;#pragma omp threadprivate(global)int _tmain(int argc, TCHAR * argv)global=1000;#pragma omp parallel copyin(global) printf(global=%dn,global); global=omp_get_thread_num(); printf(global=%dn,global);printf(parallel againn);#pragma omp parallelprintf(global=%dn,global); 51程序段12

28、52程序段12(变化)运行结果正常运行结果 去掉threadprivate, copyin子句53程序段12(变化)运行结果正常运行结果 只去掉copyin子句54程序段12(变化)运行结果使用private子句 使用firstprivate子句lastprivate不能使用(仅对for,sections)55并行区域之间的工作共享工作队列工作队列的基本工作过程即维持一个工作的队列,线程在并行执行的时候,不断从这个队列中取出相应的工作完成,直到队列为空为止。根据线程号分配任务由于每一个线程在执行的过程中的线程标识号是不同的,可以根据这个线程标识号来分配不同的任务编译指导语句实现方法直接使用编译

29、指导语句for将任务分配到各个线程用sections编译指导语句以及section子句自然地将不同的工作任务编写成不同的代码片段并行执行并行区域之间的工作共享程序13int next_task=0; int get_next_task() int task; #pragma omp criticalif(next_task8) task=next_task; next_task+; else task=-1; return task; void task_queue() int my_task; #pragma omp parallel private(my_task) my_task=get

30、_next_task(); while(my_task!=-1) get_task_done(my_task); my_task=get_next_task(); 并行区域之间的工作共享根据线程号分配任务:由于每一个线程在执行的过程中的线程标识号是不同的,可以根据这个线程标识号来分配不同的任务。#pragma omp parallel private(myid) nthreads=omp_get_num_threads(); myid=omp_get_thread_num(); get_my_work_done(myid,nthreads); 58并行区域之间的工作共享使用循环语句分配任务(程

31、序段15)#pragma omp parallel printf(outside loop thread=%dn, omp_get_thread_num(); #pragma omp for for(int i=0;i4;i+)printf(inside loop i=%d thread=%dn, i, omp_get_thread_num();59程序段15运行结果去掉#pragma omp for60并行区域之间的工作共享工作分区编码(程序段16)#pragma omp parallel sections #pragma omp section printf(section 1 threa

32、d=%dn,omp_get_thread_num(); #pragma omp sectionprintf(section 2 thread=%dn,omp_get_thread_num(); #pragma omp sectionprintf(sectino 3 thread=%dn,omp_get_thread_num();并行区域之间的工作共享执行结果: section 1 thread=0 section 2 thread=1 section 3 thread=0各个线程自动从各个分区中获得任务执行,在执行完一个分区的时候如果分区组里还有未完成的工作,则继续取得任务完成626.2.3

33、OpenMP线程同步OpenMP支持两种不同类型的线程同步机制互斥锁:用来保护一块共享的存储空间,使得每次访问这块空间的线程最多只有一个,保证了数据的完整性事件通知机制:保证多个线程之间的执行顺序数据竞争 int i; int max_num=-1; #pragma omp parallel for for(i=0; imax_num) max_num=ari;63OpenMP线程同步互斥锁机制互斥锁机制在OpenMP中,提供了三种不同的互斥锁机制用来对一块内存进行保护,它们分别是: (1) 临界区(critical) (2) 原子操作(atomic) (3) 库函数来提供同步操作64Open

34、MP线程同步临界区在程序需要访问可能产生竞争的内存数据的时候,都需要插入相应的临界区代码。临界区编译指导语句的格式如下所示: #pragma omp critical (name) block65OpenMP线程同步临界区int i; int max_num_x=max_num_y=-1;#pragma omp parallel forfor(i=0;imax_num_x) max_num_x=arxi; #pragma omp critical (max_ary) if(aryimax_num_y) max_num_y=aryi; 66OpenMP线程同步原子操作只能作用在语言内建的基本数据

35、结构(程序段18)。#pragma omp atomic 或者 #pragma omp atomicx =expr x+/or x-, -x, +x int counter=0; #pragma omp parallel for(int i=0;i10000;i+) #pragma omp atomic /atomic operation counter+; printf(counter = %dn,counter);67OpenMP运行时库函数的互斥锁支持去掉#pragma omp atomicOMP_NUM_THREADS=468OpenMP运行时库函数的互斥锁支持OpenMP通过一系列的

36、库函数支持更加细致的互斥锁操作编译指导语句进行的互斥锁支持只能放置在一段代码之前,作用在这段代码之上。程序员必须自己保证在调用相应锁操作之后释放相应的锁,否则就会造成多线程程序的死锁。69OpenMP运行时库函数的互斥锁支持omp_lock_t lock; /对应程序实例3int counter=0;void inc_counter() printf(thread id=%dn,omp_get_thread_num(); for(int i=0;i100000;i+) omp_set_nest_lock(&lock); counter+; omp_unset_nest_lock(&lock);

37、 70事件同步机制隐含的同步屏障 在每一个并行区域中都会有一个隐含的的同步屏障,线程组执行完本区域代码,则需要进行同步。 一个同步屏障要求所有的线程都执行到此屏障,容纳后才能够继续执行下面的代码。 #pragma omp for #pragma omp sections71隐含的同步屏障程序实例(程序段20) #pragma omp parallel #pragma omp for nowait for(int i=0;i9;+i) xi=(yi+zi)/2; printf(i=%d thread=%dn,i,omp_get_thread_num(); printf(finishedn); 7

38、2程序20运行结果没有nowait子句加上nowait子句73事件同步机制明确的同步屏障 有些情况,隐含的同步屏障不能提供有效的同步措施,因此需要明确的同步屏障语句。 #pragma omp parallel initialization ( ) ; #pragma omp barrier; process ( ) ; 74事件同步机制循环并行化中的顺序语句 在某些情况下,对于循环并行化中的某些处理需要规定执行的顺序。例如:在一次循环的过程之中,一大部分的工作是可以并行执行的,而其余的工作需要等到前面的工作全部完成后才能执行。 在循环并行化的过程中可以使用ordered子句使顺序执行的语句能够在前面的循环都执行完毕之后再执行。 #pragma omp ordered #pragma omp parallel for ordered schedule(dynamic)75程序实例47

温馨提示

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

评论

0/150

提交评论