使用omp并行技术加速bfs广度优先算法

news2024/10/6 10:43:08

基本思想

   从初始状态S开始,利用规则,生成所有可能的状态。构成树的下一层节点,检查是否出现目标状态G,若未出现,就对该层所有状态节点,分别顺序利用规则。生成再下一层的所有状态节点,对这一层的所有状态节点检查是否出现G,若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开。直到出现目标状态为止。

.算法步骤

(1)把起始节点S线放到queue 表中克祥

  (2)如果queue是空表,则失败退出,否则继续。

  (3)在queue表中取最前面的节点node 移到 CL OSED 表中。(出队)

  (4)扩展node节点。若没有后继即叶节点),则转向(2)循环。

  (5)把node的所有后继节点放在queue表的末端。各后继结点指针指向node节点。(入队)

  (6)若后继节点中某一个是目标节点,则找到一个解,成功退出。否则转向(2)循环。

omp并行加速:

使用#pragma omp parallel for shared(vis)

#pragma omp parallel for shared(vis, q)

共享数据

使用#pragma omp critical

防止越界。

算法实现:

#include <iostream>
#include <queue>
#include <fstream>
#include <omp.h>
using namespace std;

const int MAXN =4039; // 最大节点数
bool vis[MAXN]; // 标记数组,记录节点是否被访问过
int G[MAXN][MAXN]; // 图的邻接矩阵
//int n; // 节点数

void bfs(int s, ofstream& out) {
queue<int> q;
q.push(s);
vis[s] = true;
while (!q.empty()) 
{
int u = q.front();
q.pop();
out << u << " "; // 将节点编号输出到文件中
#pragma omp parallel for shared(vis, q)
for (int v = 0; v < MAXN; v++) {
if (G[u][v] && !vis[v]) {
#pragma omp critical
{
q.push(v);
vis[v] = true;
}
}
}
}
}

int main(int argc, char *argv[]) {

int n = atoi(argv[1]);   //线程数

ifstream inFile("input.txt"); // 从文件中读取图的信息
int u,v;
while(inFile >> u >> v) //假设每一行插入一条边u->v
{
G[u][v]=1;
}

inFile.close();

ofstream outFile("output_omp.txt"); // 将结果保存到文件中
double starttime = omp_get_wtime();
omp_set_num_threads(n);   //设置线程数
#pragma omp parallel for shared(vis)
for (int i = 0; i < MAXN; i++) {
if (!vis[i]) {
bfs(i, outFile);
}
}
outFile.close();
double endtime = omp_get_wtime();
printf("\n并行时间:%lfs\n", endtime - starttime);
return 0;
}

运行结果:

Omp运行结果:

加速比:0.021814/0.014498=1.504621327079597

Omp结果:

数据集下载:数据集

提取码:k3v2

OpenMP基本概念
OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C、C++和Fortran。OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度。当编译器不支持OpenMP时,程序会退化成普通(串行)程序。程序中已有的OpenMP指令不会影响程序的正常编译运行。

在VS中启用OpenMP很简单,很多主流的编译环境都内置了OpenMP。在项目上右键->属性->配置属性->C/C++->语言->OpenMP支持,选择“是”即可。

OpenMP执行模式
OpenMP采用fork-join的执行模式。开始的时候只存在一个主线程,当需要进行并行计算的时候,派生出若干个分支线程来执行并行任务。当并行代码执行完成之后,分支线程会合,并把控制流程交给单独的主线程。

一个典型的fork-join执行模型的示意图如下:

OpenMP编程模型以线程为基础,通过编译制导指令制导并行化,有三种编程要素可以实现并行化控制,他们分别是编译制导、API函数集和环境变量。

编译制导
编译制导指令以#pragma omp 开始,后边跟具体的功能指令,格式如:#pragma omp 指令[子句[,子句] …]。常用的功能指令如下:

parallel:用在一个结构块之前,表示这段代码将被多个线程并行执行;
for:用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性;
parallel for:parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能;
sections:用在可被并行执行的代码段之前,用于实现多个结构块语句的任务分担,可并行执行的代码段各自用section指令标出(注意区分sections和section);
parallel sections:parallel和sections两个语句的结合,类似于parallel for;
single:用在并行域内,表示一段只被单个线程执行的代码;
critical:用在一段代码临界区之前,保证每次只有一个OpenMP线程进入;
flush:保证各个OpenMP线程的数据影像的一致性;
barrier:用于并行域内代码的线程同步,线程执行到barrier时要停下等待,直到所有线程都执行到barrier时才继续往下执行;
atomic:用于指定一个数据操作需要原子性地完成;
master:用于指定一段代码由主线程执行;
threadprivate:用于指定一个或多个变量是线程专用,后面会解释线程专有和私有的区别。
相应的OpenMP子句为: 


private:指定一个或多个变量在每个线程中都有它自己的私有副本;
firstprivate:指定一个或多个变量在每个线程都有它自己的私有副本,并且私有变量要在进入并行域或任务分担域时,继承主线程中的同名变量的值作为初值;
lastprivate:是用来指定将线程中的一个或多个私有变量的值在并行处理结束后复制到主线程中的同名变量中,负责拷贝的线程是for或sections任务分担中的最后一个线程; 
reduction:用来指定一个或多个变量是私有的,并且在并行处理结束后这些变量要执行指定的归约运算,并将结果返回给主线程同名变量;
nowait:指出并发线程可以忽略其他制导指令暗含的路障同步;
num_threads:指定并行域内的线程的数目; 
schedule:指定for任务分担中的任务分配调度类型;
shared:指定一个或多个变量为多个线程间的共享变量;
ordered:用来指定for任务分担域内指定代码段需要按照串行循环次序执行;
copyprivate:配合single指令,将指定线程的专有变量广播到并行域内其他线程的同名变量中;
copyin:用来指定一个threadprivate类型的变量需要用主线程同名变量进行初始化;
default:用来指定并行域内的变量的使用方式,缺省是shared。
利用omp_set_num_threads()来设置线程数,

利用#pragma omp parallel sections 声明下面大括号中的语句要并行多线程执行;

利用#pragma omp section 分配线程。

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

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

相关文章

chatgpt赋能python:Python在SEO中的排名

Python在SEO中的排名 Python作为一门高级编程语言&#xff0c;已经有近三十年的历史&#xff0c;被广泛用于各个领域的开发&#xff0c;包括 Web开发、数据分析、机器学习等。在 SEO 中&#xff0c;Python 也具有很高的应用价值。本文将会介绍 Python 在 SEO 中的应用以及其排…

C语言进阶教程(一个可执行文件生成的具体步骤)

文章目录 前言一、预处理二、编译三、汇编四、链接总结 前言 本篇文章来讲解一个.c文件生成一个可执行文件的完整过程&#xff0c;我们学习了那么久&#xff0c;只知道在编译器中按下编译运行就可以将一个.c文件运行起来了&#xff0c;但是我们并不了解其中的具体步骤&#xf…

【openGauss简单数据库管理---快速入门】

【openGauss简单数据库管理---快速入门】 &#x1f53b; 一、openGauss数据库管理&#x1f530; 1.1 连接openGauss数据库&#x1f530; 1.2 创建数据库&#x1f530; 1.3 查看数据库和切换数据库&#x1f530; 1.4 修改数据库&#x1f530; 1.5 删除数据库&#x1f530; 1.6 启…

高等代数复习(二)

本篇复习内容有 求解标准正交基 证明标准正交基 证明正交变换 利用共轭变换证明 求解与给定矩阵的相似矩阵--对角矩阵 1.求标准正交基 在求标准正交基时&#xff0c;通常要先正交化&#xff0c;然后单位化&#xff0c;即可求出标准正交基。 2.证明标准正交基 标准正交基单位…

chatgpt赋能python:Python提取指定位置字符

Python 提取指定位置字符 Python 是一种高级程序语言&#xff0c;其易读性、简单易学性和易维护性使其成为最受欢迎的编程语言之一。它可以用于各种数据分析和科学计算&#xff0c;包括搜索引擎优化&#xff08;SEO&#xff09;。 在SEO中&#xff0c;提取和处理数据是一个重…

C++——string容器模拟实现

目录 1. 基本成员变量 2. 默认成员函数 2.1 构造函数 2.2 析构函数 2.3 拷贝构造函数 2.4 赋值运算符重载 3. 容量与大小相关函数 3.1 size 3.2 capacity 4. 字符串访问相关函数 4.1 operator[ ]重载 4.2 迭代器 5. 增加函数接口 5.1 reserve 5.2 resize 5.3 …

【二叉树part01】| 二叉树的递归遍历、二叉树的迭代遍历

目录 ✿二叉树的递归遍历❀ ☞LeetCode144.前序遍历 ☞LeetCode145.二叉树的后序遍历 ☞LeetCode94.二叉树的中序遍历 ✿二叉树的迭代遍历❀ ☞LeetCode144.前序遍历 ☞LeetCode145.二叉树的后序遍历 ☞LeetCode94.二叉树的中序遍历 ✿二叉树的递归遍历❀ ☞LeetCode…

docker-compose启动opengauss数据库——华为“自研”数据库

文章目录 1. 启动数据库2. 登录2.1 本地登录2.2 远程登录 1. 启动数据库 yml文件 创建opengauss目录&#xff0c;里边创建docker-compose.yml文件内容如下&#xff1a; 华为开源数据库&#xff0c;默认5432端口&#xff0c;是不是很熟悉&#xff0c;疑似又是个套壳子的事件。果…

Cortext-M3系列:调试系统架构(8)

1、调试特性概述 单片机的调试功能在程序开发中有着十分重要的地位&#xff0c;好的调试工具&#xff0c;能让程序开发大大加快。笔者在刚开始学单片机相关知识时&#xff0c;使用的是pintf打印相关参数&#xff0c;进行调试&#xff08;虽然现在很多时候也这样&#xff09;&am…

MyBatis 的使用方法

观前提示:本篇博客演示使用的 IDEA 版本为2021.3.3版本,使用的是Java8(又名jdk1.8) 前端使用 VSCode(Visual Studio Code1.78.2) 电脑使用的操作系统版本为 Windows 10 目录 Mybatis是什么? Mybatis 有什么用? Mybatis 框架交流 Mybatis 项目环境搭建 1. 添加 Mybatis…

设计模式之生成器(建造者)模式笔记

设计模式之建造者模式笔记 说明Builder(生成器)目录UML生成器(建造者)模式示例类图自行车类建造者抽象类摩拜单车对象类小黄车单车对象类指挥者类测试类优缺点 模式扩展手机类测试类 说明 记录下学习设计模式-生成器(也叫建造者)模式的写法。 Builder(生成器) 意图:将一个复…

监控中的计算机科学

文章目录 一、前言二、监控分类2.1 模拟摄像头2.1 数字摄像头 三、监控系统四、后端产品4.1 硬盘录像机4.2 视频矩阵4.3 控制设备4.4 显示设备 五、传输端5.1 光纤视频线5.1.2 单模光纤5.1.3 多模光纤5.1.4 光端机 5.1 双绞线 六、畅享 一、前言 布林肯访华&#xff0c;黑我们…

Redis6之事务与锁

事务 Redis事务是一个单独的隔离操作&#xff1a;事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断。 Redis事务的主要作用就是串联多个命令防止别的命令插队。 命令 1、开启事务&#xff1a;multi 2、执行事…

STM32 RGB屏幕

使用ST的HAL库进行开发&#xff0c;RGB屏幕是480*272的4.3寸LCD&#xff0c;由于驱动RGB屏幕需要较多的内存&#xff0c; 所以使用了外部SDRAM&#xff0c;内存是32M字节&#xff0c;关于SDRAM的驱动本文不进行讨论。 RGB屏幕常用的像素格式有&#xff1a;ARGB8888、RGB888、…

Vue----Vue项目的目录结构

【原文链接】Vue----Vue项目的目录结构 Vue 项目的目录结构 VUE项目的目录结构如下所示 .vscode VSCode工具的配置文件&#xff0c;和VUE项目没有什么关系 node_modules VUE项目运行依赖文件&#xff0c;通过npm install 安装的文件即存放在此文件夹 public 资源文件夹&am…

【现代密码学】(网安)期末复习笔记

现代密码学 【考后感悟】还是得注重简答题&#xff0c;需每个密码算法都要有所了解&#xff08;有些难的可以不用了解完整算法过程&#xff0c;估计考不上&#xff1f;&#xff09;&#xff0c;并对几个重要密码算法&#xff08;重点下面会讲&#xff09;着重复习&#xff08;会…

部署kubernets v1.27.3集群

本文将演示如何使用kubeadm快速部署一个Kubernetes v1.27.1集群&#xff0c;并会简单说明如何在集群上部署nginx容器 主机环境预设 本示例中的Kubernetes集群部署将基于以下环境进行。 OS: Ubuntu 20.04 Kubernetes&#xff1a;v1.27.3 Container Runtime: Docker CE 23.0.…

【并发编程】深入探索AQS

文章目录 一、AQS 介绍二、通过ReentrantLock分析AQS的实现2.1、获取锁流程2.2、获取锁源码分析2.2.1、acquire2.2.2、tryAcquire2.2.3、addWaiter2.2.4、acquireQueued2.2.5、shouldParkAfterFailedAcquire 2.3、解锁源码分析2.3.1、unlock2.3.2、release2.3.3、tryRelease2.3…

实验篇(7.2) 17. 站对站安全隧道 - FortiGate作为SSL客户端(SSL) ❀ 远程访问

【简介】虽然常用的站到站的连接用的是IPsec VPN&#xff0c;但是在某些特殊情况下&#xff0c;UDP500或4500端口被阻断&#xff0c;IPsec VPN无法连接&#xff0c;那么还有其它办法实现站到站的连接吗&#xff1f;SSL VPN也可以的。 实验要求与环境 OldMei集团深圳总部部署了域…

NodeJS File Upload⑩

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言文件上传 后端接口 Form表单上传 Axios前后端分离上传 实现效果演示 记录 读取图片文件总结 ✨文章有误请指正&#xff0c;如果觉得对你有用&a…