OpenMP

news2024/11/16 7:23:51

官方文档:OpenMP | LLNL HPC Tutorials

OpenMP总览

统一内存访问:OpenMP、Pthreads

非统一内存访问:MPI

OpenMP与Pthread

OpenMP原理

串行区到达并行区后会派生多个线程,并行区代码执行完后进行线程合并,剩下主线程

编译指导语句格式

openmp提供基于指令的内存共享API

预处理指令:#pragma omp 指导指令 [子句]

                     若一行放不下要另起一行,则需要 / 来转义

编译指令:gcc -g -fopenmp -o hello hello.c

没有代码补全了,很急啊!!!

示例程序

“Hello world”

#include<stdlib.h>
#include<stdio.h>
#ifdef _OPENMP
#include<omp.h>
#endif

int thread_count;
void* Hello(void)
{
    #ifdef _OPENMP
        int my_rank = omp_get_thread_num();//获取线程号
        int thread_count = omp_get_num_threads();//确定当前线程组中活动线程的数量
    #else
        int my_rank = 0;
        int thread_count = 1;
    #endif
    printf("Hello from thread %ld of %d\n",my_rank,thread_count);
    return NULL;
}
 
int main(int argc,char* argv[])
{
    thread_count = strtol(argv[1],NULL,10);
    #pragma omp parallel num_threads(thread_count)
        Hello();
    return 0;
}

不传惨默认电脑核数(我的电脑是12核)

计算机环境变量:OMP_NUM_THREADS

 传参结果

 梯形积分法

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#ifdef _OPENMP
#include<omp.h>
#endif

void work(double a,double b,int n,double *global_result)
{
    #ifdef _OPENMP
        int my_rank = omp_get_thread_num();//获取线程号
        int thread_count = omp_get_num_threads();//确定当前线程组中活动线程的数量
    #else
        int my_rank = 0;
        int thread_count = 1;
    #endif

    double h = (b-a)/n;
    double my_result;
    int local_n = n/thread_count;//每个线程执行多少块梯形
    double local_a = a + my_rank * local_n * h;
    double local_b = local_a + local_n * h;
    long long i;
    my_result = (sin(local_a)+sin(local_b))/2.0;
    for(i=1;i<=local_n-1;i++){//这里ppt写的是i<loacl_n-1,应该是<=
        double x = (double)i*h + local_a;
        my_result += sin(x);
    }
    my_result *= h;
    #pragma omp critical
    {
        *global_result += my_result;
    }
    
}
 
int main(int argc,char* argv[])
{   int thread_count;
    int n;//分割成n个梯形
    double a,b;//积分区域的左右两端
    double global_result = 0.0;

    thread_count = strtol(argv[1],NULL,10);
    printf("Please enter n,a and b\n");
    scanf("%d %lf %lf",&n,&a,&b);
    
    #pragma omp parallel num_threads(thread_count)
        work(a,b,n,&global_result);
    printf("result: %.6f",global_result);
       
    return 0;
}

变量作用域

private ( list )
private将一个或多个变量声明成线程的私有变量,每个线程有自己变量私有副本,仅当前并行区域有效 。


fistprivate ( list )
对私有变量进行初始化,把串行变量值拷贝到私有变量中。


lastprivate ( list )
对私有变量的终结操作,把私有变量(最后的循环迭代)拷贝到同名串行变量中。

shared ( list )
将变量声明为共享变量

上面为粗粒度锁,下面为细粒度锁

double factor = 1.0;
double sum = 0.0;
# pragma omp parallel for num_threads( th_count ) default(none) reduction( +: sum ) \
private( k, factor ) shared(n)
for ( k = 0; k < n; k ++ ) {
if ( k % 2 == 0)
factor = 1.0;
else
factor = -1.0;
sum += factor / ( 2 * k + 1 );
}
pi_approx = 4.0 * sum;

default(none) 相当于在并行区域之前告诉编译器,在没有使用 shared 或 private 等指定变量共享属性的情况下,所有变量都被视为私有的。这样做是为了防止程序员忘记明确指定共享属性导致错误的结果。 

归约子句

归约操作将归约操作符重复地应用于操作数序列来得到一个结果的计算

语法:reduction ( <operator> : <variable list>)

global_result = 0.0;
# pragma omp parallel num_threads (thread_count) reduction (+: global_result)
global_result += Local_trap(a,b,n);

把各个线程计算的结果汇总到归约变量上

归约是通过为每个隐式任务创建每个线程的列表项的私有副本来实现的,就像使用了private子句global_result += my_result一样。

OpenMP for

 它告诉编译器,接下来的for循环将会使用并行的方式执行

使用并行的时候需要满足以下四个需求:

在循环的迭代器必须是可计算的并且在执行前就需要确定迭代的次数。

在循环的代码块中不能包含break,return,exit。

在循环的代码块中不能使用goto跳出到循环外部。

迭代器只能够被for语句中的增量表达式所修改。

嵌套循环并行化中内层循环并行和外层循环并行是不一样的

以下为2个线程为例:

1.外层

i = 0时为一个线程,i = 1为一个线程,每个线程执行一次j = 6,7,8,9

因为是并行,所以会有i = 0和i = 1交替出现的情况,同时需要用private将j声明成线程私有变量,因为i = 0时的j和i = 1时的j不一样

2.内层:

j = 6,9为一个线程,j = 8,7为一个线程,不需要private声明,开启并行区域时,两个线程的i索引都相同,用的是同一层i下的j

数据依赖性

 OpenMP编译器不检查被parallel for指令并行化的循环所包含的迭代间的依赖关系
一个或者更多个迭代结果依赖于其他迭代的循环,一般不能被正确的并行化

有数据依赖关系的计算被分配到一个线程,不会影响计算结果

比如在斐波那契数列,算了前面的才能算后面的,但是parallel for会把n次迭代分配好后同时开始算,并不会等计算下标在前的数的线程算好后再算

OpenMP section and single

 

 OpenMP barrier

循环调度

 

 

 

 

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

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

相关文章

SqueezeLM 的想法,压缩输入句子潜变量,生成下一句子

又搞了一段时间。还是感觉LongNet那种空洞注意力做编码器有搞头。 RetNet等AFT方法&#xff0c;直接生成太长的句子感觉有点难度&#xff0c;不过可以一句句生成&#xff0c;每次生成短句&#xff0c;这样感觉比较合适。 启发 受 MemroyTransformer 和 GLM 启发 想了一个类似…

大会第二日,精彩不停!LiveVideoStackCon 2023 上海站

历时四个月的精心筹备&#xff0c;LiveVideoStackCon 组委会与联席主席、出品人及评审团通力合作&#xff0c;90余位讲师对演讲内容的反复琢磨……只为呈现最专业的音视频技术盛会。 今日&#xff0c;以「沉浸新视界」为主题的LiveVideoStackCon 2023 上海站 音视频技术大会继续…

ACL原理

ACL原理 ACL是一种用于控制网络设备访问权限的技术&#xff0c;可以通过配置ACL来限制特定用户、应用程序或网络设备对网络资源的访问。 1、ACL&#xff08;Access Control List&#xff09; 2、ACL是一种包过滤技术。 3、ACL基于IP包头的IP地址、四层TCP/UDP头部的端口号、…

Flowable-服务-微服务任务

目录 定义图形标记XML内容界面操作 定义 Sc 任务不是 BPMN 2.0 规范定义的官方任务&#xff0c;在 Flowable 中&#xff0c;Sc 任务是作为一种特殊的服务 任务来实现的&#xff0c;主要调用springcloud的微服务使用。 图形标记 由于 Sc 任务不是 BPMN 2.0 规范的“官方”任务…

WebAgent-基于大型语言模型的代理程序

大型语言模型&#xff08;LLM&#xff09;可以解决多种自然语言任务&#xff0c;例如算术、常识、逻辑推理、问答、文本生成、交互式决策任务。最近&#xff0c;LLM在自主网络导航方面也取得了巨大成功&#xff0c;代理程序助HTML理解和多步推理的能力&#xff0c;通过控制计算…

【Linux多线程】详解线程控制、线程分离

线程互斥与同步 &#x1f478; 理解线程&#x1f934;pthead_t&#x1f977;关于线程&#x1f9b8;‍♀️线程控制POSIX线程库线程ID及进程地址空间布局 &#x1f9b8;线程分离__thread关键字&#x1f9b8;‍♂️pthread_detach函数&#x1f9b9;‍♀️pthread_exit函数&#x…

[JavaWeb]SQL介绍-DDL-DML

SQL介绍-DDL-DML 一.SQL简介1.简介2.SQL通用语法3.SQL语言的分类 二.DDL-操作数据库与表1.DDL操作数据库2.DDL操作表①.查询表(Retrieve)②.创建表(Create)③.修改表(Update)④.删除表(Delete) 三.Navicat的安装与使用四.DML-操作表数据1.添加(Insert)2.修改(Update)3.删除(Del…

【C++】反向迭代器的模拟实现通用(可运用于vector,string,list等模拟容器)

文章目录 前言一、反向迭代器封装&#xff08;reverseiterator&#xff09;1.构造函数1解引用操作.3.->运算符重载4.前置&#xff0c;后置5.前置--&#xff0c;后置--6.不等号运算符重载7.完整代码 二、rbegin&#xff08;&#xff09;以及rend&#xff08;&#xff09;1.rb…

[nlp] TF-IDF算法介绍

&#xff08;1&#xff09;TF是词频(Term Frequency) 词频是文档中词出现的概率。 &#xff08;2&#xff09; IDF是逆向文件频率(Inverse Document Frequency) 包含词条的文档越少&#xff0c;IDF越大。

01-导数的定义_左导数和右导数

微积分 导数的定义 左导数与右导数、可导函数 趋近于 0 有两个方向&#xff0c;从左边趋向于 0 是左导数&#xff0c;反之是右导数 下面的绝对值函数的左导数和右导数不相同&#xff0c;一个-1 一个1&#xff0c;0 位置不可导 f(x)|x|&#xff0c; 导数可以理解为某点的斜率…

生命在于学习——指纹混淆技术学习

一、前言 本篇文章仅为学习笔记记录&#xff0c;不得用于违规用途。 本篇文章为安全社公众号的Poker安全所发&#xff0c;本文仅为学习复现。 二、介绍 指纹混淆技术&#xff0c;顾名思义&#xff0c;就是迷惑指纹扫描识别技术。 三、思路 作者的思路&#xff1a; 1、伪…

代码随香录day31

今天开始贪心算法了&#xff01; 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 455. 分发饼干 这里的思路…

openEuler?搭建java开发环境的详细过程

目录 1. 初始化环境2. 安装jdk83. 安装SVN4. 安装Git5. 安装Node.js6. 下载并激活IntelliJ IDEA7. 下载并激活Navicat 本文操作系统及版本号&#xff1a;↓ openEuler release 22.03 LTS Linux version 5.10.0-60.35.0.64.oe2203.x86 _64 1. 初始化环境 ? 1 2 3 4 # 1. 更新…

Spring事务的传播机制与隔离级别

目录 前言事务的隔离级别事务特性Spring 中设置事务隔离级别MySQL的隔离级别Spring中的隔离级别 Spring的传播机制事务传播机制是什么&#xff1f;为什么需要事务传播机制&#xff1f;事务传播机制有哪些&#xff1f; 事务的隔离级别 与 传播机制 解决的问题 前言 无论对于那个…

2020年全国硕士研究生入学统一考试管理类专业学位联考写作试题——解析版

四、写作第56~57小题&#xff0c;共65分。其中论证有效性分析30分&#xff0c;论说文35分。 56. 论证有效性分析&#xff1a;分析下述论证中存在的缺陷和漏洞&#xff0c;选择若干要点&#xff0c;写一篇600字左右的文章&#xff0c;对该论证的有效性进行分析和评论。( 论证有…

自动装配再次理解

随便点进去一个自动装配类&#xff0c;也就是spring.factories 文件下的一个全限定名指定的一个配置类 里面有个内部类 Encoding 类 这个注解是绑定了yaml文件&#xff0c;通过前缀可以往里面赋值&#xff0c;来实现自定义配置Springboot 了解完自动装配的原理后&#xff0c;我…

<C语言> 预处理和宏

1.预定义符号 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C&#xff0c;其值为1&#xff0c;否则未定义这些预定义符号都是C语言内置的。 举个例子&…

如何高效维护电脑

电脑维护技巧&#xff1a;让你的电脑始终高效稳定 电脑维护技巧&#xff1a;让你的电脑始终高效稳定引言方向一&#xff1a;介绍你的电脑方向二&#xff1a;介绍一下你的日常维护措施方向三&#xff1a;给出一些你觉得有用的维护技巧方向四&#xff1a;其他你想补充的方向五&am…

苍穹外卖学习心得与总结【对比瑞吉】【如何获得铁粉】

对于苍穹外卖项目&#xff0c;从学习课程加复习已经13天了。 对于一名已经学习过SSMLinuxRedis数据库的Java练习生来说&#xff0c;这个项目相对于之前学习的《瑞吉外卖》新增了很多功能和技术&#xff0c;是很值得练手和提升的课程&#xff0c;下面给出自己的一些见解。&#…

【点云处理教程】02从 Python 中的深度图像估计点云

一、说明 这是“点云处理”教程的第二篇文章。“点云处理”教程对初学者友好&#xff0c;我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。在本教程中&#xff0c;我们将学习如何在不使用 Open3D 库的情况下从深度图像计算点云。我们还将展示如何优化代码以获…