OPENMP学习笔记(1)——简介,模型,运行

简介:

OpenMP的英文全称是Open Multiprocessing,一种应用程序接口(API,即Application Program Interface),是一种单进程多线程并行的实现和方法,也可以认为是共享存储结构上的一种编程模型,可用于共享内存并行系统的多线程程序设计的一套指导性注释(Compiler Directive)。
在链接可以到官网看5.0以及4.5版本的官方文档以及示例。

在项目程序已经完成好的情况下不需要大幅度的修改源代码,只需要加上专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMp时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。OpenMP提供的这种对于并行描述的高层抽象降低了并行编程的难度和复杂度,对基于数据分集的多线程程序设计,OpenMP是一个很好的选择。

OpenMP支持的语言包括C/C++、Fortran;而支持OpenMP的编译器VS、gcc、clang等都行。可移植性也很好:Unix/Linux和Windows

OpenMP缺点:
1:作为高层抽象,OpenMp并不适合需要复杂的线程间同步和互斥的场合;
2:另一个缺点是不能在非共享内存系统(如计算机集群)上使用。在这样的系统上,MPI使用较多

模型:

内存共享模型:OpenMP是专为多处理器/核,共享内存机器所设计的。底层架构可以是UMA和NUMA。即(Uniform Memory Access和Non-Uniform Memory Access)

注意:OpenMP并行性本身仅限于单个节点
在高性能计算(HPC)应用中,OpenMP与MPI相结合实现分布式内存并行。这通常被称为混合并行编程。
(1)OpenMP用于每个节点上的计算密集型工作。
(2)MPI用于实现节点之间的通信和数据共享。
这允许在集群的整个规模上实现并行性。

基于线程的并行化:
1)OpenMP程序通过使用线程来完成并行化;
2)线程是可由操作系统调度的最小处理单元,其特点是可以安排自主运行的子程序;
3)线程存在于单个进程的资源中,如果没有这个进程,那么线程也就不存在了;
4)通常,线程数与机器处理器/内核的数量相匹配,但是线程的实际使用也取决于具体的应用程序。
显式并行化:
1)OpenMP是一个显式的(而不是自动的)编程模型,为编程者提供了对并行化的完全控制;
2)并行化可以简单到仅仅为一段串行程序添加几条编译器指令
3)或者复杂到插入子程序,以建立多层次的并行机制、锁甚至嵌套锁。
Fork-Join模型

另一种图示:

openMP采用fork-join的执行模式。开始的时候只存在一个主线程,当需要进行并行计算的时候,派生出若干个分支线程来执行并行任务。当并行代码执行完成之后,分支线程会合,并把控制流程交给单独的主线程。

过程:
(1)所有的OpenMP程序都从一个单个进程——master thread开始。主线程串行执行,直到遇到第一个并行区域。
(2)Fork:主线程将创建一组并行线程。
(3)并行区域内的代码被用大括号包围起来,然后在多个并行线程上被并行执行。
(4)Join:当并行线程执行完成并行区域内的代码之后,它们进行同步并且自动结束,只剩下主线程。
(5)并行区域的数量以及并行线程的数量都可以是任意的

基于编译器指令
嵌套并行
动态线程
输入输出 (I/O)
内存模型:频繁更新(flush)

OpenMP API

OpenMP三类组件: OpenMP API包含三个不同的组件:
编译器指令(44个);
运行时库函数(35个);
环境变量(13个)。

编译器指令
编译制导指令以#pragma omp 开始,后边跟具体的功能指令,格式如:#pragma omp 指令[子句[,子句] …]。

API函数(运行时库函数)
除上述编译制导指令之外,OpenMP还提供了一组API函数用于控制并发线程的某些行为。
函数库链接

环境变量
OpenMP中定义一些环境变量,可以通过这些环境变量控制OpenMP程序的行为,常用的环境变量:
OMP_SCHEDULE:用于for循环并行化后的调度,它的值就是循环调度的类型;
OMP_NUM_THREADS:用于设置并行域中的线程数;
OMP_DYNAMIC:通过设定变量值,来确定是否允许动态设定并行域内的线程数;
OMP_NESTED:指出是否可以并行嵌套。

不同编译器需要使用的编译器标识
所有的LC编译器都需要你使用适当的编译器标识来“打开”OpenMP的编译选项。下面的表格给出了每种编译器需要使用的编译器标识。
常用:

编译器平台 编译器指令 openmp标识
GNU gcc -fopenmp
Clang clang -fopenmp

具体如下:

vs使用:

点击项目->属性,打开openmp支持,否则都是串行,显示Thread0!

简单例子

串行

#include<omp.h>
#include<iostream>
using namespace std;
int main()
{  cout<<"串行化程序"<<endl; double start = omp_get_wtime( );//获取起始时间  for(int i = 0; i < 100000000; i++) //100000000次的空循环{   }  double end = omp_get_wtime( );  cout<<"串行化程序计算耗时为:"<<end-start<<endl;  getchar(); return 0;
}


omp并行
要加上#include<omp.h> 的头文件

#include<omp.h>
#include<iostream>
using namespace std;
int main()
{  cout<<"并行化程序"<<endl; omp_set_num_threads(4); //设置线程的个数为4double start = omp_get_wtime( );//获取起始时间  #pragma omp parallel forfor(int i = 0; i < 100000000; i++) //100000000次的空循环{   }  double end = omp_get_wtime( );  cout<<"并行化程序计算耗时为:"<<end-start<<endl;  getchar(); return 0;
}


通过子句num_threads显式控制创建的线程数:

#include<iostream>
#include"omp.h"using namespace std;void main()
{
#pragma omp parallel num_threads(6){cout << "Test" << endl;}system("pause");
}


程序中显式定义了6个线程,所以parallel后的语句块分别被执行了6次。第二行的空行是由于每个线程都是独立运行的,在其中一个线程输出字符“Test”之后还没有来得及换行时,另一个线程直接输出了字符“Test”。

OpenMP效率提升以及不同线程数效率对比

#include<iostream>
#include"omp.h"using namespace std;void test()
{for (int i = 0; i < 80000; i++){}
}void main()
{float startTime = omp_get_wtime();//指定2个线程
#pragma omp parallel for num_threads(2)for (int i = 0; i < 80000; i++){test();}float endTime = omp_get_wtime();printf("指定 2 个线程,执行时间: %f\n", endTime - startTime);startTime = endTime;//指定4个线程
#pragma omp parallel for num_threads(4)for (int i = 0; i < 80000; i++){test();}endTime = omp_get_wtime();printf("指定 4 个线程,执行时间: %f\n", endTime - startTime);startTime = endTime;//指定8个线程
#pragma omp parallel for num_threads(8)for (int i = 0; i < 80000; i++){test();}endTime = omp_get_wtime();printf("指定 8 个线程,执行时间: %f\n", endTime - startTime);startTime = endTime;//指定12个线程
#pragma omp parallel for num_threads(12)for (int i = 0; i < 80000; i++){test();}endTime = omp_get_wtime();printf("指定 12 个线程,执行时间: %f\n", endTime - startTime);startTime = endTime;//不使用OpenMPfor (int i = 0; i < 80000; i++){test();}endTime = omp_get_wtime();printf("不使用OpenMP多线程,执行时间: %f\n", endTime - startTime);startTime = endTime;system("pause");
}


使用OpenMP优化后的程序执行时间是原来的1/4左右,并且并不是线程数使用越多效率越高,一般线程数达到4~8个的时候,不能简单通过提高线程数来进一步提高效率。

命令行编译

(测试为manjiaro,archlinux的一种)

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>int main()
{int nthreads, tid;/* Fork a team of threads giving them their own copies of variables */#pragma omp parallel private(nthreads, tid){/* Obtain thread number */tid = omp_get_thread_num();printf("Hello World from thread = %d\n", tid);/* Only master thread does this */if (tid == 0){nthreads = omp_get_num_threads();printf("Number of threads = %d\n", nthreads);}}  /* All threads join master thread and disband */return 0;
}

加上-fopenmp编译

g++ test.cpp -o test -fopenmp
gcc test.cpp -o test -fopenmp -lstdc++
//上述两种方式都可以
./test

OPENMP学习笔记(1)——简介,模型,运行相关推荐

  1. PCL学习笔记-PCL简介

    PCL(点云库)学习笔记 1.简介 点云数据的处理可以采用获得广泛应用的Point Cloud Library(点云库,PCL库). PCL库是一个最初发布于 2013年的开源c++库,它实现了大量点 ...

  2. OptiX资料学习笔记1——简介

    OptiX资料学习笔记1--简介 OptiX引擎的现状 目前有三种开源的API支持NVIDIA的光线追踪功能,分别为: DirectX Raytracing (DXR) DX的光线追踪API Vulk ...

  3. OpenMP学习笔记1

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

  4. 51单片机学习笔记1 简介及开发环境

    51单片机学习笔记1 简介及开发环境 一.51单片机 1. STC89C52单片机简介 2. 命名规则 3. 封装 (1)PDIP (2)LQFP (3)PLCC (4)PQFP 二.STC8051结 ...

  5. V-rep学习笔记:机器人模型创建2—添加关节

    下面接着之前经过简化并调整好视觉效果的模型继续工作流,为了使模型能受控制运动起来必须在合适的位置上添加相应的运动副/关节.一般情况下我们可以查阅手册或根据设计图纸获得这些关节的准确位置和姿态,知道这些 ...

  6. ArcGIS模型构建器案例学习笔记-字段处理模型集

    ArcGIS模型构建器案例学习笔记-字段处理模型集 联系方式:谢老师,135-4855-4328,xiexiaokui@qq.com 由四个子模型组成 子模型1:判断字段是否存在 方法:python工 ...

  7. 【相机标定与三维重建原理及实现】学习笔记1——相机模型数学推导详解

    目录 前言 一.小孔成像模型 二.坐标系的变换 1.世界坐标系到相机坐标系的变换(刚体变换)[xw^→xc^\boldsymbol {\hat{x_{w}}}\rightarrow \boldsymb ...

  8. 小吴的《机器学习 周志华》学习笔记 第二章 模型评估与选择

    小吴的<机器学习 周志华>学习笔记 第二章 模型评估与选择 上一周我们介绍了第一章的基础概念,这一次将带来第二章的前三节.后面的2.4 比较检验与2.5 偏差与方差,涉及概率论与数理统计概 ...

  9. Machine Learning A-Z学习笔记12-分类模型性能评级及选择

    Machine Learning A-Z学习笔记12-分类模型性能评级及选择 1.简单原理 一般认为假阴性比假阳性更严重,如核酸检测 用混淆矩阵表示如下图 准确率驳论(Accuracy Paradox ...

最新文章

  1. Udacity机器人软件工程师课程笔记(二十四) - 控制(其二) - PID优化,梯度下降算法,带噪声的PID控制
  2. 计算机考试受苦受累,受苦受累真是福作文800字
  3. 解决 -- 代码没有问题时接口报错:Status Code: 404 Not Found
  4. 【飞秋】进一步完善 -- GEF创建助手工具条
  5. linux select 服务器,Linux下用select()实现异步的Echo服务器
  6. 10 个步骤让你成为高效的 Web 开发者
  7. vue3.0 vuex 全局变量 存储更改
  8. Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法
  9. 常见卫星汇总--期待大神补充下载地址
  10. 微信小程序码无法解析到scene参数问题
  11. 计算机软件网络工程师考试试题,计算机软件水平考试《网络工程师》试题及答案(6)...
  12. TOJ 5138: 数字游戏
  13. python的key函数_由 sort 中 key 的用法浅谈 python
  14. CVPR 2021 | 目标引导的人类注意力估计提升零样本学习
  15. 黄金避险有效?量化实测黄金资产与A股轮动真实收益
  16. 439、Java框架93 -【SpringMVC - 拦截器】 2020.12.14
  17. 计算机毕设之医院药房管理系统
  18. 【Flutter】GridView 网格布局 ( GridView.count 构造函数 | crossAxisCount 参数指定每行元素个数 )
  19. 医药行业数字化转型加速,上云势在必行!
  20. IDEA的安装及JDK环境配置(Java小白入门必备)

热门文章

  1. js学习笔记----JavaScript中DOM扩展的那些事
  2. “马里奥(Mario)之父”──宫本茂
  3. C++右值引用与函数返回值
  4. 01_03 获取答案
  5. 开发一款游戏需要服务器系统,搭建一个游戏服务器需要什么
  6. Windows无法安装,选中的磁盘为GPT分区形式 --解决办法
  7. 三大跨境电商平台开店必备的材料
  8. 2015.8.23——张佳莉
  9. pandas.dataframe中根据条件获取元素所在的位置(索引)
  10. Shader学习建议