OpenMP 参考(指令详解)

作者:操作系统    发布时间:2020-02-10 06:55     浏览次数 :

[返回]

在本人的主次中,作者考虑对以下四个巡回用OpenMP并行化doublepottemp,pot2body;pot2body=0.0;pottemp=0.0;#pragmaompparallelforreduction(+:pot2body)private(pottemp)schedule(dynamic)for(inti=0;inc2;i++){pottemp=ener2body[i]-calculatePot(ener2body[i]-m_molsState of Qatar;pot2body+=pottemp;}个中等高校函授数'calculatePot'中二个很关键的大循环也被用OpenMP并行化了CEnergymulti::calculatePot(vectorCMolecule*m_mols){...#pragmaompparallelforreduction(+:dev)schedule(dynamic)for(inti=0;ii_max;i++卡塔尔{...}}所以实际上在自个儿的并行化程序中冒出了对嵌套循环的四次并行化。当本身策动把最外面风流倜傥层循环的并行化去掉后,开掘运路程序的进程反而比不并行快非常多。相当于说小编从前并行化的成效超低,所以小编想问一下用怎么样点子能使小编的并行化效能升高吗(假使依然使用OpenMP,作者不太想使用MPI卡塔尔?互连网有人建议对于嵌套循环,在最外层循环的#pragmaompparallelfor前边加上collapse,但网络又说collapse只限于嵌套的五个循环之间未有任何语句的处境。所以像作者这种嵌套循环,是或不是还会有其余方法提升并行效用呢?

OpenMP 仿照效法(指令精解)

翻译 2011年03月21日 17:53:00

  • 标签:
  • parallel /
  • fortran /
  • newline /
  • list /
  • integer /
  • 工作 /
  • 9866
  • 编辑
  • 删除

  小喵的唠叨话:前段时间十分久没写博客了,一是因为事前写的LSoftmax后馈一贯未能如愿,所以在等笔者的源码。二是近期没什么想写的事物。前二日,在预管理图片的时候,开掘管理200w张图纸,跑了生龙活虎晚上也才管理完二分一。早晨的时候,必不得已,花半个小时改写了贰个大致调用OpenMP的管理程序,用了三10个大旨,然后风姿罗曼蒂克钟头不到就管理完了。感叹在多核的一代,固然是大约的前后相继,就算能支撑多核,应该都能节约数不完时日。

分享职业(Work-Sharing) 构造

  • 分享专业组织将它功能的代码段在达到此代码段的线程中抽离实施
  • Work-sharing 不会生出新线程
  • 跻身工作分享布局时不曾关卡,但停止时会有

Work-Sharing 布局的品类:

注意: 关于Fortran 的workshare 布局稍后斟酌

DO / for - 在一组线程中共享循环中的计数器

(iteration). 表示一种 “数据并行处理”.

SECTIONS - 将工作分成独立,不关联的片段。

每个片段被一个线程执行。用来实现一种

“函数并行处理”

SINGLE - 串行化代码段

 

 

 

规则:

  • 为了能并行试行此命令,三个干活分享布局必得被并行区域动态密封
  • 一个线程组达到三个办事分享结构时,要么全体全线程被占用,要么不占用
  • 线程组的具有成员必需以同风流倜傥的逐生机勃勃达到一连的做事分享构造

 DO / for 指令

目的:

  • DO/for指令评释接下去的轮回将被并行试行。前提是一个互相区域已经被开端化,否则以串行的法子试行。

 格式:

Fortran

 
!$OMP DO [clause ...] 
         SCHEDULE (type [,chunk]) 
         ORDERED 
         PRIVATE (list) 
         FIRSTPRIVATE (list) 
         LASTPRIVATE (list) 
         SHARED (list) 
         REDUCTION (operator | intrinsic : list) 
         COLLAPSE (n) 
 
   do_loop
 
!$OMP END DO  [ NOWAIT ]

C/C++

 
#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: 描述线程组中的线程分配多少次巡回。 私下认可schedule注重于具体落到实处

STATIC

巡回遵照chunk的值被等分并静态付与线程。若无一些名chunk,那么将均分此循环。

DYNAMIC

循环根据chunk的值被等分并动态授予线程。假使叁个线程实现了一个支行,那么它将三番五次运转下一个分段。暗中认可的chunk值为1.

GUIDED

借使chunk为1,各种分支的值为剩下的循环次数除以线程数量,减弱到1.只要chunk的值为K(比1大),每块分支也以雷同的法子分配迭代次数,只是每块的迭代次数非常的大于K。私下认可chunk的值为1.

RUNTIME

调治的计策信任于运作时的景况变量OMP_SCHEDULE.为那一个子句钦定chunk的值是不法的。

AUTO

调解战略信赖于编写翻译器只怕运转时系统

  • NO WAIT / nowait: 借使钦赐了,线程在互相循环截至时不会同步.
  • ORDERED: 钦定该循环迭代务必以串行情势施行.
  • COLLAPSE:钦命在三个嵌套循环中,多少次巡回被折叠到叁个大的迭代空间并依据schedule子句来划分。全数有关循环中的迭代的实行顺序决定迭代空间中折叠迭代的次第。
  • 别的的子句就要Data Scope Attribute Clauses 章节牵线

规则:

  • DO循环不可能是DO WHILE循环,也无法未有循环调整。循环迭代变量必需是整型,并且对于全数的线程,循环调节参数都生机勃勃律
  • 先后的不易不能够决议于那多个线程实行了特定的迭代
  • 与DO/for 指令关联的轮回要依据规范格式书写
  • 由于分化的线程在赋值时并不联合,chunk的值必需钦定为二个周而复始的不变整型表明式
  • TiggoDERED, COLLAPSE 和SCHEDULE 子句只可选其大器晚成.
  • 翻看OpenMP的相干文档获得额外的音信

正文系原创,转发请申明出处~

范例: DO / for 指令

  • 对vector执行加法操作的总结程序
    • 数组A, B, C, and 变量N 被所有线程分享.
    • 变量I对各样线程都以个人的;每一个线程都会有一个它的唯风姿洒脱copy .
    • 巡回的迭代将被动态地以CHUNK为单位分发.
    • 线程在做到各自的独门的做事时并不进行联合(NOWAIT卡塔尔.

Fortran - DO Directive Example


 
      PROGRAM VEC_ADD_DO 
      INTEGER N, CHUNKSIZE, CHUNK, I
      PARAMETER (N=1000) 
      PARAMETER (CHUNKSIZE=100) 
      REAL A(N), B(N), C(N) 
!     Some initializations
      DO I = 1, N
        A(I) = I * 1.0
        B(I) = A(I)
      ENDDO
      CHUNK = CHUNKSIZE
        
!$OMP PARALLEL SHARED(A,B,C,CHUNK) PRIVATE(I)
 
!$OMP DO SCHEDULE(DYNAMIC,CHUNK)
      DO I = 1, N
         C(I) = A(I) + B(I)
      ENDDO
!$OMP END DO NOWAIT
 
!$OMP END PARALLEL
 
      END

· 

C / C++ - for Directive Example


#include <omp.h>
#define CHUNKSIZE 100
#define N     1000 
main ()  
int i, chunk;
float a[N], b[N], c[N];
 
/* Some initializations */
for (i=0; 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=0; i < N; i++)
    c[i] = a[i] + b[i]; 
  }  /* end of parallel section */
 
}

 

小喵的博客:http://www.miaoerduo.com

SECTIONS 指令

目的:

  • SECTIONS指令是生龙活虎种非迭代式工作分享结构。它钦定段中的代码被分配到线程组的线程中实行。
  • 独自的SECTION指令嵌套在SECTIONS指令中。每种SECTION仅被线程组中的三个线程实行。分歧的段大概被差异的线程实施。在促成允许的情况下,假若一条线程丰富快,它恐怕会实行有个别个代码段。

 

格式:

Fortran

 
!$OMP SECTIONS [clause ...] 
               PRIVATE (list) 
               FIRSTPRIVATE (list) 
               LASTPRIVATE (list) 
               REDUCTION (operator | intrinsic : list) 
 
!$OMP  SECTION 
 
   block
 
!$OMP  SECTION 
 
    block 
 
!$OMP END SECTIONS  [ NOWAIT ]

C/C++

 
#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/nowait子句未有被利用,在SECTIONS指令结束时会有三个隐身的关卡(barrier)
  • 越来越多子句在Data Scope Attribute Clauses 章节详细斟酌.

问答:

   

 

如果线程数量和SECTIONS的数量不一样会怎样?比SECTIONS多呢?比SECTIONS少呢?

 

 

 

 

哪条线程执行哪块SECTION?

规则:

  • section块要遵照格式书写(It is illegal to branch into or out of section blocks.) 
  • SECTION指令只可以出未来SECTIONS指令的静态范围内

博客原来的文章:http://www.miaoerduo.com/openmp/应用openmp的三个简易的希图形式.html

范例: SECTIONS 指令

  • 呈现不相同的行事块被不相同的线程奉行的归纳程序

Fortran - SECTIONS Directive Example


      PROGRAM VEC_ADD_SECTIONS 
      INTEGER N, I
      PARAMETER (N=1000)
      REAL A(N), B(N), C(N), D(N) 
!     Some initializations
      DO I = 1, N
        A(I) = I * 1.5
        B(I) = I + 22.35
      ENDDO 
!$OMP PARALLEL SHARED(A,B,C,D), PRIVATE(I) 
!$OMP SECTIONS 
!$OMP SECTION
      DO I = 1, N
         C(I) = A(I) + B(I)
      ENDDO
!$OMP SECTION
      DO I = 1, N
         D(I) = A(I) * B(I)
      ENDDO 
!$OMP END SECTIONS NOWAIT 
!$OMP END PARALLEL
 
      END

· 

C / C++ - sections Directive Example


 
#include <omp.h>
#define N     1000 
main ()
int i;
float a[N], b[N], c[N], d[N]; 
/* Some initializations */
for (i=0; 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=0; i < N; i++)
      c[i] = a[i] + b[i]; 
    #pragma omp section
    for (i=0; i < N; i++)
      d[i] = a[i] * b[i];
 
    }  /* end of sections */ 
  }  /* end of parallel section */
 
}

 

 

WORKSHARE 指令

目的:

  • Fortran 适用
  • WOOdysseyKSHARE指令将密封的协会块分成一些单独的做事单元来施行,各个专门的学问单元被实行一回。
  • 结构块只好由如下组合:
    • array assignments
    • scalar assignments
    • FORALL statements
    • FORALL constructs
    • WHERE statements
    • WHERE constructs
    • atomic constructs
    • critical constructs
    • parallel constructs
  • 更加多音信请查看OpenMP API 文书档案.

格式:

Fortran

 
!$OMP WORKSHARE
 
   structured block
 
!$OMP END WORKSHARE [ NOWAIT ]

规则:

  • 除此之外ELEMENTAL函数,该组织不能够包涵其余客户函数调用.

后生可畏、写在前面

对此OpenMP,小喵其实并非精晓比比较多,况且小喵自个儿也只用到了OpenMP的最简易的功能。在这里处根本是共享叁个融洽常用的写轻便的并行程序的笔触。希望能扶助到大家。

以此设计情势的第风流倜傥特征如下:

1,处理的职务是单独的;

2,能够在运营中输出结果,并不是最后才输出;

3,有限的财富占用;

4,在每趟职务的执行时间不生龙活虎的场合下,也能很好的行事;

5,在历次任务试行需求占用私有的数量时(信赖了线程不安全的库),也得以很好的做事;

6,输出是有序的

 

只顾:本文中仅介绍小喵本人用到的几个OpenMP的功用。既不深切也不周密。仅切合初读书人。

小喵学习OpenMP首借使看了周明伟的博客:

OpenMP编制程序指南:

想要相比较中肯地上学的童鞋请看周先生的博客。

对此怎样是OpenMP,OpenMP有哪些长处等的标题。周先生的博客也很详细的认证。这里小喵就相当的少废话了。直接奔向主旨。

范例: WORKSHARE 指令

  • Simple array and scalar assigments shared by the team of threads. A unit of work would include:
    • Any scalar assignment
    • For array assignment statements, the assignment of each element is a unit of work

Fortran - WORKSHARE Directive Example


 
      PROGRAM WORKSHARE
 
      INTEGER N, I, J
      PARAMETER (N=100)
      REAL AA(N,N), BB(N,N), CC(N,N), DD(N,N), FIRST, LAST
 
!     Some initializations
      DO I = 1, N
        DO J = 1, N
          AA(J,I) = I * 1.0
          BB(J,I) = J + 1.0
        ENDDO
      ENDDO
 
!$OMP PARALLEL SHARED(AA,BB,CC,DD,FIRST,LAST)
 
!$OMP WORKSHARE
      CC = AA * BB
      DD = AA + BB
      FIRST = CC(1,1) + DD(1,1)
      LAST = CC(N,N) + DD(N,N)
!$OMP END WORKSHARE NOWAIT
 
!$OMP END PARALLEL
 
      END

 

二、怎样选用OpenMP

小喵使用的开销条件是Linux,windows的童鞋能够看一下那些博客:。MAC上的GCC实际上是Clang,想要使用OpenMP的话相比劳累。要额外装一些东东,自身bing一下就有。

本喵的编写翻译碰着是CentOS 7, GCC 4.8.5。大非常多连串和编写翻译器都扶持OpenMP了。

先举个小栗子:

不使用OpenMP:

 1 #include <iostream>
 2 #define N 100000000
 3 
 4 int fun() {
 5     int a = 0;
 6     for (int i = 0; i < N; ++ i) {
 7         a += i;
 8     }
 9     return a;
10 }
11 
12 int main() {
13 
14     for (int i = 0; i < 100; ++ i) {
15         fun();
16     }
17     std::cout << "finish" << std::endl;
18     return 0;
19 }

事后选取g++编写翻译,并计时:

g++ sample_without_omp.cpp -o sample_without_omp.bin
time ./sample_with_omp.bin

运维结果:

./sample_without_omp.bin  24.42s user 0.00s system 100% cpu 24.417 total

这里能够见见用了100%的cpu,总时间是24.417 s。

使用OpenMP,调用2个线程:

 1 #include <iostream>
 2 #include <omp.h>
 3 
 4 #define N 100000000
 5 
 6 int fun() {
 7     int a = 0;
 8     for (int i = 0; i < N; ++ i) {
 9         a += i;
10     }
11     return a;
12 }
13 
14 int main() {
15 
16 #pragma omp parallel for num_threads(2) schedule(dynamic)
17     for (int i = 0; i < 100; ++ i) {
18         fun();
19     }
20     std::cout << "finish" << std::endl;
21     return 0;
22 }

此处源码的异样是多了叁个omp.h的头文件,和一个难以置信的话语:

#pragma omp parallel for num_threads(2) schedule(dynamic)

编写翻译的时候,也是有一点小校勘:

g++ sample_with_omp.cpp -o sample_with_omp.bin -fopenmp
time ./sample_with_omp.bin

运营结果如下:

./sample_with_omp.bin  24.32s user 0.01s system 199% cpu 12.182 total

能够见见,user的年华差相当少没变,那意味CPU总的运维时刻还未有变化。然则cpu的使用形成了199%,total的年月变成了12.182 s。那就申明了小编们选择了2个cpu,使得运营时刻成功减半了!

是或不是很快乐,大家只加多了2行代码,就使得程序的速度翻倍。可以见到OpenMP是多么的简短实用。

那就是说,今后是或不是无须小喵说,大家也掌握怎么给程序插手OpenMP的支撑了呢?

综合一下,首要有三点:

1,到场OpenMP的头文件 omp.h

2,使用合适的编写翻译器指令修饰大家须求彼此的有个别(线程数、职务分配情势等等,后边会讲到)

3,编写翻译的时候参与openmp的支撑,编写翻译的时候加入参数 -fopenmp

SINGLE Directive

目的:

  • SINGLE 指令表示其功效的代码将单线程实行.
  • 当实行非线程安全代码段(如I/O)时会派上用途

格式:

Fortran

 
!$OMP SINGLE [clause ...] 
             PRIVATE (list) 
             FIRSTPRIVATE (list) 
 
   block
 
!$OMP END SINGLE [ NOWAIT ]

C/C++

 
#pragma omp single [clause ...]  newline 
                   private (list) 
                   firstprivate (list) 
                   nowait
 
     structured_block

子句:

  • 除非钦命了NOWAIT/nowait指令,线程组中尚无实行SINGLE指令的线程将要密闭代码块的扫尾处等待.
  • 越来越多的子句描述见Data Scope Attribute Clauses 章节.

规则:

  • SINGLE块要根据格式书写(It is illegal to branch into or out of a SINGLE block. )

 

三、fork/join的并行实行方式

我们事情未发生前见到了多少个回顾的事例,能够看见,程序其实是有串行部分和人机联作部分三个部分构成的。

在前后相继刚启动的时候,唯有三个主线程,当推行到相互部分的时候(下面的例证中就是pragma之后的for循环),并行的代码会通过派生别的线程来施行。独有当互相的享有代码推行完事后,才会继续执行串行的风姿洒脱部分。

据此首要的运转流程是这个样子的:

图片 1

掌握那些流程是意气风发对后生可畏关键的,可以制止过多的没有必要的不当。两个大范围的怪诞正是能源访问的冲突。比方文件,流对象等,假诺在互相的代码部分随便拜会这几个财富,就恐怕会促成不可预感的不当。那在三十二线程编制程序中也是最常现身的大谬不然,我们在下面会具体提起。

统生龙活虎的交互作用专门的工作分享布局

四、OpenMP的常用命令和库函数

在C/C++中,OpenMP的下令使用的格式如下:

#pragma omp 指令 [子句[子句]...]

指令用来提示下边包车型地铁代码的运作形式。子句是提交一些非常的音讯。

此间根本介绍多少个指令:parallelfor

parallel:用在代码段在此以前,表示上面包车型地铁代码段使用八线程运营。

for:用于for循环在此以前,将循环分配到七个线程中并行实践,必得确定保障每便循环之间无相关性。

parallel for:parallel 和for语句的三结合,也是用在一个for循环从前,表示for循环的代码将被多少个线程并行实施。

小喵使用的时候都以直接行使了parallel for这么些组成指令。用来对接着的for循环的代码段举行相互。其余的吩咐请查阅以前提到的博客。

子句中首假诺交给一些相当的装置,这里也重视介绍2个:num_threads,schedule。

num_threads:内定线程的数据(不设置该参数好似会利用和cpu大旨数大器晚成致的线程数)。

schedule:钦定如何调节for循环迭代。有4种情势:static、dynamic、guided,runtime,前边会特别讲到。

此处,我们再回首一下事前写的代码:

#pragma omp parallel for num_threads(2) schedule(dynamic)

是或不是茅塞顿开。那句话的意趣是,使用OpenMP(#pragma omp),将下边包车型客车for循环使用二十四线程去推行(parallel for),线程数为2(num_threads(2)),职分调解格局利用dynamic情势(schedule(dynamic))。

前段时间,让大家搭乘飞机,学习for循环的写法。

那边,小喵直接复制了周先生的布道(解释得实在太好了):

for 循环语句中,书写是亟需依照一定规范来写才得以的,即for循环小括号内的话语要奉公守法一定的正式实行书写,for语句小括号里共有三条语句
for( i = start; i < end; i++)

i = start; 是for循环里的第一条语句,必得写成 “变量=初值” 的措施。如 i=0
i < end; 是for循环里的第二条语句,那个讲话里可以写成以下4种格局之生龙活虎:
变量 < 边界值
变量 <= 边界值
变量 > 边界值
变量 >= 边界值
如 i>10 i<10 i>=10 i<=10 等等
style="font-size: 10pt">最终一条语句i++能够有以下9种写法之生龙活虎
i++
++i
i--
--i
i += inc
i -= inc
i = i + inc
i = inc + i
i = i – inc
比如i += 2; i -= 2;i = i + 2;i = i - 2;都是适合标准的写法。

足见日常的话,大家的for循环的写法OpenMP是支撑的。那么有没有OpenMP不协助的for循环呢?小喵没试过,但是能够测度,for (auto &v: arrState of Qatar这种写法是不扶助的。使用迭代器的话,不知晓能否选择,小喵未有认证过。喵粉假设好奇的话,能够自动验证一下。

在介绍schedule从前,大家先读书多少个常用的库函数,用来收获和安装OpenMP的种种运转时意况:

omp_get_num_procs, 重返运转本线程的多管理机的计算机个数。平日能够依靠微处理器的个数来合理设置并行的线程数。
omp_get_num_threads, 再次回到当前相互区域中的活动线程个数。举个例子上面的例子,应该就能回来2。
omp_get_thread_num, 重临线程号。并行区域的代码会被多少个线程奉行,而种种线程都有叁个谈得来的ID,也正是线程号。假设大家设置使用N个线程,那么线程号会是0,1,2,...,N-1。
omp_set_num_threads, 设置并行实践代码时的线程个数。和num_threads作用相像。

OpenMP提供了四个方便指令:

    • PARALLEL DO / parallel for
    • PARALLEL SECTIONS
    • PARALLEL WORKSHARE (fortran 适用)
  • 大部场所下,那一个指令的行为和叁个单独的PARALLEL指令前面紧跟八个单独的work-sharing指令相符

  • 大部对指令的原理,子句和限量都灵验。更加多细节参谋OpenMP API.
  • 下边是一个行使PARALLEL DO/PARALLEL FO君越联合指令的圭表 .

Fortran - PARALLEL DO Directive Example


 
      PROGRAM VECTOR_ADD
 
      INTEGER N, I, CHUNKSIZE, CHUNK
      PARAMETER (N=1000) 
      PARAMETER (CHUNKSIZE=100) 
      REAL A(N), B(N), C(N)
 
!     Some initializations
      DO I = 1, N
        A(I) = I * 1.0
        B(I) = A(I)
      ENDDO
      CHUNK = CHUNKSIZE
             
!$OMP PARALLEL DO
!$OMP& SHARED(A,B,C,CHUNK) PRIVATE(I) 
!$OMP& SCHEDULE(STATIC,CHUNK)
 
      DO I = 1, N
         C(I) = A(I) + B(I)
      ENDDO
 
!$OMP END PARALLEL DO
 
      END

· 

C / C++ - parallel for Directive Example


 
#include <omp.h>
#define N       1000
#define CHUNKSIZE   100
 
main ()  {
 
int i, chunk;
float a[N], b[N], c[N];
 
/* Some initializations */
for (i=0; i < N; i++)
  a[i] = b[i] = 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++)
    c[i] = a[i] + b[i];
}

 

 

五、OpenMP中的职分调整

那么接下去,大家最初攻读职责调解的多种方式。使用的子句正是schedule。

schedule的利用格式:

schedule(type[, size])

type主要有4种:static,dynamic,guilded,runtime。

TASK 构造

目的:

  • OpenMP 3.0的新构造
  • TASK布局定义多少个显式职分,该职分被遇上的线程实践,恐怕被线程组中的别的线程推迟试行
  • 多中国少年共产党享属性情句决定它的数量景况
  • Task的执行固守职责调整-更加多新闻请查看OpenMP4.0参照文书档案

Format:

Fortran

 
!$OMP TASK [clause ...] 
             IF (scalar expression) 
             UNTIED
             DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
             PRIVATE (list) 
             FIRSTPRIVATE (list) 
             SHARED (list) 
 
   block
 
!$OMP END TASK

C/C++

 
#pragma omp task [clause ...]  newline 
                   if (scalar expression) 
                   untied
                   default (shared | none)
                   private (list) 
                   firstprivate (list) 
                   shared (list) 
 
     structured_block

子句和限量:

  • 请参谋 OpenMP 3.0 标准文书档案

 

 

读书全文

    </div>
    <!--  <div class="reward_box">
        <div class="tit">
          <button class="btn_reward"><i class="icon iconfont icon-dashang-"></i></button>
        </div>
        <dl class="clearfix">
          <dt><a href="#" target="_blank">近期打赏</a></dt>
          <dd><a href="#" target="_blank"><img src="http://avatar.csdn.net/9/3/2/2_nzf_001.jpg" alt="聂兆芳" title="聂兆芳"></a></dd>
          <dd><a href="#" target="_blank"><img src="http://avatar.csdn.net/9/3/2/2_nzf_001.jpg" alt="聂兆芳" title="聂兆芳"></a></dd>
          <dd><a href="#" target="_blank"><img src="http://avatar.csdn.net/9/3/2/2_nzf_001.jpg" alt="聂兆芳" title="聂兆芳"></a></dd>
          <dd><a href="#" target="_blank"><img src="http://avatar.csdn.net/9/3/2/2_nzf_001.jpg" alt="聂兆芳" title="聂兆芳"></a></dd>
          <dd><a href="#" target="_blank"><img src="http://avatar.csdn.net/9/3/2/2_nzf_001.jpg" alt="聂兆芳" title="聂兆芳"></a></dd>
        </dl>
      </div>-->

    <ul class="article_collect clearfix csdn-tracking-statistics" data-mod="popu_378" style="display: none;">
        <li class="tit">本文已收录于以下专栏:</li>

    </ul>
    <div class="comment_box clearfix">
        <div id="comment_form">
            <div id="commentsbmitarear">
                <!-- <h6>0条评论</h6> -->
       <!--          <dl class="clearfix" id="commentbox">
                    <dt>
                        <a href="http://my.csdn.net/u014731650"><img src="http://avatar.csdn.net/D/0/8/1_u014731650.jpg" ></a>
                    </dt>
                    <dd>
                        <a href="http://my.csdn.net/u014731650" target="_blank">u014731650</a>
                    </dd>
                    <dd class="txt_tip"></dd>
                </dl> -->
                <div class="comment_area clearfix" style="height: 60px;">
                    <div class="userimg"><a href="http://my.csdn.net/u014731650"><img src="http://avatar.csdn.net/D/0/8/1_u014731650.jpg"></a></div>
                    <form action="/saga1979/comment/submit?id=6265564" method="post" onsubmit="return subform(this);" id="commentform">
                        <textarea class="comment_content" name="comment_content" id="comment_content" placeholder="发表你的评论" style="height: 40px;"></textarea>
                        <div class="bot_bar clearfix" style="opacity: 0;">
                            <div id="ubbtools" class="add_code">
                                <a href="#insertcode" code="code" target="_self"><i class="icon iconfont icon-daima"></i></a>
                            </div>

                            <input type="hidden" id="comment_replyId" name="comment_replyId">
                            <input type="hidden" id="comment_userId" name="comment_userId" value="">
                            <input type="hidden" id="commentId" name="commentId" value="">
                            <input type="submit" class="btn btn-redborder" value="发表评论">

                            <div style="display: none;" class="csdn-tracking-statistics" data-mod="popu_384"><a href="#" target="_blank" class="comment_area_btn">发表评论</a></div>

                            <div id="lang_list" code="code">
                                <a href="#html" style="width:95px;" class="long_name" target="_self">HTML/XML</a>
                                <a href="#objc" style="width:95px;" class="long_name" target="_self">objective-c</a>
                                <a href="#delphi" style="width:58px;" class="zhong_name" target="_self">Delphi</a>
                                <a href="#ruby" class="zhong_name" target="_self">Ruby</a>
                                <a href="#php" target="_self">PHP</a>
                                <a href="#csharp" class="duan_name" target="_self">C#</a>
                                <a style=" border-right: none;" href="#cpp" class="duan_name" target="_self">C++</a>
                                <a style=" border-bottom:none;width:95px;" href="#javascript" class="long_name" target="_self">JavaScript</a>
                                <a style=" border-bottom:none;width:95px;" href="#vb" class="long_name" target="_self">Visual Basic</a>
                                <a style=" border-bottom:none;" href="#python" class="zhong_name" target="_self">Python</a>
                                <a style=" border-bottom:none;" href="#java" class="zhong_name" target="_self">Java</a>
                                <a style="border-bottom:none;" href="#css" class="duan_name" target="_self">CSS</a>
                                <a style="border-bottom:none;" href="#sql" class="duan_name" target="_self">SQL</a>
                                <a style="border:none; " href="#plain" class="duan_name" target="_self">其它</a>

                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>

    <div class="comment_li_outbox"></div>

    <div class="more_comment" style="display: none;">
        <div id="comment_bar" class="trackgin-ad" data-mod="popu_385"></div>
    </div>

    <h3 class="recommend_tit">相关文章推荐</h3>
    <div class="recommend_list clearfix">

        <dl class="clearfix csdn-tracking-statistics" data-mod="popu_387" data-poputype="feed" data-feed-show="true" data-dsm="post">
            <dd>
                <h2><a href="/augusdi/article/details/8807757" target="_blank" strategy="BlogCommendFromBaidu_0">OpenMP中数据属性相关子句详解(2):shared/default/copyin/copyprivate子句的使用</a></h2>
                <div class="summary">
                    (1) sharedshared子句可以用于声明一个或多个变量为共享变量。所谓的共享变量,是值在一个并行区域的team内的所有线程只拥有变量的一个内存地址,所有线程访问同一地址。所以,对于并行区域内的...
                </div>
                <ul>
                    <li class="avatar_img"><a href="http://blog.csdn.net/Augusdi" target="_blank" strategy="BlogCommendFromBaidu_0"><img src="http://avatar.csdn.net/D/A/7/2_augusdi.jpg" alt="Augusdi" title="Augusdi"></a></li>
                    <li class="user_name"><a href="http://blog.csdn.net/Augusdi" target="_blank">Augusdi</a></li>
                    <li class="time">2013-04-16 11:02</li>
                    <li class="visited_num"><i class="icon iconfont icon-read"></i>4280</li>
                </ul>
            </dd>
        </dl>

        <dl class="clearfix csdn-tracking-statistics" data-mod="popu_387" data-poputype="feed" data-feed-show="true" data-dsm="post">
            <dd>
                <h2><a href="/zsc09_leaf/article/details/7759180" target="_blank" strategy="BlogCommendFromBaidu_1">OpenMP 参考(子句)</a></h2>
                <div class="summary">
                    Data Scope Attribute Clauses

也叫Data-sharing属性格句对数码成效域的明白与应用是OpenMP编制程序的首要性元素因为OpenMP是依照内部存款和储蓄器分享编制程序模型的,超级多变…

  • 图片 2
  • zsc09_leaf
  • 2012-07-18 14:54
  • 3325
        <!--dl class="clearfix csdn-tracking-statistics" data-mod="popu_393">
            <dt><a href="http://edu.csdn.net/huiyiCourse/series_detail/64?utm_source=blog10" target="_blank"><img class="maxwidth" src="http://img.blog.csdn.net/20170928113144608" alt="图片 3" title=""></a></dt>
            <dd>
                <div class="summary">
                    <h2><a href='http://edu.csdn.net/topic/python1?utm_source=blog10' target='_blank'>伤心啊!年度热门编程语言排行榜出来了...</a></h2>  <div class="summary">近期,IEEE Spectrum 发布了第四届顶级编程语言交互排行榜。结合 10 个线上数据源的 12 个标准,对 48 种语言进行了排行!此外,七牛云许式伟曾说过Go语言会取代Java...气氛... </div> 
                </div>
            </dd>
        </dl-->
<script>
    (function() {
        var s = "_" + Math.random().toString(36).slice(2);
        document.write('<div id="' + s + '"></div>');
        (window.slotbydup=window.slotbydup || []).push({
        id: '4765209',
        container: s,
        size: '808,120',
        display: 'inlay-fix'
        });
    })();
</script><div id="_m0q5wum6nkfwqo6g4cwbqpvi"></div><script charset="utf-8" src="http://pos.baidu.com/scjm?di=4765209&amp;dri=0&amp;dis=0&amp;dai=0&amp;ps=11776x33&amp;dcb=___adblockplus&amp;dtm=SSP_JSONP&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1508223385739&amp;ti=OpenMP%20%E5%8F%82%E8%80%83%EF%BC%88%E6%8C%87%E4%BB%A4%E8%AF%A6%E8%A7%A3%EF%BC%89%20-%20CSDN%E5%8D%9A%E5%AE%A2&amp;ari=2&amp;dbv=2&amp;drs=1&amp;pcs=1196x652&amp;pss=1196x11798&amp;cfv=0&amp;cpl=5&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1508223385&amp;rw=652&amp;ltu=http%3A%2F%2Fblog.csdn.net%2Fsaga1979%2Farticle%2Fdetails%2F6265564&amp;ecd=1&amp;uc=1512x900&amp;pis=-1x-1&amp;sr=1600x900&amp;tcn=1508223386"></script><a href="http://www.baidu.com/cb.php?c=IgF_pyfqnHmsrHTYrjT0IZ0qnfK9ujYzP1D4P1Tk0Aw-5Hc3rHnYnHb0TAq15HfLPWRznjb0T1dWnWm1nHPWn1TdrHcLmHf30AwY5HDdnj6znWn1PWb0IgF_5y9YIZ0lQzq-uZR8mLPbUB48ugfEpZNGXy-jULNzTvRETvNzpyN1gvw-IA7GUatvrjqdIAdxTvqdThP-5yF_UvTkn0KzujYkrfKBUHYs0ZKz5H00Iy-b5HDdP1f1PWD0Uv-b5HDzrH63nHf0mv-b5HTzPWb1n6KEIv3qn0KsXHYznjm0mLFW5HDsrjD3" target="_blank">
<dl class="clearfix csdn-tracking-statistics" data-mod="popu_393">
    <dt><img class="maxwidth" src="http://ubmcmm.baidustatic.com/media/v1/0f000D9ndwDBR6CkQlDgK0.jpg" alt="图片 4" title=""></dt>
    <dd>
        <div class="summary">
            <h2>2万和5万,人工智能行业薪酬曝光,程序员如何搭边AI领域?</h2>  <div class="summary">人工智能目前是一个快速增长的领域,对开发者的需求也是杠杠滴,那么2万和5万,AI领域的开发者都需要了解什么?掌握什么?阿里人工智能实验室高级算法专家是这么说的...</div> 
        </div>
    </dd>
</dl>

        <dl class="clearfix csdn-tracking-statistics" data-mod="popu_387" data-poputype="feed" data-feed-show="true" data-dsm="post">
            <dd>
                <h2><a href="/gengshenghong/article/details/6957594" target="_blank" strategy="BlogCommendFromBaidu_2">OpenMP Tutorial学习笔记(5)OpenMP指令之共享工作构造(Work-Sharing)</a></h2>
                <div class="summary">
                    OpenMP Tutorial:https://computing.llnl.gov/tutorials/openMP/#WorkSharing

分享职业协会:Work-Sharing Constr…

  • 图片 5
  • gengshenghong
  • 2011-11-10 22:15
  • 2350
        <dl class="clearfix csdn-tracking-statistics" data-mod="popu_387" data-poputype="feed" data-feed-show="true" data-dsm="post">
            <dd>
                <h2><a href="/hyqsong/article/details/50198551" target="_blank" strategy="BlogCommendFromBaidu_3">openMP(并行计算)  超简单快速上手</a></h2>
                <div class="summary">
                    简介:

OpenMp是并已被普遍选择的,用于分享内部存储器并行系统的多微处理器程序设计的生机勃勃套指导性的编写翻译管理方案。
OpenMP帮助的编制程序语言包涵C语言、C++和Fortran;
OpenMp提供了对并行算法…

  • 图片 6
  • hyqsong
  • 2015-12-06 21:29
  • 1320
        <dl class="clearfix csdn-tracking-statistics" data-mod="popu_387" data-poputype="feed" data-feed-show="true" data-dsm="post">
            <dd>
                <h2><a href="/scythe666/article/details/45499631" target="_blank" strategy="BlogCommendFromBaidu_4">OpenMP #pragma omp parallel for并行化小探究</a></h2>
                <div class="summary">
                    今天用了一下openmp,本人表示非常喜欢openmp的傻瓜化模式,导入一个头文件直接parallel for#include 

#include using namespace std;int ma…

  • 图片 7
  • Scythe666
  • 2015-05-05 10:47
  • 2124

1、static(静态调节)

意味着静态调治,当不设置schedule的时候,多数编写翻译器就是利用这种调解措施。它不行的简便。给定N个任务,启用t个线程,那么直接给种种线程分配N/t个任务,考虑到N只怕否整除t,所以种种线程的天职位数量会有十分的小的不等。

上面比如:

 1 #include <omp.h>
 2 #include <iostream>
 3 
 4 int main() {
 5 
 6     const int task_num = 10;
 7 
 8 #pragma omp parallel for num_threads(2) schedule(static)
 9     for (int i = 0; i < task_num; ++ i) {
10         std::cout << "i = " << i << " thread_id = " << omp_get_thread_num() << std::endl;
11     }
12 
13     return 0;
14 }

出口结果如下:

i = 0 thread_id = 0
i = 5 thread_id = 1
i = 6 thread_id = 1
i = 7 thread_id = 1
i = 8 thread_id = 1
i = 9 thread_id = 1
i = 1 thread_id = 0
i = 2 thread_id = 0
i = 3 thread_id = 0
i = 4 thread_id = 0

能够看到,0-4被分配给了0线程,5-9被分配给了1线程。由于是四线程,所以打字与印刷出来的逐一并无法确定保证。

纵然运用了size,则每一回回分配给三个线程size次职责,依次迭代。

 1 #include <omp.h>
 2 #include <iostream>
 3 
 4 int main() {
 5 
 6     const int task_num = 10;
 7 
 8 #pragma omp parallel for num_threads(2) schedule(static, 2)
 9     for (int i = 0; i < task_num; ++ i) {
10         std::cout << "i = " << i << " thread_id = " << omp_get_thread_num() << std::endl;
11     }
12 
13     return 0;
14 }

运行结果和地方稍有例外:

i = 2 thread_id = 1
i = 0 thread_id = 0
i = 3 thread_id = 1
i = 6 thread_id = 1
i = 7 thread_id = 1
i = 1 thread_id = 0
i = 4 thread_id = 0
i = 5 thread_id = 0
i = 8 thread_id = 0
i = 9 thread_id = 0

能够见见,接二连三的2个职分会被分配到同二个线程。0、1给线程0,2、3给线程1,4、5给线程0,6、7给线程1。。。

static是多个百般精短的国策,但同不时候会带给一些主题素材。比方当义务的执行时间差距相当大的时候,由于OpenMP的fork/join的建制,速度快的线程必得等待速度慢的线程,即使恰恰分配的特别不创造的话(耗时的天职聚集在了某三个线程),别的的线程大概会等待较长的大运。那显著不实惠我们丰富利用多核实资金源。

openmp在多重循环内的轻便利用及其详明

是因为项目供给,在三重循环内参与了并行总括,但出于只好在内层循环步入,而内层循环独有32维度,因而进程提升的也就那么几纳秒。 在这 不再将代码贴出! 以下是转发的外人博客中的详细疏解,很正确!   …

  • 图片 8
  • Allyli0022
  • 2016-09-29 15:44
  • 3189

2、dynamic(动态调解)

动态调节会依照运转时的线程状态来支配下一回的迭代。当八个线程试行完自个儿的职分之后,会再去提取职分。不安装size的话,一个线程二遍会分配一个职务,当实行完了,会再领取一个任务。借使设置了size,线程则一遍领取size个职务。

dynamic是小喵最爱的情势!是因为它和专门的职业的劳动者消费者格局超近似。这里生产者暗中同意一回性临蓐有所的任务,然后各类线程都以三个客商,当自个儿试行完了,会再一次去提取任务。那样,职责的分红十字会愈发的有弹性,越来越好的适应了职责时间不风流倜傥的景况。

上面也是三个小栗子,不采取size:

 1 #include <omp.h>
 2 #include <iostream>
 3 
 4 int main() {
 5 
 6     const int task_num = 10;
 7 
 8 #pragma omp parallel for num_threads(2) schedule(dynamic)
 9     for (int i = 0; i < task_num; ++ i) {
10         std::cout << "i = " << i << " thread_id = " << omp_get_thread_num() << std::endl;
11     }
12 
13     return 0;
14 }

运作结果:

i = 0 thread_id = 0
i = 1 thread_id = 1
i = 2 thread_id = 0
i = 3 thread_id = 0
i = 4 thread_id = 1
i = 5 thread_id = 1
i = 6 thread_id = 1
i = 7 thread_id = 1
i = 8 thread_id = 1
i = 9 thread_id = 1

能够看来职务的分配是不均匀的。

使用size之后:

 1 #include <omp.h>
 2 #include <iostream>
 3 
 4 int main() {
 5 
 6     const int task_num = 10;
 7 
 8 #pragma omp parallel for num_threads(2) schedule(dynamic, 2)
 9     for (int i = 0; i < task_num; ++ i) {
10         std::cout << "i = " << i << " thread_id = " << omp_get_thread_num() << std::endl;
11     }
12 
13     return 0;
14 
15 }

运营结果如下:

i = 0 thread_id = 0
i = 2 thread_id = 1
i = 3 thread_id = 1
i = 4 thread_id = 1
i = 5 thread_id = 1
i = 6 thread_id = 1
i = 7 thread_id = 1
i = 8 thread_id = 1
i = 9 thread_id = 1
i = 1 thread_id = 0

线程0先提取了职务0、1。线程1提取了2、3。线程1做完事后,又领取了4、5。。。

能够观察,每一趟的职务分配是以2个为单位的,分配的依次视运维时情状动态调节。

在C++中接受openmp实行多线程编制程序

注解:本文是依附Joel Yliluoma写的Guid into OpenMP:Easy multithreading programming for C++而写的,基本是比照本人的接头,用自身语言组…

  • 图片 9
  • acaiwlj
  • 2015-11-13 15:53
  • 3841

3、guided(启示式调整)

动用启迪式调整措施进行调解,每一遍分配给线程迭代次数不相同,起头比一点都不小,今后逐年减小。

size代表每一回分配的迭代次数的细小值,由于每一回分配的迭代次数会日益压缩,少到size时,将不再裁减。即使不知情size的分寸,那么默许size为1,即直接减低到1。具体行使哪大器晚成种启迪式算法,须求参照他事他说加以考察具体的编写翻译器和血脉相仿手册的消息。

openMP编制程序(上篇卡塔尔之指令和锁

parallel : #include “omp.h” //openmp的头文件

#include “stdio.h” #define NUM_THREADS 4 int main() {…

  • 图片 10
  • g425680992
  • 2017-04-19 21:43
  • 145

4、runtime

runtime调用,实际不是二个确实调治方式。它是依赖景况变量的OMP_SCHEDULE来鲜明调解情势。最后还是是上述三种办法之一。具体用法能够查阅相关文书档案。

OpenMP 之for指令并行求和(学习笔记)

OpenMP 并行求和相互区域方法 开启三个并行线程程序如下:

  • 图片 11
  • XX_123_1_RJ
  • 2014-09-10 11:45
  • 997

六、叁个常用的设计方式

在做了前5个部分的选配之后,相信喵粉们早就开首调节了OpenMP的多少个基本的学问。那么,今后就起来讲我们最要害的有的——小喵最常用的多个设计情势。

 

尤为重要流程如下:

<1>初始化:
1,定义线程数为thread_num
2,定义平均每种线程上的天职位数量为task_per_thread
3,初叶化微机对象(handle_arr),大小为thread_num
4,开端化职责空间(task_arr),大小为thread_num * task_per_thread
5,伊始化结果空间(result_arr),大小为thread_num * task_per_thread

<2>读取职务(串行):
1,读取thread_num * task_per_thread个任务,存入task_arr。
2,记录读取职务的数目task_num(task_num <= thread_num * task_per_thread)

<3>职务管理(并行):
1,任务的task_id正是for循环的下标
2,通过omp_get_thread_num获取当前的线程id,依照线程id查找微处理器对象。
3,使用Computer管理定义的task_id对应的职务task_arr[task_id]
4,将试行结果存入result_arr[task_id]的位置

<4>结果管理(串行):
根据task_num,处理完result_arr中的结果。

<5>程序状态判别
判断task_num是不是等于thread_num * task_per_thread。
若是相等,说明任务队列未有施行完,继续<2>伊始实施。
借使不对等,则证实义务队列全体甩卖完,程序实践截止<6>。

<6>enjoy your programming

 

让大家来一步一步的掌握那几个格局。

<1>初始化:

此间最首要产生都部队分初步化的行事。

1)thread_num和task_per_thread

能够见到,这里开始化了七个参数。那么为何需求thread_num和task_per_thread那三个参数呢?

为了越来越好的施用和操纵财富。

听别人讲机器的两样,我们能够和谐安装须求展开的线程数,这正是thread_num。

反派汪:作者感到你说的有标题。大家在前后相继中明显能够行使omp_get_num_procs获取机器的富有的计算机的数据,然后就启用这么多的线程的话,不就能够最大限度的采用具备的总括本事了吗?

喵座:并非如此。假设服务器的微处理机数目为40,遵照你的思路,则会启用叁16个线程。那样一是会引致其余人不能经常的干活,二是当服务器原来就有其余的次序在run的时候,你的三十多个线程亦不能很好的做事。不比自个儿在运维在此之前安装一下亟需的测算能源数,会更利于一点。

那么为什么我们须求设置那一个task_per_thread呢?

因为能源是零星的。

考虑到最便捷的行事章程,就是让具有的线程不间断的办事。比方三遍性读完全数的职务列表,然后利用dynamic做完全数的天职。那样在任务做完在此以前,各个线程都会无间断的职业。

天时地利是两全的,现实是残忍的。就算职务特别多,例如小喵须求管理的200w条数据。很难二次性全部载入内部存款和储蓄器。並且,固然那样做了,也必需得职责总体做完,技能得到周转结果,时效性非常差。

那么大家不安装thask_per_thread不行呢?或然就把那个设置成1。每一趟就读取线程数相像的任务数,这样代码编写不该更简约吗?

这儿,让大家想起一下OpenMP的调治机制。要是每一趟只读取thread_num这么多的个任务数,那么每一回并行计算的时候,各种线程都会分配到一个职务。那么总的耗费时间将成为最慢的职分的实施时间。

举个大致的例证,比方有拾二个职责,耗时为2,1,2,1,2,1,2,1,2,1,2,1。大家应用2个线程。那么每管理2个任务,耗费时间都以2。总时间是12。

假诺大家每6个协同实行,也是利用2个线程。需求的总时间会化为了10。

施行进度看下图:

图片 12

能够使用task_per_task那些安顿,每一次管理thread_num * task_per_task个义务以来,可以更加好了采纳多核的财富。(task_per_task设得越大,讲道理效果应该越好。小喵自身爱怜设成10或20)

另一个利润是,当大家管理完这么些任务之后,可以至时将结果写入结果文件。

2)微处理机对象:

那是可选的。大家在事实上管理职责的时候,临时候会动用到部分优质的财富,并且必需确定保证这个财富是独占的(比方互连网通信的套接字,文件对象,或是线程不安全的局地实例的对象)。最简易连忙的章程正是为各类线程都初步化一个要好的微电脑(或是财富)对象。那样在其实管理的时候,每一个线程能够依赖本人的线程id找到自个儿的Computer,从而避免了八线程中的各类主题材料。

3)task_arr和result_arr

那七个空中是用来寄放每一趟并行管理的任务和结果的。大小自然和每趟并行的职责数(thread_num * task_per_thread)相等。考虑到每一次并行都足以复用那么些空中,所以提前报名好丰硕的半空中能够拉长运维功能。

<2>读取任务:

我们平时会将义务的剧情保留在文书中。而文件的读取是不可能相互的。因而大家供给提前按串行的方法将职务读取到职责队列task_arr中。每一回读取thread_num * task_per_thread个。考虑到职务总量大概不是thread_num * task_per_thread的整数倍,因而最后三遍读取的任务数会稍小一些。大家将每一趟读取的职务数记录下来,命名称叫task_num。

<3>任务管理:

这边正是我们适逢其时学习到的OpenMP的发挥专长。

日常性的写法是:

1 #pragma omp parallel for num_threads(thread_num) schedule(dynamic)
2 for (int task_idx = 0; task_idx < task_num; ++ task_idx) {
3     int thread_id = omp_get_thread_num();                      // 获取当前的线程id
4     handle_type handle = handle_arr[thread_id];                // 根据线程id,获取处理器
5     result_type result = handle->process(task_arr[task_idx]);  // 处理指定的任务
6     result_arr[task_idx] = result;                             // 在指定位置写回执行的结果
7 }

收获当前的线程号,然后拿走计算机,然后管理相应的天职,并将结果寄放进对应的职位。

小心,线程之间是单身的,不能够读写同叁个线程不安全的财富。并且在互相区域不保证别的的线程间的各个。

那般,我们就会平平安安且急忙的施行完每一次的职分了。

<4>结果管理:

那豆蔻梢头部分可怜轻巧易行,因为职责的结果已经按顺序存进了result_arr中,有效的result是前task_num个,之后想怎么处理都以喵粉本人的业务了。

<5>程序状态判别:

正如我们在<2>中提及的,大家每一趟管理一堆职责,最后的一堆义务的个数将不是thread_num * task_per_thread这么多。因而必要与task_num相比一下。假若相等,就大概是大家还尚未拍卖完,回到<2>继续施行。要是不等于,那就印证大家管理完了具有的天职了!你可以坐下来喝杯caffe,然后enjoy八线程带给的快感了。

 

聊到底,附上叁个简洁明了的demo。使用二十四线程,从文本上读取图片的list,读取图片的抑扬顿挫,并将结果存入贰个新的公文中。

 1 #include <opencv2/opencv.hpp>
 2 #include <fstream>
 3 #include <iostream>
 4 #include <string>
 5 
 6 typedef struct {
 7     int width;
 8     int height;
 9 } Size;
10 
11 int main(int argc, char **argv) {
12 
13     if (argc < 3) {
14         std::cerr << "usage: get_size.bin input_list output_list"
15             " [thread_num] [task_per_thread]" << std::endl;
16             return 1;
17     }
18     const int thread_num = (argc > 3) ? atoi(argv[3]):1;
19     const int task_per_thread = (argc > 4) ? atoi(argv[4]): 10;
20 
21     const int total_task = thread_num * task_per_thread;
22 
23     std::string image_name_arr[total_task];    // task arr
24     Size image_size_arr[total_task]; // result arr
25 
26     std::ifstream is(argv[1]);
27     std::ofstream os(argv[2]);
28 
29     int count = 0;
30 
31     while (1) {
32 
33         // 读取任务
34         int task_num = 0;
35         for (int task_idx = 0; task_idx < total_task; ++ task_idx) {
36             if (!(is >> image_name_arr[task_idx])) break;
37             ++ task_num;
38             ++ count;
39         }
40 
41         // 处理任务
42 #pragma omp parallel for num_threads(thread_num) schedule(dynamic)
43         for (int task_idx = 0; task_idx < task_num; ++ task_idx) {
44 
45             cv::Mat image = cv::imread(image_name_arr[task_idx]);
46             image_size_arr[task_idx].width = image.cols;
47             image_size_arr[task_idx].height = image.rows;
48 
49         }
50 
51         std::cout << "process #" << count << std::endl;
52 
53         // 处理结果
54         for (int task_idx = 0; task_idx < task_num; ++ task_idx) {
55             os << image_name_arr[task_idx] << " " 
56                 << image_size_arr[task_idx].width << " "
57                 << image_size_arr[task_idx].height << "n";
58         }
59 
60         // 状态判断
61         if (task_num != total_task) break;
62 
63     }
64     return 0;
65 }

编写翻译和试行:

g++ get_image_size_with_omp.cpp -o get_image_size_with_omp -fopenmp -I/path/to/opencv/include -L/path/to/opencv/lib -lopencv_core -lopencv_highgui
./get_image_size_with_omp /path/to/image_list /path/to/save/result 2 20

怎么样,使用这种格局来兑现轻便的八线程程序是还是不是很简短?

 

若果你以为本文对你有帮助,那请小喵喝杯茶啊O(∩_∩)O

图片 13

转发请注明出处~

 

OpenMP5.0的新特点Task指令根底

从OpenDVD.0发端,OpenMP扩充了task指令,那是Openmp5.0中最激动人心的叁个新特色。 本文的”术语“大大多是依靠个人了然用词,不保障用词正确性。 (1)task底工Ope…

  • 图片 14
  • gengshenghong
  • 2011-11-23 23:22
  • 3150

OpenMP 参考(子句)

原文:

  • 图片 15
  • saga1979
  • 2011-03-30 09:51
  • 2523

OpenMP 参谋 (同步布局)

原文:

  • 图片 16
  • saga1979
  • 2011-03-29 09:42
  • 4479

图片 17

MPI和OPENMP混合编制程序详细明白

  • 2016-12-21 16:38
  • 993KB
  • 下载

OpenMP并路程序设计——for循环并行化详整

在C/C++中使用OpenMP优化代码方便又简便,代码中需求并行管理的一再是部分比较耗时的for循环,所以最首要介绍一下OpenMP中for循环的采取。个人认为只要通晓了文中讲的这么些就足足了,假诺想要学…

  • 图片 18
  • zhongkejingwang
  • 2014-10-22 18:12
  • 7766