news 2026/7/4 10:03:26

高性能计算之OpenMP——超算习堂学习2

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
高性能计算之OpenMP——超算习堂学习2

OpenMP学习2——超算习堂

一、for指令的使用方法细嚼

1.1、parallel for指令的用法

在OpenMP并行程序设计中,for循环是一种独立的并行指令。它非常重要!它的指令格式是:

#include<omp.h>#pragmaomp parallelforfor(i=begin;i<end;++i){// Content}
十分需要注意的是:

parallel for指令的后面必须要紧跟for语句块!!!!

并且for循环并行必须要处在parallel并行区块内!!!!否则会当作串行执行!

1.2、parallel for指令的执行机制

此前一篇博客已经说明了,OpenMP的并行计算模式是插入并行语句的方法,如上图。当我们的串行程序执行到并行语句块的时候,会从主线程中派生出线程组,然后线程组对计算任务进行均分,然后并行计算。并行计算结束后重新回到串行程序。

1.3、parallel for并行程序设计案例

案例1:计算两个向量的点乘
#include<omp.h>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>constintmaxn=5e7;constintmod=10000;intvec1[maxn],vec2[maxn],vec[maxn],i;intmain(){srand((unsignedint)time(NULL));for(i=0;i<maxn;++i){vec1[i]=rand()%mod;vec2[i]=rand()%mod;}printf("--------------before parallel compute---------------\n");clock_t s,t;s=clock();for(i=0;i<maxn;++i){vec[i]=vec1[i]*vec2[i];}t=clock();printf("--------------used time = %d ms---------------\n",t-s);s=clock();printf("--------------enter parallel compute---------------\n");#pragmaomp parallelnum_threads(20)shared(vec1,vec2,vec)private(i){#pragmaompforfor(i=0;i<maxn;++i){vec[i]=vec1[i]*vec2[i];}}t=clock();printf("--------------used time = %d ms---------------\n",t-s);return0;}
计算效率对比:

案例2:parallel for并行计算矩阵乘法
#include<omp.h>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>constintmaxn=1000;constintmod=10000;intvec1[maxn][maxn],vec2[maxn][maxn],vec[maxn][maxn],i,j,k;intmain(){srand((unsignedint)time(NULL));for(i=0;i<maxn;++i){for(j=0;j<maxn;++j){vec1[i][j]=rand()%mod;vec2[i][j]=rand()%mod;}}printf("--------------before parallel compute---------------\n");clock_t s1,t1,s2,t2;s1=clock();for(i=0;i<maxn;++i){for(j=0;j<maxn;++j){for(k=0;k<maxn;++k){vec[i][j]+=(vec1[i][k]*vec2[k][j]);}}}t1=clock();printf("----------------used time = %d ms-----------------\n",t1-s1);printf("--------------enter parallel compute---------------\n");s2=clock();#pragmaomp parallelforcollapse(2)schedule(dynamic)private(i,j,k)shared(vec1,vec2,vec)for(i=0;i<maxn;++i){for(j=0;j<maxn;++j){for(k=0;k<maxn;++k){vec[i][j]+=(vec1[i][k]*vec2[k][j]);}}}t2=clock();printf("----------------used time = %d ms-----------------\n",t2-s2);printf("\n----------------the speedup ratio = %lf---------------\n",1.0*(t1-s1)/(t2-s2));return0;}
运行结果如下:

1.4、运用omp parallel for的一些注意事项

第一:omp parallel for 和 omp for 不要混用

一旦在前面有使用过

#pragmaomp parallel...

语句,并且当前还处在这个并行区,然后这个时候你想使用for循环并行,则千万不要再搞一次:

#pragmaomp parallelfor

这样的操作了,因为这样会让线程组重组,然后相当于有两重并行,举个例子看看:

在有#pragma omp parallel 的并行区下运行
#include<omp.h>#include<iostream>usingnamespacestd;intmain(){#pragmaomp parallelnum_threads(10){#pragmaompforfor(inti=0;i<5;++i){#pragmaomp critical{cout<<"i = "<<i<<endl;}}}return0;}

此时的运行结果是:

然后如果你多此一举多搞一遍parallel命令就会:
#include<omp.h>#include<iostream>usingnamespacestd;intmain(){#pragmaomp parallelnum_threads(4){#pragmaomp parallelfor// 注意看这里哦for(inti=0;i<5;++i){#pragmaomp critical{cout<<"i = "<<i<<endl;}}}return0;}

看看这样的“多此一举”的运行结果:

我们会发现,这个0 ~ 4 被重复执行啦!这样会影响并行程序结果,还会误以为运行的开销变大哦!!!!

造成这种结果的原因就是:parallel命令会告诉操作系统,此时我要重组线程组,要重新开始并行程序运行。然后这下好啦,每个线程到了那句指令的时候都重组线程组,白白多执行4次(取决于线程数)

二、多线程下数据访问同步

2.1、同步一词在并行计算的含义

其实同步啊,在并行计算里有两种含义:

第一:线程/进程的运行有的快有的慢,我想要在某处各个线程/进程达到同样的状态,这叫并行程序的运行同步

第二:对于共享内存的模型,我们需要控制数据的访问,达到线程同步。这样做的目的是为了防止多个进程/线程同时访问某个数据、内存,导致该数据同时改变,这样的作用下会让数据失真!举个例子:初始有变量a = 2,比如线程A要让a++,线程B要让a*=2。如果不控制访问,让变量a(或者某语句块)的执行的时候只能让一个线程进入执行,其他线程等待执行。则会让资源出现同步问题。这就叫数据同步。

2.2用critical创建临界区的方式避免线程同步危害

#include<omp.h>#include<iostream>usingnamespacestd;intmain(){inti,len,cnt=0;#pragmaomp parallelnum_threads(6){len=omp_get_num_threads();#pragmaompforprivate(i)for(i=0;i<len;++i){#pragmaomp critical{cout<<"Current is "<<i<<endl;cnt+=i;}}}cout<<"cnt = "<<cnt<<endl;return0;}
利用critical指令完成线程同步的运行结果:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 10:01:06

vue 延迟加载

setTimeout(() > {console.log(延迟加载的内容);}, 3000);草率吗&#xff1f; 哈哈哈哈哈

作者头像 李华
网站建设 2026/7/4 10:00:34

Python初学者笔记--第一天(面试题)

本文整理了几道之前面试中遇到的题目&#xff0c;以便后期复习查看。 1.统计数组中数字出现次数&#xff0c;如果只出现一次&#xff0c;输出TRUE&#xff0c;否则输出FALSE#第一种&#xff1a;列表中的数 list1 list(map(int, input().split())) #输入一个数组 list2 set…

作者头像 李华
网站建设 2026/7/4 10:00:01

《经典递归问题:汉罗塔》

&#x1f320;作者&#xff1a;TheMythWS. &#x1f387;座右铭&#xff1a;不走心的努力都是在敷衍自己&#xff0c;让自己所做的选择&#xff0c;熠熠发光。 目录 ✨汉罗塔的介绍 图解游戏​ ✨N层汉罗塔需移动的次数 ✨汉罗塔的代码实现 c语言实现&#xff1a; 运行结…

作者头像 李华
网站建设 2026/7/4 9:59:46

回溯题目:复原 IP 地址

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;复原 IP 地址 出处&#xff1a;93. 复原 IP 地址 难度 5 级 题目描述 要求 有效 IP 地址由恰好四个整数和分隔整数的点组成。每个整数在范围 0 \…

作者头像 李华
网站建设 2026/7/4 9:58:28

统计字符串中数字、字母、其他字符的出现次数

【问题描述】从键盘输入一个字符串&#xff0c;分别统计数字&#xff0c;字母&#xff08;包括大小写&#xff09;和其他字符的个数&#xff0c;输出每个字符及其个数。要求&#xff1a;用字典进行统计。【输入形式】输入一个随机字符串 【输出形式】输出为记录统计的结果&…

作者头像 李华
网站建设 2026/7/4 9:57:53

PowerShell 获取AD域用户属性

1、查看指定用户信息Get-ADUser -Identity zhangsan# 显示 DistinguishedName : CNzhang san,OUSHA,DCmsh,DClocal Enabled : True GivenName : zhang Name : zhang san ObjectClass : user ObjectGUID : 7aa0a36a-4e9f-48b8-87dd…

作者头像 李华