性能优化-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.hqwc.cn/news/327244.html

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

相关文章

万众期盼的剪辑新功能来了 会声会影2024旗舰版焕新登场

会声会影2024全新升级来袭&#xff0c;Corel公司这次为用户带来了多项功能更新&#xff0c;软件风格整体更偏向于“轻松剪辑&#xff0c;快速出片”。会声会影的本次更新还是很令人惊喜的&#xff0c;在各种人工智能算法的加持下&#xff0c;用户只需要进行几步简单地设置&…

数据结构——堆排序

什么是堆排序 堆排序就是利用堆&#xff08;假设利用大堆&#xff09;进行排序的算法。他的基本思想是&#xff0c;将待排序的序列构造成一个大顶堆。此时&#xff0c;整个序列的最大值就是堆顶的根节点。将他移走&#xff08;其实就是将其与堆数组的末尾元素交换&#xff0c;…

transforms图像增强(二)

一、图像变换 1、transforms.Pad transforms.Pad是一个用于对图像边缘进行填充的数据转换操作。 参数&#xff1a; padding&#xff1a;设置填充大小。可以是单个整数&#xff0c;表示在上下左右四个方向上均填充相同数量的像素&#xff1b;也可以是一个包含两个整数的元组…

PEFT: 在低资源硬件上对十亿规模模型进行参数高效微调

1 引言 最近&#xff0c;深度学习的研究中出现了许多大型预训练模型&#xff0c;例如 GPT-3、BERT 等&#xff0c;这些模型可以在多种自然语言处理任务中取得优异的性能表现。而其中&#xff0c;ChatGPT 模型因为在对话生成方面的表现而备受瞩目&#xff0c;成为了自然语言处理…

webgl调试之排查内存泄漏

内存泄漏自然而然是要看内存是不是涨了 然后我们如何确认泄露了呢&#xff0c;我们需要把代码梳理清楚&#xff0c;知道哪个时机&#xff0c;在delete&#xff0c;在create&#xff0c;那么这个时候&#xff0c;按道理&#xff0c;delete了n个对象&#xff0c;create了N个对象&…

Python从入门到网络爬虫(MySQL链接)

前言 在实际数据分析和建模过程中&#xff0c;我们通常需要从数据库中读取数据&#xff0c;并将其转化为 Pandas dataframe 对象进行进一步处理。而 MySQL 数据库是最常用的关系型数据库之一&#xff0c;因此在 Python 中如何连接 MySQL 数据库并查询数据成为了一个重要的问题…

实验笔记之——基于Linux服务器复现Instant-NGP及常用的tmux指令

之前博客实现了基于windows来复现Instant-NGP&#xff0c;本博文在linux服务器上测试 实验笔记之——基于windows复现Instant-NGP-CSDN博客文章浏览阅读444次&#xff0c;点赞15次&#xff0c;收藏7次。之前博客对NeRF-SLAM进行了调研&#xff0c;本博文先复现一下Intant-NGP。…

QT----Visual stdio翻金币案例,附源码

历经一个月&#xff0c;各种事情磕磕绊绊&#xff0c;终于结束了&#xff0c;自己还是太菜了 案例的文档写的教程已经很详细&#xff0c;这边主要是记录一些问题 github代码 gitee代码 1、图片无法加载 一开始加载首页图片和标题出不来&#xff0c;结果是paintEvent重写的字打…

rust 注释文档生成 cargo doc

rust的cargo文档生成 只需要在每个函数写清楚注释&#xff0c;就可以自动生成文档&#xff0c;很方便 即不用写文档&#xff0c;又可以快速查看&#xff0c;是开发rust的必备技能 rust安装和开发环境配置&#xff0c;可以参考&#xff1a;链接 1.写注释的方法 连续三个 \ 即…

【已解决】js定义对象属性是.如何访问

当变量没有length属性的时候&#xff0c;可能是个对象变量&#xff0c;当有键值对的时候就可能是个对象&#xff0c;读者都知道的是&#xff0c;用typeof(变量)可以查看属性&#xff0c;今天本文解决的问题是如果js定义对象中属性是"点"如何访问 问题再现 var a {…

【性能测试入门】详解客户端性能测试和服务器端性能测试!

一&#xff1a;客户端性能测试和服务器端性能测试 客户端性能测试和服务器端性能测试是两个不同但相关的概念: 客户端性能测试: - 测试应用程序客户端(如Web浏览器、移动应用等)的性能,例如加载时间,响应时间等。 - 测试在不同系统配置(CPU、内存、网络等)下客户端的运行性…

【HarmonyOS】装饰器下的状态管理与页面路由跳转实现

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…