并行程序设计-第五讲.openmp编程


第五讲 openmp

OpenMP并行模型

程序员视角

image-20221114104633837

执行模型

image-20221114104747893

编程环境配置

image-20221114104917033

image-20221114104938547

编程模型

image-20221114105212217

编译指示格式

  • 编译指示格式
    • #pragma omp directive_name[clause[clause]……]
  • 条件编译
    • image-20221114105619319
    • 如果使用的平台支持openmp则。。
    • 不支持的话就按照串行方式,保证结果正确
  • 大小写敏感
  • 使用库函数需要包含头文件

运行时库,查询函数

image-20221114105948585

并行区域结构

image-20221114110155127

hello world程序

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

void Hello(void);

int main(int argc,char* argv[]){
  int thread_count=strtol(argv[1],NULL,10);
  
  #pragma omp parallel num_threads(thread_count)
  Hello();
  
  return 0;
}




void Hello(void){
  int my_rank=omp_get_thread_num();
  int thread_count=omp_get_num_threads();
  
  print("Hello from thread %d of %d\n",my_rank,thread_count);
}

为防止编译器不支持openMP

image-20221114111804810

梯形积分法

image-20221114112046950

临界区指令

归约

并行循环

OpenMp数据并行:并行循环

image-20221114141348225

局限和语义

必须提前看到for循环就能看到有多少任务

带break、goto之类的不支持

不支持依赖的(例如斐波那契数列,每次计算都要用到前面的数)

image-20221114142008518

简单并行化循环的版本

image-20221114142232525

同步

openmp隐式同步

在要并行的语句前隐式的有开始并行和join之类的

image-20221114142437576

并行for指示的各种形式

数据依赖(中间跳过了一部分,只讲了下面的几个ppt,跳过p39、)

image-20221114142745626

image-20221114143132650

第一个存在数据依赖

第二个不存在依赖

  • 例子

    • image-20221114143408845

    • image-20221114143519896

    • 气泡排序(🌟)

      image-20221114143824119

      内层和外层哪个存在循环依赖??

      都存在

      外层:每次循环数组的顺序都发生了变化,下一次循环依赖上次循环的结果,存在循环依赖关系

      内层,每次都要比较a[i]和a[i+1],并要交换两者位置,存在循环依赖关系

    • 气泡排序内外层都存在依赖,怎么进行并行化

      • 解决方法
      • 第一轮奇数项和他的下一个比较,第二轮偶数项和她的下一个比较
      • 每一轮之间不存在依赖了
      • 串行的代码
        • image-20221114150929703
      • 并行代码
        • image-20221114150549415
        • 有什么问题
        • 每次大循环的时候频繁地创建线程以及销毁线程,耗费系统资源
        • 怎么改进?
        • 把创建线程拿到大循环外面
        • image-20221114150633942
        • 不用加parrallel_for啥的,因为不是对外循环并行化。只是现在外面生成线程,在执行内循环的时候在写pragma omp for,把任务分到线程上

循环调度

什么都不写的话默认static,最大块

image-20221114153015722

静态分配

image-20221114151337679

不指定的话默认为threads,指定的话变成循环分配,下面是制定了static(2)

在执行任务之前划分好,执行的时候

image-20221114151712217

动态分配

谁先执行好把剩下的最后一块给哪个线程

image-20221114151913079

guided动态划分

剩余任务数➗二倍的线程数

image-20221114152516458

更多属性

image-20221114152850597

局部性

image-20221114154109286

重用

===========中间跳过了

image-20221114154155141

image-20221114154240600

后面全都跳过了

任务并行


文章作者: zxn
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zxn !
  目录