性能优化-OpenMP基础教程(三)

本文主要介绍OpenMP并行编程的环境变量和实战、主要对比理解嵌套并行的效果。

🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:高性能(HPC)开发基础教程
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!

目录

一、OpenMP是什么?

1 OpenMP的主要特点

2 Linux下OpenMP版本查看

3 OpenMP 环境变量

二、OPenMP实战

1 parallel

2 parallel for 

3 最大线程数获取(核数)

4 嵌套的使用(重点)

4.1 简单单并行

4.2 双并行不允许嵌套

4.3 双并行允许嵌套


一、OpenMP是什么?

        OpenMP(Open Multi-Processing)是一个用于C、C++和Fortran编程语言的并行编程模型。

        是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套指导性注释(Compiler Directive)。

        支持OpenMP的编译器包括Sun Compiler,GNU Compiler和Intel Compiler等。它提供了一套简单而强大的API,使得开发人员可以轻松地在多核处理器上编写并行程序。

        OpenMP通过将一个大的任务分解成多个小的任务,并将这些任务分配给不同的线程来并行执行,从而提高程序的性能。它提供了一些指令和函数,用于控制线程的创建、同步和通信等操作。

        OpenMP提供了一种高层的抽象描述,用于并行算法。程序员可以通过在源代码中添加专用的pragma来明确表达他们的意图,这样编译器就可以自动将程序进行并行化,并在需要的地方添加同步、互斥和通信机制。当选择忽略这些pragma或者编译器不支持OpenMP时,程序可以退化为普通的串行程序,代码仍然可以正常运行,只是无法利用多线程来加速程序执行

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

        OpenMP官网 OpenMP官网

        OpenMP规范 OpenMP规范

        

1 OpenMP的主要特点

        1. 简单易用:OpenMP提供了一组简单的API,使得开发人员可以轻松地编写并行代码。
        2. 可移植性:OpenMP可以在各种硬件平台上运行,包括多核CPU、GPU和分布式系统等。
        3. 高性能:OpenMP可以利用多核处理器的并行计算能力,提高程序的执行效率。
        4. 共享内存模型:OpenMP使用共享内存模型来实现线程之间的通信和同步,避免了数据竞争的问题。
        5. 支持多种编程范式:OpenMP支持多种编程范式,包括数据并行、任务并行和指令级并行等。

2 Linux下OpenMP版本查看

        Linux的GCC编译器支持OpenMP,版本的查看使用如下:

 echo |cpp -fopenmp -dM |grep -i open

        执行后打印例如:

#define _OPENMP 201511

        可以到OpenMP Specification 查看对应的版本映射,201511代表2015年11月发布的OpenMP版本。

3 OpenMP 环境变量

        在性能优化-OpenMP基础教程(一)中主要介绍了OpenMP的指令和函数,这里补充OpenMP的环境变量。

环境变量描述
OMP_NUM_THREADS指定并行区域中使用的线程数
OMP_PROC_BIND控制线程与处理器之间的绑定关系
OMP_PLACES指定线程在处理器上的放置方式
OMP_SCHEDULE控制循环迭代的调度策略
OMP_STACKSIZE指定线程栈的大小
OMP_DYNAMIC控制是否启用动态调度
OMP_DEBUG控制是否启用OpenMP调试功能
OMP_WAIT_POLICY控制线程等待其他线程完成的策略
OMP_FLUSH_INTERVAL指定刷新内存缓存的时间间隔
OMP_PROC_BIND控制线程与处理器之间的绑定关系
OMP_PLACES指定线程在处理器上的放置方式
OMP_SCHEDULE控制循环迭代的调度策略
OMP_STACKSIZE指定线程栈的大小
OMP_DYNAMIC控制是否启用动态调度
OMP_DEBUG控制是否启用OpenMP调试功能
OMP_WAIT_POLICY控制线程等待其他线程完成的策略
OMP_FLUSH_INTERVAL指定刷新内存缓存的时间间隔

二、OPenMP实战

        编译仅仅需要在g++或者gcc 后面加编译选项 -fopenmp 。需要调用OpenMP的某些接口时,需要在代码中包含<omp.h>头文件。例如:

gcc test.c -fopenmp -o testg++ test1.cpp -fopenmp -o test1

1 parallel

        编译制导指令parallel,用来创建并行域,后面紧跟需要创建并行域的代码,紧跟的才有用,可以使用{}括起来,空行不算代码。

#include<iostream>
#include"omp.h"
using namespace std;
int main()
{#pragma omp parallel{cout << "parallel Test" << endl;}{cout << "serial Test" << endl;}return 0;
}

        运行结果:

        由于笔者电脑有八个核,所以打印8次。可以明显看出只有紧跟的代码才并行处理。OpenMP可以非常简单的编写并行程序,这是它的优势。

        注意:输出也可能是乱码,因为多线程共享标准输出引起的竞争条件

2 parallel for 

        paraller 仅仅只是让系统有了并行域,创建了多个线程执行相同的内容,并没有提高效率。使用parallel for可以让内容分配给不同的线程去执行,注意是将一个任务划分为多个子任务让多核系统去执行,这样就提高了效率,这才是OpenMP的核心。parallel for 可以默认使用系统的多核线程数,也可以用num_threads(number)指定线程数。

        parallel for 只作用于紧跟的for循环,但是这个for循环是可以嵌套的。

        注意parallel for 需要搭配for 循环使用。

#include<iostream>
#include"omp.h"
using namespace std;
int main()
{#pragma omp parallel forfor (int i = 0;i < 8;i++){printf("ThreadID: %d i = %d 当前并行域线程数: %d \n",omp_get_thread_num(),i,omp_get_num_threads());}printf("****************************\n");#pragma omp parallel for num_threads(4)for (int i = 0;i < 8;i++){printf("ThreadID: %d i = %d 当前并行域线程数: %d \n",omp_get_thread_num(),i,omp_get_num_threads());}{cout << "serial Test" << endl;}return 0;
}

        运行结果:

3 最大线程数获取(核数)

#include <iostream>
#include <omp.h>int main()
{#ifdef _OPENMPprintf("Max threads nums: %d \n",omp_get_max_threads());#else#endifreturn 0;
}

        运行结果:

4 嵌套的使用(重点)

        omp_set_nested(1) 设置允许嵌套使用,作用域在下面所有代码,不包括设置之前,只有当设置为omp_set_nested(0)时,嵌套允许才会被取消。

        omp_get_nested() 测试当前并行域是否支持嵌套使用

4.1 简单单并行

#include <stdio.h>
#include <omp.h>int  main()
{// omp_set_nested(1);   // 设置允许嵌套并行可用 #pragma omp parallel num_threads(2){printf("第一级, thread %d of %d\n", omp_get_thread_num(),omp_get_num_threads());// #pragma omp parallel num_threads(2){printf("第二级, thread %d of %d\n", omp_get_thread_num(),omp_get_num_threads());}}return 0;
}

        运行结果:

        分析可知2个线程,都执行第一级和第二级,两个线程都执行一次第一级和第二级。

4.2 双并行不允许嵌套

#include <stdio.h>
#include <omp.h>int  main()
{// omp_set_nested(1);   // 设置允许嵌套并行可用 #pragma omp parallel num_threads(2){printf("第一级, thread %d of %d\n", omp_get_thread_num(),omp_get_num_threads());#pragma omp parallel num_threads(2){printf("第二级, thread %d of %d\n", omp_get_thread_num(),omp_get_num_threads());}}return 0;
}

        运行结果:

        分析可知,第一级部分获得两个线程执行,第二级一个线程执行两次,这是不允许嵌套并行。

4.3 双并行允许嵌套

#include <stdio.h>
#include <omp.h>int  main()
{omp_set_nested(1);   // 设置允许嵌套并行可用 #pragma omp parallel num_threads(2){printf("第一级, thread %d of %d\n", omp_get_thread_num(),omp_get_num_threads());#pragma omp parallel num_threads(2){printf("第二级, thread %d of %d\n", omp_get_thread_num(),omp_get_num_threads());}}return 0;
}

        运行结果:

     

        分析可知,第一级在嵌套并行外部,因此在允许嵌套并行的情况下,执行两次;第二级在嵌套并行内,因此外部的每个线程会产生两个线程,这样就有4个线程执行第二级,这是允许嵌套执行的效果。

🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!

下一节继续对OpenMP的更深层次的编程进行讲解!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/601152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

书生·浦语大模型全链路开源体系 学习笔记 第一课

背景 大模型是发展人工通用人工智能的一个重要途径&#xff0c;能够解决多种任务和多种模态&#xff0c;展示了一个更面向更高阶的智能的潜在途径。大模型的发展历程是从专用模型到通用模型的过程&#xff0c;从语音识别、图像识别、人脸识别等专用模型&#xff0c;到通用的大…

Java8内置四大核心函数式接口

先来看几个例子,主要练习策略模式: 用策略模式的做法 定义个接口 其实像这样的接口并不需要我们自己创建 java8推出的Lambda表达式主要就是为了简化开发,而Lambda表达式 的应用主要是针对与函数式接口,自然也推出了对应的一些接口 /*** Java8 内置的四大核心函数式接口** C…

【C++】STL 算法 ③ ( 函数对象中存储状态 | 函数对象作为参数传递时值传递问题 | for_each 算法的 函数对象 参数是值传递 )

文章目录 一、函数对象中存储状态1、函数对象中存储状态简介2、示例分析 二、函数对象作为参数传递时值传递问题1、for_each 算法的 函数对象 参数是值传递2、代码示例 - for_each 函数的 函数对象 参数在外部不保留状态3、代码示例 - for_each 函数的 函数对象 返回值 一、函数…

权威认可!甄知科技猪齿鱼产品荣获信创产品评估证书

近日&#xff0c;依据《信息技术应用创新产品评估规范 第1部分&#xff1a;应用软件》&#xff08;T/SSIA 2001-2022&#xff09;&#xff0c;经过严格评估&#xff0c;甄知科技旗下自主研发的猪齿鱼数智化开发管理平台 V2.0.0&#xff0c;通过信创测试认证&#xff0c;获得上海…

差分约束算法

差分约束 差分约束系统包含 m m m个涉及 n n n个变量的差额限制条件&#xff0c;这些差额限制条件每个都是形式为 x i − x j ≤ b ∈ [ 1 , m ] x_i-x_j\leq b_{\in[1,m]} xi​−xj​≤b∈[1,m]​的简单线性不等式。 通常我们要求解出一组可行解。 最短路差分约束 如果我们…

ubuntu 22 virt-manger(kvm)安装winxp; ubuntu22体验 firebird3.0

安装 、启动 virt-manager sudo apt install virt-manager sudo systemctl start libvirtdsudo virt-manager安装windowsXP 安装过程截图如下 要点1 启用 “包括寿终正寝的操作系统” win_xp.iso 安装过程 &#xff1a; 从winXp.iso启动, 执行完自己重启从硬盘重启&#xff0c…

稿件代写3个不可或缺的步骤让你事半功倍-华媒舍

作为一个需求频繁的作者&#xff0c;你可能会面临大量的稿件代写任务。但是&#xff0c;你是否曾经为提高文章质量而苦恼过&#xff1f;是否希望在有限的时间内完成更多的代写任务&#xff1f;本篇文章将向你介绍三个不可或缺的稿件代写步骤&#xff0c;帮助你事半功倍&#xf…

Redis高级特性和应用(慢查询、Pipeline、事务、Lua)

Redis的慢查询 许多存储系统(例如 MySQL)提供慢查询日志帮助开发和运维人员定位系统存在的慢操作。所谓慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息(例如:发生时间,耗时,命令的详细信息)记录下来,Redis也提供了类似…

Huggy Lingo: 利用机器学习改进 Hugging Face Hub 上的语言元数据

太长不看版: Hub 上有不少数据集没有语言元数据&#xff0c;我们用机器学习来检测其语言&#xff0c;并使用 librarian-bots 自动向这些数据集提 PR 以添加其语言元数据。 Hugging Face Hub 已成为社区共享机器学习模型、数据集以及应用的存储库。随着 Hub 上的数据集越来越多&…

[概率论]四小时不挂猴博士

贝叶斯公式是什么 贝叶斯公式是概率论中的一个重要定理&#xff0c;用于计算在已知一些先验信息的情况下&#xff0c;更新对事件发生概率的估计。贝叶斯公式的表达式如下&#xff1a; P(A|B) P(B|A) * P(A) / P(B) 其中&#xff0c;P(A|B)表示在事件B发生的条件下事件A发生的概…

基于sumo实现交通灯控制算法的模板

基于sumo实现交通灯控制算法的模板 目录 在windows安装run hello world networkroutesviewsettings & configurationsimulation 交通灯控制系统 介绍文件生成器类&#xff08;FileGenerator&#xff09;道路网络&#xff08;Network&#xff09;辅助函数生成道路网络&am…

php 数组中的元素进行排列组合

需求背景&#xff1a;计算出数组[A,B,C,D]各种排列组合&#xff0c;希望得到的是数据如下图 直接上代码&#xff1a; private function finish_combination($array, &$groupResult [], $splite ,){$result [];$finish_result [];$this->diffArrayItems($array, $…

12、DolphinScheduler

1、DolphinScheduler简介 1.1、 DolphinScheduler概述 Apache DolphinScheduler是一个分布式、易扩展的可视化DAG工作流任务调度平台。致力于解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。 1.2、 DolphinScheduler核心架构 Dolph…

USB -- STM32F103缓冲区描述表及USB数据存放位置讲解(续)

目录 链接快速定位 前沿 1 0x40005C00和0x40006000地址的区别和联系 2 USB_BTABLE寄存器介绍 3 USB缓冲区描述表&#xff08;SRAM&#xff09;介绍 3.1 发送缓冲区地址寄存器n&#xff08;n[0..7]&#xff09; 3.2 发送数据字节数寄存器n&#xff08;n[0..7]&#xff09…

从C++习题中思考

目录 一.开始1.1 二.变量和基本类型1.11.21.31.31.41.5 C Peimer习题集第5版练习。 一.开始 1.1 编写程序&#xff0c;提示用户输入2个整数&#xff0c;打印出这两个整数指定的范围内的所有整数。 方式1&#xff1a;使用while循环。 #include<iostream> using namespac…

socket实现视频通话-WebRTC

最近喜欢研究视频流&#xff0c;所以思考了双向通信socket&#xff0c;接下来我们就一起来看看本地如何实现双向视频通讯的功能吧~ 客户端获取视频流 首先思考如何获取视频流呢&#xff1f; 其实跟录音的功能差不多&#xff0c;都是查询电脑上是否有媒体设备&#xff0c;如果…

C语言学习NO.11-字符函数strlen,strlen函数的使用,与三种strlen函数的模拟实现

&#xff08;一&#xff09;strlen函数的使用 strlen函数的演示 #include <stdio.h> #include <string.h>int main() {char arr1[] "abcdef";char arr2[] "good";printf("arr1 %d,arr2 %d",strlen(arr1),strlen(arr2));return …

GUI三维绘图

绘制三维图plot3 t0:pi/50:10*pi; xsin(t); ycos(t); zt; plot3(x,y,z); 产生栅格数据点meshgrid 这个接口在绘制三维图像里面相当重要&#xff0c;很多时候要将向量变成矩阵才能绘制三维图。 x0:0.5:5; y0:1:10; [X,Y]meshgrid(x,y); plot(X,Y,o); x和y是向量&#xff0c;…

Python开发环境搭建

Python程序设计语言是解释型语言&#xff0c;其广泛应用于运维开发领域、数据分析领域、人工智能领域&#xff0c;本文主要描述Python开发环境的搭建。 www.python.org 如上所示&#xff0c;从官方网站下载Python最新的稳定版本3.12.1 如上所示&#xff0c;在本地的开发环境安…

Spring面试篇

Spring面试篇 前置知识ApplicationContextInitializerApplicationListenerBeanFactoryBeanDefinitionBeanFactoryPostProcesssorAwareInitialzingBean&#xff0c;DisposableBeanBeanPostProcessor SpringBoot启动流程IOC容器初始化流程Bean生命周期Bean循环依赖解决 SpringMvc…