OpenMP并行计算
创始人
2024-06-02 23:02:16
0

1. OpenMP简介

  • 通过多线程实现并行
  • 开放式的多处理框架 Open Multi-Process
  • 统一内存访问 : 多个CPU共享同一片内存,pthread/OpenMP在CPU上执行,属于统一内存访问
  • 非统一内存访问: 每个CPU有单独的Memory, 如MPI,通过总线通信的方式获取内存信息

OpenMP与PThread

  • pthread需要明确指定每个线程的行为,openmp只需简单的生命代码段需要并行即可
  • pthread依赖pthreads库,能被任意C编译器使用,openmp依赖openmp库,还依赖编译器支持某些特定操作
  • pthread可通过编写代码明确线程执行的过程,而openmp难以对底层的线程交互进行编程

Fork与Join

  • Fork: 由主线程创建出一系列并行化执行的子线程(派生)
  • Join: 多个线程完成工作之后,进行同步与终止,回到主线程执行(合并)

2. OpenMP使用

  • OpenMP提供基于指令的共享内存API
  • 编译器需要支持pragma指令提示的语句编译
  • 在系统中加入预处理指令一般是用来允许不符合C语言基本规划的行为

OpenMP parallel 指定并发线程数目

  • 编译器指令: #pragma omp parallel num_threads(num)
#include void test()
{int num = omp_get_thred_num();  // 获取线程是第几个int thrNum = omp_get_num_threads(); //获取线程总数// 打印当前线程是omp诸多线程中的哪一个
}int main()
{
#pragma omp parallel num_threads(4)test();
return 0;
}

OpenMP for

  • 编译器指令: #pragma omp parallel for
  • 指定指令后的for循环语句,将使用并行的方式执行,for语句需要满足:
    (1)循环的迭代器必须是可计算的,在循环前需要确定迭代的次数
    (2)循环代码块中不能包含break、return、exit
    (3)循环语句中不能使用goto跳出循环之外
    (4)迭代器只能被for语句中的增量表达式所修改
#pragma omp parallel for num_threads(4)for(int i = 0; i < 1000; ++i){if(i == 400){// 打印在哪个线程中执行}}
  • 数据依赖性: 循环中的计算依赖之前迭代计算的结果
    (1)编译器不检查被parallel for指令并行化的循环所包含的迭代间的依赖关系
    (2)一个或更多迭代的结果依赖其他迭代的循环,一般不能被正确的并行化
// 斐波那契数列案例

OpenMP Private Variables

  • OpenMP能共享进程中作用域范围内的变量,也可指定parallel块中能够访问该变量的线程集合
  • 能够被线程组中所有的线程访问的变量拥有共享作用域,而一个只能被单个线程访问的变量拥有私有作用域
  • Private在pragma指令中是一个可选附加的选项,它能直接高速编译器去将共享变量作为每个线程中的私有变量 #pragma omp … private()
  • Private的说明
    (1)每一个线程都是拥有独立的该变量的副本,不会共享原来的初始值
    (2)变量被定义为私有变量后,其他线程均不能访问某一个线程的私有变量
    (3)所有线程都不会使用先前变量的定义
    (4)所有线程均不能改变私有变量赋值
    (5)在循环的出入口均不会进行定义

*FirstPrivate的说明 #pragma omp parallel for firstprivate(var)
(1)告诉编译器私有变量在第一个循环会继承共享变量的值
(2)这个私有变量只会在每个线程的第一个循环继承原始的值,不会再每个循环中继承
(3)使用方法与Private一致

  • 变量的拷贝
    (1)变量是基础数据类型,如Int,double等,会将数据进行直接的拷贝
    (2)如果变量是一个数组,会分配数组大小的私有内存后,拷贝数组内容
    (3)如果变量是指针,会将地址指向的地址拷贝过去,指向相同的堆内容
    (4)如果变量是一个类的实例,会调用对应的构造函数构造一个私有的变量

  • LastPrivate的说明 #pragma omp parallel for lastprivate(var)
    (1)告诉编译器私有变量会在最后一个循环出去的时候,用私有变量的值替换掉共享变量的值

OpenMP Section

for: 在代码段中一部分代码再次分成多个子线程执行

single : 代码段中指定一部分代码仅由单个线程执行

master: 代码段中指定一部分代码仅由主线程执行

Section选项

  • sections在封闭代码的指定部分中,由线程组进行分配任务
  • 每个独立的section都需要在sections里面
  • 每个section都是被一个section执行
  • 不同的section可能执行不同的任务
  • 如果一个线程够快,它可能执行多个section

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...