10OpenMP

news2024/12/28 18:38:35

OpenMP概述

通过线程实现并行化,与Pthread一样,是基于线程共享内存库

与Pthread的不同

image-20221020201159889

简而言之:

Pthread更加底层,需要用户自己定义每一个线程的行为,OpenMP虽然更加简单,但是底层的线程交互实现很难

CLION设置

CMakeLists.txt

FIND_PACKAGE( OpenMP REQUIRED)
if(OPENMP_FOUND)
    message("OPENMP FOUND")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()

样例

#include <omp.h>
#include <iostream>

using namespace std;

int main() {
    int tid, mcpu;
    //get the thread ID
    tid = omp_get_thread_num();
    //get the number of threads in the current parallel area
    mcpu = omp_get_num_threads();
    cout << "hello from thread " << tid << " in " << mcpu << "CPUs" << endl;

#pragma omp parallel private(tid, mcpu) default(none)
    //尽量不适用shared去***共享变量***,因为多个线程只会使用这一个变量的地址,会造成值的覆盖问题
    //如果不指定thread_num默认会根据电脑CPU的逻辑线程数进行创建
    {
        tid = omp_get_thread_num();
        mcpu = omp_get_num_threads();
        //std::cout << "hello from thread " << tid << " in " << mcpu << "CPUs" << endl;
        printf("aaa");
    }
    cout << "hello from thread " << tid << " in " << mcpu << "CPUs" << endl;
}

default(none)

表示所有的变量均默认为private,如需要设置共享变量,则需要使用shared字段

注意:

C++中的std::cout如果想要在并行空间中使用,就必须加入到shared字段中去,并且cout中的<<符号其实相当于又调用一次cout,如果期望输出不受干扰,推荐使用printf

image-20221020200659040

for

表明接下来的for循环将会使用并行的方式执行:

image-20221020201606490

int main() {
#pragma omp parallel for num_threads(4) default(none)//注意这里没有大括号!!!
    for (int i = 0; i < 12; i++) {
        printf("i= %d,I am Thread %d\n", i, omp_get_thread_num());
    }
    return 0;
}

分配策略为平均分配,每个线程均等分循环次数:

image-20221020203045857

数据依赖

image-20221020203157543

即[i]的结果依赖于[i-1]和[i-2],这就会导致:如果后面的线程首先被执行,但它用的却是之前未被计算的数据,从而使得数据计算不正确

变量作用域

image-20221020203622764

private

表示变量在线程中私有,其他线程访问不到,相当于每个线程内部都有一个名字一样的变量,每个线程只操作自己的变量,进入for,该变量与先前定义的值无关,会自动赋值为一个默认值(int:0,double:0.000等),上代码:

int main() {
    const int n=1000;
    int a[n],b[n],c[n],d[n],tmp;
    for(int i=0;i<n;i++) {
        a[i]=i;
        b[i]=1000-a[i];
    }
    omp_set_num_threads(8);
#pragma omp parallel for default(none) shared(a,b,c,tmp,n)//这里的shared表示并行区间要使用区间外的变量
    /*
     * 当前没有声明tmp为每个线程中的私有变量,所以在并行区间内,tmp是共享的,于是可能出现如下情况:
     * 线程1访问完tmp,正准备给c[i],赋值,此时线程5刚好修改了tmp,于是线程1赋值给c[i]的结果就出错了
     * */
    //计算c[i]
    for(int i=0;i<n;i++) {
        tmp=a[i]-b[i];
        c[i]=tmp*2;
    }
    //计算d[i]
    for(int i=0;i<n;i++) {
        tmp=a[i]-b[i];
        d[i]=tmp*2;
    }
    //统计出错次数
    int count=0;
    for(int i=0;i<n;i++) {
        if(c[i]!=d[i]) count++;
    }

    printf("%d",count);
    return 0;
}

输出结果(数据量1000):

image-20221020210119349

计算量越大,线程数越多,发生抢占的几率就越大,出错的可能也越大,如数据量为10000:

image-20221020210209616

加入private字段后:错误数为0

image-20221020210436794

firstprivate

image-20221020214435192

image-20221020214600245

数据拷贝

无论是什么类型的数据,都会重新创建一个变量,如果是数组类型,则重新创建一个一模一样的数组,如果是类的实例,则会调用构造函数创建一个一模一样的实例,在并行区间内改变变量的值,都不会影响并行区间外的变量但是特别注意:

如果是指针同样,会创建一个一模一样的指针,该指针和并行区间外的指针指向同一个内存单元,只是由于指针的定义,在并行区间内对变量所指地址的值进行修改,就会改变区间外变量所指的值,因为他俩指向的是同一个地址

int main() {

    int a[] = {1, 2, 3, 4, 5};
    int *b=a;
    omp_set_num_threads(5);
#pragma omp parallel default(none) firstprivate(a,b)
    {
        //b[0]=100;
        a[0]=100;
    }
    printf("a[0]=%d\n",a[0]);
    printf("b[0]=%d",b[0]);
        return 0;
}

输出结果:

a[0]=1
b[0]=1

如果将a[0]=100注释,而b[0]=100取消注释,则是对指针类型操作,在并行区间内改变指针所指的值,区间外指针所指的值也会随之改变

lastprivate

某一线程执行的最后一个循环(与最后执行的线程无关,而是与执行最后一次循环的线程有关)出去的时候,会将并行区间变量的值替换掉并行区间变量的值

image-20221020221314764

自定义哪个线程做哪一部分

single选项

  • 告诉编译器接下来的代码只由一个线程执行
  • 在处理使用多线程不安全代码时非常有用
  • 不使用no wait选项时,其他线程会等待single线程结束之后,才继续

master选项

  • 告诉编译器接下来的代码只由主线程执行
  • 其他线程不会等待

image-20221020222302675

image-20221020222335273

section选项

  • sections中定义section,由线程组分配任务
    • 每个section都是被一个线程执行
    • 不同section可能执行不同任务
    • 如果一个线程执行速度很快,则该线程可能又去执行另外的section了,即一个线程可能执行多个section

2个section 分配4个线程,谁先抢到谁执行

image-20221020223107157

5个section,2个线程,同样谁先抢到谁执行:

​ 下图可以看到,1号线程执行很快,抢到了4个section

image-20221020223320530

reduction计算

  • 首先会对变量进行相当于private的拷贝,并赋初值,如下图;与lastprivate不同的是,reduction会将所有该变量(包括所有线程的同名变量以及并行区间外的该变量)进行相应运算操作
  • reduction提供的操作符基本都符合结合律

image-20221020223653626

image-20221020223932172

image-20221020224646930

barrier同步

image-20221021105755358

image-20221021110237500

nowait取消等待

不让线程彼此相互等待,每个线程继续执行下去

image-20221021113600054

critical互斥

竞争现象

image-20221021114155392

image-20221021113925535

critical案例:图中打错了

image-20221021125111234

automic原子操作

image-20221021125237695

与critical的区别

image-20221021125519370

schedule调度

根据不同的for场景使用不同的策略

image-20221021125706035

static

线程执行顺序—轮循:012301230123……

image-20221021125940989

dynamic

线程每次质询一个块(chunk),谁执行的快,谁就可以优先抢占,如下图中 2号线程执行快,执行顺序为012321

image-20221021130221597

guided

开销与dynamic稍高,具体根据for的循环来确定使用哪种操作

image-20221021131059635

对比

)]

static

线程执行顺序—轮循:012301230123……

[外链图片转存中…(img-AlOf1XVK-1696142420540)]

dynamic

线程每次质询一个块(chunk),谁执行的快,谁就可以优先抢占,如下图中 2号线程执行快,执行顺序为012321

[外链图片转存中…(img-bPy6Y9Om-1696142420540)]

guided

开销与dynamic稍高,具体根据for的循环来确定使用哪种操作

[外链图片转存中…(img-SsvBWOnw-1696142420542)]

对比

image-20221021131428378

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

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

相关文章

【单片机】13-实时时钟DS1302

1.RTC的简介 1.什么是实时时钟&#xff08;RTC&#xff09; &#xff08;rtc for real time clock) &#xff08;1&#xff09;时间点和时间段的概念区分 &#xff08;2&#xff09;单片机为什么需要时间点【一定的时间点干什么事情】 &#xff08;3&#xff09;RTC如何存在于…

【Git】Git 原理和使用

Git 一、Git 本地仓库1. 本地仓库的创建2. 配置 Git3. 工作区、暂存区、版本库4. 添加文件5. 查看 .git 文件6. 修改文件7. 版本回退8. 撤销修改9. 删除文件 二、分支管理1. 理解分支2. 创建分支3. 切换分支4. 合并分支5. 删除分支6. 合并冲突7. 分支管理策略8. bug 分支9. 强制…

基于Java的厨艺交流平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

JavaScript Web APIs第三天笔记

Web APIs - 第3天 进一步学习 事件进阶&#xff0c;实现更多交互的网页特效&#xff0c;结合事件流的特征优化事件执行的效率 掌握阻止事件冒泡的方法理解事件委托的实现原理 事件流 事件流是对事件执行过程的描述&#xff0c;了解事件的执行过程有助于加深对事件的理解&…

数据结构刷题(三十三):完全背包最小值情况。322. 零钱兑换、279. 完全平方数

题目一&#xff1a; 322. 零钱兑换https://leetcode.cn/problems/coin-change/ 思路&#xff1a;完全背包问题&#xff0c;求解最小组合数。dp[j]&#xff1a;凑足总额为j所需钱币的最少个数为dp[j]。同时需要确保凑足总金额为0所需钱币的个数一定是0&#xff0c;那么dp[0] 0…

如果只是用php纯做api的话,给移动端做数据接口,是否需要用php框架?

API接口对接是现代软件开发中不可或缺的一部分&#xff0c;它允许不同的应用程序之间进行数据交换和服务调用。在PHP中&#xff0c;可以使用多种方式实现API接口的对接&#xff0c;包括基于HTTP协议的传统方法以及现代的API客户端库客户端库客户端库等。 一、实现API接口的对接…

Web开发-登录页面设计流程

目录 确定页面设计样式创建js文件jquery.min.jsbootstrap.min.js 创建css文件bootstrap.min.cssmaterialdesignicons.min.cssstyle.min.css 创建ftl文件header.ftlfooter.ftllogin.ftlcss部分html部分 确定页面设计样式 可以自己用“画图”等软件进行设计&#xff0c;也可以打…

步进电机只响不转

我出现问题的原因是相位线接错。 我使用的滑台上示17H的步进电机&#xff0c;之前用的是57的步进电机。 57步进电机的相位线是A黑、A-绿、B红、B-蓝。 17步进电机的相位线是A红、A-绿、B黑、B-蓝。 这两天被一个问题困扰了好久&#xff0c;在调试步进电机开发板的时候电机发生…

ubuntu安装ROS

进官网&#xff0c;选版本&#xff0c;操作系统 ROS: Home 开始安装&#xff1a; noetic/Installation/Ubuntu - ROS Wiki Installation Configure your Ubuntu repositories Configure your Ubuntu repositories to allow "restricted," "universe,"…

银行金融科技岗笔试题资料大总结

程序员进银行科技岗——简单总结_银行程序员 无水印&#xff0c;可直接打印使用。 中国银行 通用资料 视频资料

IPV6(IPV6,RIPng的配置以及手工配置IPV4隧道)

目录 实验一&#xff1a;IPv6的基本配置 实验二&#xff1a;RIPng基本配置 RIPng RIPng的工作机制 实验三&#xff1a;手工配置IPV4隧道 实验一&#xff1a;IPv6的基本配置 案例如下&#xff1a; 各部分配置如下 配置路由器RTA <Huawei>sys Enter system view, …

【论文笔记】DiffusionTrack: Diffusion Model For Multi-Object Tracking

原文链接&#xff1a;https://arxiv.org/abs/2308.09905 1. 引言 多目标跟踪通常分为两阶段的检测后跟踪&#xff08;TBD&#xff09;和一阶段的联合检测跟踪&#xff08;JDT&#xff09;。TBD对单帧进行目标检测后&#xff0c;使用跟踪器跨帧关联相同物体。使用的跟踪器包括使…

【STM32基础 CubeMX】外部中断

文章目录 前言一、中断是什么二、使用CubeMX配置你的第一个中断三、代码分析CubeMX四、中断函数按键中断点灯示例代码总结 前言 当涉及到STM32基础的外部中断时&#xff0c;我们进入了一个引人入胜的领域&#xff0c;它允许微控制器与外部世界进行互动并实时响应各种事件。外部…

【论文阅读】通过3D和2D网络的交叉示教实现稀疏标注的3D医学图像分割(CVPR2023)

目录 前言方法标注3D-2D Cross Teaching伪标签选择Hard-Soft Confidence Threshold Consistent Prediction Fusion 结论 论文&#xff1a;3D Medical Image Segmentation with Sparse Annotation via Cross-Teaching between 3D and 2D Networks 代码&#xff1a;https://githu…

2023年中国艺术涂料市场发展历程及趋势分析:艺术涂料市场规模将进一步扩大[图]

艺术涂料是一种用于绘画和装饰&#xff0c;具有各种纹理或通过涂装手段后具有高装饰性的新型涂料。由于具有高度饱和的颜色、良好的遮盖力和可塑性&#xff0c;呈现立体装饰效果好、色彩搭配适当、风格独具特色的特点&#xff0c;而使得涂装出的饰面自然贴合、更加美观漂亮&…

Centos7环境下安装MySQL8详细教程

目录 一、Xftp7下载二、MySQL8安装包的下载三、将MySQL8安装包上传至服务器四、解压mysql8安装包五、rpm包的安装六、依次安装下列文件七、对MySQL进行初始化和授权八、查看数据库初始密码九、启动MySQL服务十、使用初始密码登录MySQL关于MySQL的卸载 一、Xftp7下载 关于Xftp7…

力扣 -- 718. 最长重复子数组

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int findLength(vector<int>& nums1, vector<int>& nums2) {int m nums1.size();int n nums2.size();//多开一行&#xff0c;多开一列vector<vector<int>> dp(m 1, ve…

华为云云耀云服务器L实例评测 | 搭建企业级 Registry 服务器 Harbor

文章目录 您需要了解Harbor介绍Harbor特性和优势系统设置关闭防火墙安装Docker安装Docker Compose配置镜像加速器 Habor安装传包并解压配置Harbor安装Horbor登录Harbor 测试创建项目推送镜像拉取镜像 您需要了解 本次搭建采用 华为云耀云服务器 &#xff0c;一键部署、快速搭建…

Visual Studio 代码显示空格等空白符

1.VS2010: 快捷键&#xff1a;CtrlR,W 2.VS2017、VS2019、VS2022&#xff1a; 工具 -> 选项 -> 文本编辑器 -> 显示 -> 勾选查看空白

RWA分析通过10个问题。不要让数字和视觉欺骗您!(文章很长,请仔细阅读)

已经有30个小伙伴加入我们的星球了&#xff0c;如果你不介意的话&#xff0c;可以加入 我的知识星球主要分享 1. 分享区块链各种有价值的内容 2. 一起攻读一些有用的书籍 3. 财富密码&#xff08;不敢保证&#xff09; 4. 一些自我的感悟 1.什么是现实世界资产&#xff08;RWA&…