OpenMp之sections用法

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函数被新的线程使用,下面也如此。

时间: 2024-10-12 20:10:27

OpenMp之sections用法的相关文章

OpenMP初步(英文)

Beginning OpenMP OpenMP provides a straight-forward interface to write software that can use multiple cores of a computer. Using OpenMP you can write code that uses all of the cores in a multicore computer, and that will run faster as more cores beco

OpenMP并行编程应用—加速OpenCV图像拼接算法

OpenMP是一种应用于多处理器程序设计的并行编程处理方案,它提供了对于并行编程的高层抽象.仅仅须要在程序中加入简单的指令,就能够编写高效的并行程序,而不用关心详细的并行实现细节.减少了并行编程的难度和复杂度.也正由于OpenMP的简单易用性,它并不适合于须要复杂的线程间同步和相互排斥的场合. OpenCV中使用Sift或者Surf特征进行图像拼接的算法.须要分别对两幅或多幅图像进行特征提取和特征描写叙述,之后再进行图像特征点的配对.图像变换等操作.不同图像的特征提取和描写叙述的工作是整个过程中

OpenMP用法大全

OpenMP基本概念OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并行程序设计.编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度.当编译器不支持OpenMP时,程序会退化成普通(串行)程序.程序中已有的OpenMP指令不会影响程序的正常编译运行.在VS中启用OpenMP很简单,很多主流的编译环境都内置了Open

OpenMp实现并行化

前言 昨天,往arm上移植opencv程序,发现运行速度很慢.观察资源监视器发现只有一个核处于高负荷(总共4核),遂考虑到需要多核计算.OpenMp和MPI是常用并行计算库,OpenMP相对简单适合单机多核多线程,MPI适合集群,但复杂. OpenMp是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多处理器程序设计的一套指导性的编译处理方案(Compiler Directive).OpenMP支持的编程语言包括C语言.C++

OpenMP for Android初学记录

1. 资料整理与收集 1.1 国外资料 (1). Wiki上的介绍:http://en.wikipedia.org/wiki/OpenMP (2). OpenMP教程: http://www.llnl.gov/computing/tutorials/openMP (3). 并行计算介绍:https://computing.llnl.gov/tutorials/parallel_comp/ (4). 官方指定参考书:<Using OpenMP>CSDN上的下载链接 1.2 国内资料 (1). O

如何利用VS的代码优化和openmp并行计算提高程序运行速度

以前利用多线程为拥有较大量计算的程序提速过,但也深知多线程的同步和程序的调试是一大坑,最近为实验室的项目学习了一点VS下优化代码的设置以及利用openmp加速运算,都是些很基本的提升程序速度的方法,只要稍微修改下代码和设置,就可使程序加速.配合多线程,经过clock()函数验证,我的程序运行可提高60%的速度,详细如下: 代码优化: 属性->配置属性->C/C++->代码生成:启用增强指令集,可选用 流式处理 SIMD 扩展 2 (/arch:SSE2) (/arch:SSE2).流式处

并行计算之OpenMP

在上一篇文章中介绍了并行计算的基础概念,也顺便介绍了OpenMP. OpenMp提供了对于并行描述的高层抽象,降低了并行编程的难度和复杂度,这样程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节.对基于数据分集的多线程程序设计,OpenMP是一个很好的选择.同时,使用OpenMP也提供了更强的灵活性,可以较容易的适应不同的并行系统配置.线程粒度和负载平衡等是传统多线程程序设计中的难题,但在OpenMp中,OpenMp库从程序员手中接管了部分这两方面的工作.但是,作为高层抽象,OpenM

openMP的一点使用经验

最近在看多核编程.简单来说,由于现在电脑CPU一般都有两个核,4核与8核的CPU也逐渐走入了寻常百姓家,传统的单线程编程方式难以发挥多核CPU的强大功能,于是多核编程应运而生.按照我的理解,多核编程可以认为是对多线程编程做了一定程度的抽象,提供一些简单的API,使得用户不必花费太多精力来了解多线程的底层知识,从而提高编程效率.这两天关注的多核编程的工具包括openMP和TBB.按照目前网上的讨论,TBB风头要盖过openMP,比如openCV过去是使用openMP的,但从2.3版本开始抛弃ope

readelf用法小记

By francis_hao    Feb 14,2017 显示ELF文件的信息 用法概述 readelf和objdump类似,不过,readelf会显示更详细的信息,而且独立于BFD库,因此当BFD库出问题时readelf不会受影响. 选项解释 -d --dynamic 显示正文的动态部分,可用于显示程序依赖的动态库 -s --symbols --syms 显示符号表,包含但不限于 函数名 变量名-- -h --file-header 显示在文件开始处的ELF头信息,包含但不限于 魔数 大小端