OpenMP简介
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Openmp与mpi比较
MPI是多主机联网协作进行并行计算,它是使用进程间通信的方式协调并算 的一个标准,也可用于单主机多核/多CPU的并行计行计算。
1.8
mpi 一 二 四 八 1.399423 1.358985 0.855627 0.728092
openmp 1.550089 1.181123 0.690652 0.556877
两个线程
四个线程
六个线程
八个线程
3 2.5 2 1.5 1 加速比 效率
1.513399 1.59529 1.541578
1.550089 1 1
1.189298 1.192011 1.16206
1.181123
0.707843 0.684093 0.68002
0.690652
0.540235 0.544989 0.543208
0.542811
0.587908 0.587908 0.587908
0.556987
0.5 0 2 4 6 8
1.312385
0.656193
2.244385
0.561096
2.855671
0.475945
2.784354
0.347942
并行效率
Openmp多线程应用程序性能分析
影响性能的主要因素: 根据Amdahl定律,我们应当努力提高并行化代码在应用程序中的比率,这是 通用的提高效率的方法。 1、OpenMP本身的开销:并行化需要一定的程序库的支持,库中代码的运 行必然会带来一定的开销。 2、负载均衡:各个线程之间的负载不均衡,就有可能造成某些线程在执行 过程中无事可干,经常处于空闲状态;而另外一些线程则负担沉重,需要很 长时间才能够完成任务。在OpenMP的运行时以及环境变量中对负载均衡的 需求有一定的支持,例如可以划分执行的粒度,并通过动态调度的方法消除 一定的负载均衡问题。 3、线程同步带来的开销:多个线程在进行同步的时候必然带来一定的同步开 销。考虑同步的必要性,消除不必要的同步,或者调整同步的顺序,就有可能 带来性能上的提升。
二、Openmp的常用指令的用法
在编译器编译程序的时候,会识别特定的注释,这些注释就包含 着OpenMP程序的一些语义
#pragma omp 指令 [子句[子句]…]
前面提到的parallel for就是一条指令,有些书中也将OpenMP的“指令” 叫做“编译指导语句”,后面的子句是可选的。
例如: #pragma omp parallel num_threads(n) parallel 就是指令, num_threads是子句
OpenMP的功能
由两种形式提供: 1)编译指导语句 在编译器编译程序的时候,会识别特定的注解,这些注解包含 openmp的一些语义。 在无法识别OpenMP语义的普通编译器中,这些注释被忽略 2)运行时库函数 OpenMP运行时函数库原本用以设置和获取执行环境相关的信息, 它们当中也包含一系列用以同步的API。 OpenMP头文件omp.h
OpenMP提供了schedule子句来实现任务的调度。
schedule子句
schedule(type, size), 参数type是指调度的类型,可以取值为static,dynamic,guided三种值。 参数size表示每次调度的迭代数量,必须是整数。该参数是可选的。 2. 3. 动态调度 启发式调度 dynamic guided 1. 静态调度 static 采用启发式调度方法进行调度,每次分配给线程迭代次数不同,开始比较大, 动态调度依赖于运行时的状态动态确定线程所执行的迭代,也就是线程执行完 static在编译的时候就已经确定了,那些循环由哪些线程执行。 以后逐渐减小。 已经分配的任务后,会去领取还有的任务。由于线程启动和执行完的时间不确 当不使用size 时,将给每个线程分配┌N/t┐个迭代。当使用size时,将每 size 表示每次分配的迭代次数的最小值,由于每次分配的迭代次数会逐渐减少, 定,所以迭代被分配到哪个线程是无法事先知道的。 次给线程分配size次迭代。 少到 size时,将不再减少。如果不知道 size的大小,那么默认size 为1 ,即一直减少 当不使用 size 时,是将迭代逐个地分配到各个线程。当使用 size 时,逐个 到1 。具体采用哪一种启发式算法,需要参考具体的编译器和相关手册的信息。 分配 size 个迭代给各个线程。
在四核机器上执行: (1)当不使用参数时,100/4=25,0-24由1 号线程执行;25-49由2号线程执行;50-74由3 号线程执行;75-99由4号线程执行 (2)当使用参数时,x(x=0,1,2,3)线程执行 ((n/5)%4)任务。其中n=0-99。
控制数据的共享属性
1、OpenMP程序在同一个共享内存空间上执行,可以任意使用这 个共享内存空间上的变量进行线程间的数据传递 2、OpenMP还允许线程保留自己的私有变量不能让其他线程访 问 int g=8; void funb(int * x, int *y, int z) { static int sv; int u; u=(*y)*g; *x=u+z; } void funa(int * a, int n) { int i; int cc=9; #pragma omp parallel for for(i=0;i<n;i++){ int temp=cc; funb(&a[i],&temp,i); } }
for循环并行化的约束条件
1. for循环中的循环变量必须是有符号整形。 例如,for (unsigned int i = 0; i <10; ++i){}会编译不通过; 2. for循环中比较操作符必须是<, <=, >, >=。 例如for (int i = 0; i != 10; ++i){}会编译不通过; 3. 如果for循环中的比较操作为<或<=,那么循环变量只能增加;反之亦然。 例如for (int i = 0; i <= 10; --i)会编译不通过; 4. for循环中的三个表达式,必须按照严格的书写规范,只能有一个变量。 例如for (int i = 0, j=0; i <= 10; i++){}会编译不通过; 5. 循环必须是单入口、单出口,也就是说循环内部不允许能够达到循环以外的跳 转语句,exit除外。异常的处理也必须在循环体内处理。 例如:若循环体内的break或goto会跳转到循环体外,那么会编译不通过。
线程私有数据与threadprivate,copyin子句
对于所有的线程私有全局变量来说,除了主线程,其它线程的私有变量在运行 过程中是没有初始化的,为了使用主线程的变量初始化的值,我们使用copyin 子句对线程私有的全局变量进行初始化。
并行区域编程
并行区域之间的工作共享:
1、工作队列 工作队列的基本工作过程即维持一个工作的队列,线程在并行执行 的时候,不断从这个队列中取出相应的工作完成,直到队列为空为 止。 2、根据线程号分配任务 由于每一个线程在执行的过程中的线程标识号是不同的,可以根据这个 线程标识号来分配不同的任务
0.206644
0.203056 0.219743 0.207167 0.216280
0.210537
0.065334
0.068596 0.049978 0.061647 0.070892 0.0629447
0.05
0 1 2 3 4 5 6 7 8 9 10
openmp的实例:求十万内的素数和
一个线程 1 2 3 平均值 加速比
parallel 指令的用法
parallel 是用来构造一个并行块的,也可以使用其他指令如for、sections等和它 配合使用。 #pragma omp parallel [for | sections] [子句[子句]…] { //代码 }
for指令的使用方法
for指令则是用来将一个for循环分配到多个线程中执行,一般可以和 parallel指令合起来形成parallel for指令使用,也可以单独用在parallel语句的 并行块中。 #pragma omp [parallel] for [子句] for循环语句 例:
Fork-Join执行模式
在开始执行的时候,只有主线程的运行线程存在 主线程在运行过程中,当遇到需要进行并行计算的时候,派生出 (Fork,创建新线程或者唤醒已有线程)线程来执行并行任务
在并行执行的时候,主线程和派生线程共同工作
在并行代码结束执行后,派生线程退出或者挂起,不再工作,控制流 程回到单独的主线程中(Join,即多线程的会和)。
OpenMP的介绍与使用
目录
什么是openmp? Openmp常用指令的用法 openmp的实例
一、什么是openmp?
1.面向共享内存以及分布式共享内存的多处理器多线程并行编程的一种编 译指导语句,是能够显式指导多线程、共享内存并行的应用程序编程接口。 OpenMP支持的编程语言包括C语言、C++和Fortran;OpenMp提供了对 并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma 来指明自己的意图,由此编译器可以自动将程序进行并行化。
线程私有数据与threadprivate,copyin子句
对于每一个线程来说,可能需要生成自己私有的线程数据,此时,就需要使 用threadprivate子句用来标明某一个变量是线程私有数据,在程序运行的过程中, 不能够被其它线程访问到。 执行过程最后结果都为:
而如果将含有注释的那一行删除,就将全局 变量counter变为共享,执行可能的结果:
串行和并行的比较
次数 1 2 3 4 5
串行 0.213116 0.209457 0.198449 0.209983 0.221492
并行 0.064361 0.072224 0.050114 0.066737 0.059564
0.15 串行 0.1 并行 0.2 0.25
6
7 8 9 10 平均值
1.6 1.4 1.2 1 0.8 0.6 0.4 0.2 0 一 二 四 八 mpi openmp
sections和section指令的用法
section语句是用在sections语句里,用来将sections语句里的代码划分成几 个不同的段,每段都并行执行。
#pragma omp [parallel] sections [子句] { #pragma omp section { 代码块 } }
用for语句来分摊是由系统自动进行,只要每次循环间没有时间 上的差距,那么分摊是很均匀的,使用section来划分线程是一种手 工划分线程的方式,最终并行性的好坏得依赖于程序员。
OpenMP中的线程任务调度
OpenMP中任务调度主要针对并行的for循环,当循环中每次迭源自文库的计算量 不相等时,如果简单地给各个线程分配相同次数的迭代,则可能会造成各个线 程计算负载的不平衡,影响程序的整体性能。
#pragma omp parallel private(myid) { nthreads = omp_get_num_threads(); myid = omp_get_thread_num(); my_work_done(myid, nthreads); }
三、openmp的实例
串行程序 并行程序