承接前面两篇,这里直接逐一介绍和使用有关OpenMP的指令和函数

Directives

1、for

作用:for指令指定紧随其后的程序的循环的迭代必须由团队并行执行,只是假设已经建立了并行区域,否则它在单个处理器上串行执行。

格式:

 #pragma omp for [clause ...] newline
schedule (type [,chunk])
ordered
private (list)
firstprivate (list)
lastprivate (list)
shared (list)
reduction (operator:list)
collapse (n)
nowait for_loop

可以使用如下子句:

还可以通过Schedule子句(clause)设置for循环的并行化方法:(有关一种调度如何比其他调度更优化的讨论,请参阅http://openmp.org/forum/viewtopic.php?f=3&t=83

  • static:循环迭代被分成size chunk,然后静态的分配给各个线程,如果chunk没有被指定,则均匀地划分(如果可能)给各个线程
  • dynamic:循环迭代被分成size chunk,然后动态地分配给各个线程,当一个chunk完成时,被分配另外一个chunk。默认地chunk size为1
  • guided:当线程请求循环迭代时,迭代会动态地分配给块中地线程,直到没有剩余的块要被分配。与dynamic类似,不同的地方在于每次为线程分配chunk时都会变小,所以最初组中的循环体执行数目较大。初始大小与以下成正比,number_of_iterations / number_of_thread,后续块与之成比例,number_of_iterations_remaining / number_of_threads。
  • runtime: 循环的并行化方式不在编译时静态确定,而是推迟到程序执行时动态地根据环境变量OMP_SCHEDULE 来决定要使用的方法。此时在子句中指定chunk_size是非法的
  • auto:调度决策取决于编译器/运行时系统  

nowait子句:如果指定,则线程在循环结束时不同步

ordered子句:指定必须像在串行程序中一样执行循环的迭代,可以对for的部分使用

collapse子句:指定嵌套循环中应将多少循环折叠到一个大的迭代空间中,并根据schedule子句进行划分 。折叠迭代空间中的迭代顺序被确定为顺序执行它们。可以改善表现。

其它的子句后面会做介绍

限制:

  • 循环迭代变量必须是整数,并且所有线程的循环控制参数必须相同
  • 程序正确性不能取决于哪个线程执行特定迭代,需要确保程序的正确性
  • 从for指令关联的循环中分支是非法的
  • 必须将块大小指定为循环不变整数表达式,因为在不同线程的评估期间没有同步

示例

  #include <omp.h>
#define N 1000
#define CHUNKSIZE 100 main(int argc, char *argv[]) { int i, chunk;
float a[N], b[N], c[N]; /* Some initializations */
for (i=; i < N; i++)
a[i] = b[i] = i * 1.0;
chunk = CHUNKSIZE; #pragma omp parallel shared(a,b,c,chunk) private(i)
{ #pragma omp for schedule(dynamic,chunk) nowait
for (i=; i < N; i++)
c[i] = a[i] + b[i]; } /* end of parallel region */ }

2、section

作用:section是一种非迭代的工作共享结构,代码被划分成多个区域

格式:

 #pragma omp sections [clause ...]  newline
private (list)
firstprivate (list)
lastprivate (list)
reduction (operator: list)
nowait
{ #pragma omp section newline structured_block #pragma omp section newline structured_block }

注意:

  • 除非使用nowait子句,否则sections指令结尾都有一个隐含的障碍
  • 分区块里不能含有分支

示例

  #include <omp.h>
#define N 1000 main(int argc, char *argv[]) { int i;
float a[N], b[N], c[N], d[N]; /* Some initializations */
for (i=; i < N; i++) {
a[i] = i * 1.5;
b[i] = i + 22.35;
} #pragma omp parallel shared(a,b,c,d) private(i)
{ #pragma omp sections nowait
{ #pragma omp section
for (i=; i < N; i++)
c[i] = a[i] + b[i]; #pragma omp section
for (i=; i < N; i++)
d[i] = a[i] * b[i]; } /* end of sections */ } /* end of parallel region */ }

3、其它的不一一介绍了,请参阅:OpenMP

Clause

前面已经介绍了几个子句,这里主要介绍数据作用域子句。

1、private

作用:private子句将其列表中的变量声明为每个线程的私有变量

格式:

private (list)

要点:

  • 在组中的每个线程声明一个相同数据类型的变量
  • 所有对原始变量的引用全部替换为对新变量的引用
  • 被声明为private的变量应被认为未初始化

2、shared

作用:shared子句声明其列表中的变量,以便在团队中的所有线程之间共享

格式:

shared (list)

要点:

  • 共享变量仅存在于一个内存位置,并且所有线程都可以读取或写入该地址
  • 程序员有责任确保多个线程正确访问SHARED变量(例如通过CRITICAL部分)

3、reduction

作用:reduction子句对列表中的每个变量执行简化操作。为每个线程创建并初始化每个列表变量的私有副本。在缩减结束时,reduce变量应用于共享变量的所有私有副本,最终结果将写入全局共享变量。

格式:

 reduction (operator: list)

示例:

并行循环的迭代将以相同大小的块分配给团队中的每个线程(SCHEDULE STATIC);

在并行循环结构的末尾,所有线程将添加其“result”值以更新主线程的全局副本;

 #include <omp.h>

  main(int argc, char *argv[])  {

  int   i, n, chunk;
float a[], b[], result; /* Some initializations */
n = ;
chunk = ;
result = 0.0;
for (i=; i < n; i++) {
a[i] = i * 1.0;
b[i] = i * 2.0;
} #pragma omp parallel for \
default(shared) private(i) \
schedule(static,chunk) \
reduction(+:result) for (i=; i < n; i++)
result = result + (a[i] * b[i]); printf("Final result= %f\n",result); }

4、其它还有很多,省略

Run-time Library Routines

  • OpenMP API包含越来越多的运行时库例程
  • 对于C / C ++,所有运行时库例程都是实际的子例程。对于Fortran,有些实际上是函数,有些是子例程。
  • 对于C / C ++,通常需要包含 <omp.h>头文件

例如:

 #include <omp.h>
int omp_get_num_threads(void)

详细的函数介绍可见OpenMP入门教程(二)

Environment Variables

  • OpenMP提供一些环境变量来控制并行程序的执行
  • 所有的环境变量名都是大写字母,但是分配给它们的值不区分大小写

1、OMP_NUM_THREADS:设置在运行期间最大的线程数

setenv OMP_NUM_THREADS 

2、OMP_DYNAMIC:启用或禁用动态调整可用于执行并行区域的线程数。有效值为TRUE或FALSE

setenv OMP_DYNAMIC TRUE

3、OMP_PROC_BIND:启用或禁用绑定到处理器的线程。有效值为TRUE或FALSE。

setenv OMP_PROC_BIND TRUE

4、OMP_STACKSIZE:控制创建(非主)线程的堆栈大小

setenv OMP_STACKSIZE 2000500B
setenv OMP_STACKSIZE“ k”
setenv OMP_STACKSIZE 10M
setenv OMP_STACKSIZE“ M”
setenv OMP_STACKSIZE“ m”
setenv OMP_STACKSIZE“1G”
setenv OMP_STACKSIZE

4、还有很多其它的,省略

注:前面的运行API也能做与环境变量一样的工作,同时使用环境变量和运行时 API 会出现什么情况?运行时 API 将获得更高的优先权。

注:这是一个简单的OpenMP的练习网站:https://computing.llnl.gov/tutorials/openMP/exercise.html

参考链接:https://computing.llnl.gov/tutorials/openMP/#Abstract

OpenMP入门教程(三)的更多相关文章

  1. 无废话ExtJs 入门教程三[窗体:Window组件]

    无废话ExtJs 入门教程三[窗体:Window组件] extjs技术交流,欢迎加群(201926085) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3 ...

  2. PySide——Python图形化界面入门教程(三)

    PySide——Python图形化界面入门教程(三) ——使用内建新号和槽 ——Using Built-In Signals and Slots 上一个教程中,我们学习了如何创建和建立交互widget ...

  3. Elasticsearch入门教程(三):Elasticsearch索引&映射

    原文:Elasticsearch入门教程(三):Elasticsearch索引&映射 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文 ...

  4. RabbitMQ入门教程(三):Hello World

    原文:RabbitMQ入门教程(三):Hello World 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...

  5. JasperReports入门教程(三):Paramters,Fields和Detail基本组件介绍

    JasperReports入门教程(三):Paramter,Field和Detail基本组件介绍 前言 前两篇博客带领大家进行了入门,做出了第一个例子.也解决了中文打印的问题.大家跟着例子也做出了de ...

  6. WebGL入门教程(三)-webgl动画

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL动画有移动.旋转和缩放,我们将移动.旋转和缩放图形,然后将其绘制到屏幕上,称为变换(tr ...

  7. 无废话SharePoint入门教程三[创建网站集和网站]

    一.前言 前两篇文章讲解了什么是SharePoint,并且介绍了在SharePoint中一些常用的概念.但概念终究是概念,我们还是要脚踏实地的去动手实践.下面的文章对于了解SharePoint的人来说 ...

  8. Spring Cloud 入门教程(三): 配置自动刷新

    之前讲的配置管理, 只有在应用启动时会读取到GIT的内容, 之后只要应用不重启,GIT中文件的修改,应用无法感知, 即使重启Config Server也不行. 比如上一单元(Spring Cloud ...

  9. OpenMP 入门教程

    前两天(其实是几个月以前了)看到了代码中有 #pragma omp parallel for 一段,感觉好像是 OpenMP,以前看到并行化的东西都是直接躲开,既然躲不开了,不妨研究一下: OpenM ...

随机推荐

  1. git 如何让单个文件回退到指定的版本【转】

    本文转载自:http://blog.csdn.net/ikscher/article/details/43851643 1.进入到文件所在文件目录,或者能找到文件的路径查看文件的修改记录 1 $ gi ...

  2. CodeForces-652D:Nested Segments(树状数组+离散化)

    You are given n segments on a line. There are no ends of some segments that coincide. For each segme ...

  3. Surface pro4 触摸板手势快捷键

    [一个手指]:这个大家都知道就不必在介绍了,跟之前win7一样,滑动就是鼠标,轻点(或者按左下方)就相当于点鼠标左键.(两个按键按起来真心手感不咋的,所以基本不用)[两个手指]:1.两个手指向上或下滑 ...

  4. Java-Runoob-高级教程-实例-字符串:09. Java 实例 - 字符串小写转大写

    ylbtech-Java-Runoob-高级教程-实例-字符串:09. Java 实例 - 字符串小写转大写 1.返回顶部 1. Java 实例 - 字符串小写转大写  Java 实例 以下实例使用了 ...

  5. 3winsock编程1

    先看几个结构体定义 typedef struct WSAData { WORD wVersion;//版本号 通过MAKEWORD(2,2)返回该值 高位字节存储副版本号 第位字节存储主版本号 WOR ...

  6. Ruby IO类

    更新: 2017/06/23   表格大小全部改为100%                             文件输入输出的File....系列函数的文件名参数是字符串! 更新: 2017/06 ...

  7. ios开发-常见的项目文件介绍

    一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要用来放依赖的框架 3.test文件夹是 ...

  8. [C++11新特性] 智能指针详解

    动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极为困难的.有时我们会忘记释放内存产生内存泄漏,有时提前释放了内存,再使用指针去引用内存就会报错. 为了更容易(同时也更安全)地使用动态内存, ...

  9. [ZPG TEST 116] 最小边权和【生成树相关】

    先将输入的边从小到大排序,对于一条边,它一定连接着两个联通块u与v,那么这条变对于答案的贡献是siz[u] * siz[v] * (边权 + 1) - 1,别问为什么这太显然了,一想就懂... #in ...

  10. [USACO 2012 Feb Gold] Cow Coupons【贪心 堆】

    传送门1:http://www.usaco.org/index.php?page=viewproblem2&cpid=118 传送门2:http://www.lydsy.com/JudgeOn ...