section语句是用在sections语句里用来将sections语句里的代码划分成几个不同的段

#pragma omp [parallel] sections [子句]
{
   #pragma omp section
   {
            代码块
   } 
}
     当存在可选参数#pragma omp parallel sections时,块中的代码section才会并行处理,而#pragma omp  sections是串行的程序。详见下面的代码:
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#include <unistd.h>
int main()
{printf("parent threadid:%d\n",omp_get_thread_num());#pragma omp  sections{#pragma omp section{printf("section 0,threadid=%d\n",omp_get_thread_num());sleep(1);}#pragma omp section{printf("section 1,threadid=%d\n",omp_get_thread_num());//sleep(1);
     }#pragma omp section{printf("section 2,threadid=%d\n",omp_get_thread_num());sleep(1);}}#pragma omp parallel sections{#pragma omp section{printf("section 3,threadid=%d\n",omp_get_thread_num());sleep(1);}#pragma omp section{printf("section 4,threadid=%d\n",omp_get_thread_num());sleep(1);}#pragma omp section{printf("section 5,threadid=%d\n",omp_get_thread_num());sleep(1);}}return 0;
}

输出结果为:
parent threadid:0section 0,threadid=0section 1,threadid=0section 2,threadid=0section 3,threadid=0section 4,threadid=2section 5,threadid=1

针对上面的代码,首先应该明确下面几点:

1. sections之间是串行的。主线程把section0~2执行完之后才执行的第二个sections。

2.没有加parallel的sections里面的section是串行的,为此我专门sleep了一秒,结果显示0~2都是主线程做的。

3.第二个sections里面是并行的,进程编号分别为0,2,1。

问题来了,第二部分的0是不是主线程呢?还是第二部分新开的一个线程?为此需要真正输出每个线程在内核中的线程编号:

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>int main()
{printf("pid:%d,tid=%ld\n",getpid(),syscall(SYS_gettid));#pragma omp sections{#pragma omp section{printf("section 0,tid=%ld\n",syscall(SYS_gettid));sleep(1);}#pragma omp section{printf("section 1,tid=%ld\n",syscall(SYS_gettid));//sleep(1);
     }#pragma omp section{printf("section 2,tid=%ld\n",syscall(SYS_gettid));sleep(1);}}#pragma omp parallel sections{#pragma omp section{printf("section 3,tid=%ld\n",syscall(SYS_gettid));sleep(1);}#pragma omp section{printf("section 4,tid=%ld\n",syscall(SYS_gettid));sleep(1);}#pragma omp section{printf("section 5,tid=%ld\n",syscall(SYS_gettid));sleep(1);}}return 0;
}

输出结果:

pid:7619,tid=7619section 0,tid=7619section 1,tid=7619section 2,tid=7619section 5,tid=7621section 4,tid=7619section 3,tid=7620

从结果中可以看出以下几点:

  1. OpenMP上说当程序执行到第二个sections是并行的,主线程是休眠的,一直等所有的子线程都执行完毕之后才唤醒,可是在第二个sections中有个线程id和主线程id一致?其实是不一致的,首先从两者的类型上来看,线程编号是long int的,而进程是int的,数字一致并不能说两者相同。另外一方面,在linuxthreads时代,线程称为轻量级进程(LWP),也就是每个线程就是个进程,每个线程(进程)ID不同;而从2.4.10后,采用NPTL(Native Posix Thread Library)的线程库, 各个线程同样是通过fork实现的,并且具备同一个父进程。
  2. 主进程id为7619,同时它又有个线程id也是7619,又一次证明在linux中线程进程差别不大。
  3. 猜测主线程并不是休眠,而是将原先的上下文保存,然后自身也作为并行的一份子进行并行程序的执行,当并行程序完成之后,再回复原先的上下文信息。

下面是一个比较复杂的例子

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>int main()
{
#pragma omp parallel
{printf("pid:%d,tid=%ld\n",getpid(),syscall(SYS_gettid));#pragma omp sections{#pragma omp section{printf("section 0,tid=%ld\n",syscall(SYS_gettid));//sleep(1);
     }#pragma omp section{printf("section 1,tid=%ld\n",syscall(SYS_gettid));sleep(1);}#pragma omp section{printf("section 2,tid=%ld\n",syscall(SYS_gettid));sleep(1);}}#pragma omp sections{#pragma omp section{printf("section 3,tid=%ld\n",syscall(SYS_gettid));sleep(1);}#pragma omp section{printf("section 4,tid=%ld\n",syscall(SYS_gettid));sleep(1);}#pragma omp section{printf("section 5,tid=%ld\n",syscall(SYS_gettid));sleep(1);}}
}return 0;
}

输出结果:

pid:7660,tid=7660
section 0,tid=7660
section 1,tid=7660
pid:7660,tid=7662
section 2,tid=7662
pid:7660,tid=7663
pid:7660,tid=7661
section 3,tid=7660
section 5,tid=7661
section 4,tid=7662

#pragma omp parallel里面的代码是并行处理的,但是并不意味着代码要执行N次(其中N为核数),sections之间是串行的,而并行的实际部分是sections内部的代码。当线程7660在处理0,1时,因为section1休眠1s,所以section2在此期间会被新的线程进行处理。第一个sections真正处理完成之后,第二个sections才开始并行处理。

另外值得注意的是,printf并不是并行的函数,它是将结果输出到控制台中,可是控制台资源并不是共享的。当被某个线程占用之后,其余的线程只能等待,拿输出的结果为例。对于#pragma omp parallel里面的代码是并行的,可是线程之间还是有先后的次序的,次序和线程的创建时间有关,对于线程7660来说,本身就已经存在了,所以首先获得printf函数,而直到它执行section0里面的printf时,其他的线程还没有创建完毕,接着是setion1里面的printf,即使是这个时候有其他的线程创建完成了,也只能等待,在section1中,sleep了1秒钟,printf函数被新的线程使用,下面也如此。

转载于:https://www.cnblogs.com/wzyj/p/4501348.html

OpenMp之sections用法相关推荐

  1. OpenMP Sections

    // 工作分区(sections)是只利用OpenMP的sections编译指导语句,将用section// 语句指定的内部代码,划分成多个工作区分配给线程组中的各个线程,// 不同的section由 ...

  2. OpenMP学习笔记1

    OpenMP学习笔记1 介绍 在C/C++中,OpenMP可以通过使用预处理指令来让程序并行化.OpenMP指令使用的格式为: #pragma omp 指令 [子句[子句]-] fork/join并行 ...

  3. OpenMP并行编程

    1.总览   OpenMP(Open Multi-Processing)是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层 ...

  4. 并行计算:openMP(一)—— parallel,for,sections指令的用法

    一.简介 OpenMP介绍 在C/C++中,OpenMP可以通过使用预处理指令来让程序并行化.OpenMP指令使用的格式为: #pragma omp 指令 [子句[子句]-] 下面是一个最简单的Ope ...

  5. OpenMP用法大全

    OpenMP基本概念 OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的 ...

  6. OpenMP: sections分段并行

    除了循环结构可以进行并行之外,还可以进行分段并行(parallel section).迄今为止,每谈到如何去并行一个程序时,我们主要关心的是在同一时间将一个任务划分成多个然后用多线程去完成.然而,如果 ...

  7. OpenMP入门及基本用法

    1.OpenMP的基本概念 OpenMP 是 Open MultiProcessing 的缩写.OpenMP 并不是一个简单的函数库,而是一个诸多编译器支持的框架,是一种用于共享内存并行系统的多线程程 ...

  8. OpenMP编程(4)—sections、single指令

    1. sections指令 1.1 sections指令用途 SECTIONS指令用于非迭代的多线程共享区.它指定各个section代码段分配给一组线程中部分线程. 多个独立的section指令嵌套在 ...

  9. OpenMP学习笔记之常用指令parallel/sections/critical 其余待续

    主要涵盖以下指令: parallel parallel for sections critical single flush atomic master ordered threadprivate p ...

最新文章

  1. 通过CH340G驱动的Nano ATMEAG328P驱动板初步测试
  2. 修改github用户名
  3. wordpress漏洞上传php文件夹,WordPress Asset-Manager PHP文件上传漏洞
  4. 课时85.层叠性(掌握)
  5. 九度OJ #1437 To Fill or Not to Fil
  6. 【数学】和【物理】的差别
  7. 02、django中的上下文
  8. 不稳定学习器适合做基分类器_分类稳定性
  9. Spring Boot————默认缓存应用及原理
  10. Ubuntu12.04 apt-get 安装mysql
  11. [转]xshell使用技巧
  12. 基于VAR模型出国留学人数增加的影响因素分析
  13. html怎么消除打印的进纸,关于打印机进纸故障的原因分析和解决方法(一)
  14. MacBook Pro打开前置摄像头
  15. 微信小程序中的onLoad
  16. 今日行业报告更新10月25日
  17. 开源 | Objective-C Swift 最轻量级 Hook 方案
  18. 使用Scratch制作项目《弹珠游戏》
  19. 甜度超标,程序员的尿竟是甜的,但更可怕的却是...
  20. JavaWeb面试题2020(15题)

热门文章

  1. 江西宜春三名公务员擅自驾公车钓鱼被通报-公车钓鱼-公务员-公车
  2. 十年磨一剑,剑出荡魑魅
  3. 可编程逻辑器件之按键消抖实验
  4. 浅析提高倾斜摄影超大场景的三维模型轻量化的数据质量关键技术
  5. qrcode插件生成二维码并下载
  6. vuejs的学习笔记
  7. HDU 6148 Valley Numer
  8. 第25章 JDBC核心技术第3节
  9. 大数据繁荣生态圈组件之实时大数据Druid小传(三)Druid入门实操
  10. pug在vue中的序列写法