并行程序设计之OpenMP

目录

KI

编程模型

OpenMP简介

openmp基本语法

parallel region

       关于并行区域中的变量:

        关于变量的类型确定

        关于并行变量的其他情况声明

        并行区域的其他子句

 Work sharing

        相关指导语句

        调度策略 

 Exclusive Execution

        指导语句

Synchronization

        指导语句

Nested Parallelism

openmp程序接口

环境变量


KI

        随便写写,最近学并行与分布式计算课程对openmp的相关知识和使用有点混乱。


编程模型

        在计算领域,并行编程模型是并行计算机体系架构的一种抽象,它便于编程人员在程序中编写算法及其组合。


OpenMP简介

        OpenMP是一套支持跨平台共享内存方式的多线程并发的编程API,基于Fork-Join模型。

        基本逻辑:一个openmp程序是由一个进程发起的,起初该进程只有一个主线程,在使用并行指导语句创建并行区域,进程fork出多个轻量级的线程,每个线程都执行并行区域中的代码。并行区域结束后,只有主线程继续执行。

        在并行区域内,变量分为两种:私有变量(存放于独立的线程的栈中),共享变量(定义与共享内存空间,所以线程可访问)。


openmp基本语法

parallel region

       在并行区域中 默认变量是共享的,所有的线程执行同样的代码,并且结尾有显示的同步操作。

       关于并行区域中的变量:
  1. private,如果一个变量是private的,则每个线程都有自己私有变量的本地副本。(可以理解为openmp赋值了这个变量,并将本地副本分配给每一个线程,保存在各自线程的栈中)
  2. share,如果一个变量是share的,则存在一个实例,在所有线程中共享。(针对共享变量,需要考虑数据竞争的问题)
        关于变量的类型确定
  • 在并行区域之外声明的变量没有特别指定默认是共享的。
  • 循环迭代的变量默认是私有的;并行区域之内声明的变量默认为私有的。
  • 使用shared子句声明变量为共享的。
  • 使用private子句声明变量为私有的。
  • default(shared):当使用这个指令时,它会告诉OpenMP编译器,除非明确另行指定,所有在并行区域内定义的变量都应该被视为共享的。默认情况下,如果没有明确指定变量的共享属性,OpenMP通常会将在并行区域内定义的变量标记为共享变量。使用 default(shared) 指令可以明确指定这一点,以确保在并行区域内的变量都被视为共享变量。
  • default(none):表示必须显式指定所有共享变量的数据属性,否则会报错,除非变量有明确的属性定义(比如循环并行区域的循环迭代变量只能是私有的)
        关于并行变量的其他情况声明
  • 针对于迭代变量,就算声明为shared,在并行for语句里也默认为私有变量。
  • 对于共享变量,存在数据竞争问题,对共享变量进行写的时候,无法确定线程何时写,会不会存在两个线程以上同时写的情况。
  • 如果变量的状态是 PRIVATE ,那么它会在线程的stack 中。它的值在进入并行区域时是不确定的。
        并行区域的其他子句
  • firsprivate使私有变量初始化为并行区域开始时的数值。如:#pragma omp parallel firstprivate(a),a继承它在并行区域外的值       
  • lastprivate 使变量私有,同时将它赋值为循环最后一次迭代的数值
  • reduction 每个线程有 private 的副本, reduction 为共享变量在每个线程创建私有副本,变量会将操作作用在所有的私有共享变量(私有副本)上,最终结果写回全局共享变量。(理解为:将共享变量变为私有变量,每个线程的私有变量完成其任务后返回,使用reduction指定的操作累计到原全局共享变量)

 Work sharing

        使用OpenMP创建并行区域,程序员需要显式地对任务(work)和数据进行划分,来保证没有数据竞争(data race

        相关指导语句
  • for ,如:#pragma omp parallel for。(使用for后,在并行区域,并不是所有的线程都执行一次后面的for语句,而是将for语句按调度策略分配到不同的线程,并行执行)
  • for 语句后会有隐式的 barrier ,除非有语句 NOWAIT

        调度策略 

        语句形式:#pragma omp for schedule(static|dynamic|guided)

  • Schedule(static, chunk_size ) 循环迭代以 chunk_size 分为不同的组( chunk ),各组以循环的方式分配给不同的线程如果chunk_size没有指定,则默认使各 chunk 尽可能均衡
  • Schedule(dynamic, chunk_size ) 循环迭代以 chunk_size 为单位分配给各线程。各线程完成对应的chunk 后申请执行新的 chunk
  • Schedule(guided, chunk_size ) 调度是一种采用指导性的启发式自调度方法。开始时每个线程会分配到较大的迭代块,之后分配到的迭代块会逐渐递减。迭代块的大小会按指数级下降到指定的chunk_size 大小

 Exclusive Execution

        指导语句
  • SINGLE语句使相应的并行区域中只有一个线程在执行;如果没有NOWAIT语句,其他的线程等待直到SINGLE语句对应的区域执行完成。如:#pragma omp single nowait
  • single语句配合copyprivate使用可以将该变量的值广播到其他线程。如:#pragma omp single copyprivate(a)
  • MASTER 语句创建的区域由 master线程执行;MASTER区域结尾没有隐式同步。如: #pragma omp master

Synchronization

        PARALLEL和 FOR 创建区域结束时都有隐式同步 barrier 可以通过 NOWAIT 语句绕过。
        指导语句
  • 通过barrier语句来显示同步,即需要所以线程都执行到这里。如:#pragma omp barrier
  • ATOMIC 语句能够保证内存中的共享存储位置在某时刻只被同一线程修改(原子操作)
  • CRITICAL 语句保证程序的特定区域一个时刻只有一个线程执行

Nested Parallelism

        嵌套并行指在一个并行区域中嵌套另一个并行区域。

openmp程序接口

omp_set_num_threads(): 设定并行区域中的线程数目
omp_get_num_threads(): 返回并行区域中的线程数目
omp_get_thread_num():返回目前组中的当前线程的 ID
omp_get_max_threads():返回并行区域中可以创建的最大线程数目
omp_in_parallel(): 判断是否在并行区域中
omp_set_nested(): 设置并行区域嵌套
omp_get_nested():判断是否允许嵌套

环境变量

OMP_NUM_THREADS: 并行区域中最大的线程数目
OMP_NESTED:是否允许 OpenMP 嵌套并行

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值