使用omp并行技术实现快排加速

news2024/12/23 19:26:10

快排基本原理:

快速排序可以说是最为常见的排序算法,冒泡排序时间复杂度达到了O(N2),而桶排序容易造成浪费空间。快排(Quicksort)就成为了不错的选择。

1、原理:快排需要找一个数作为基准数,用来参照。(可取第一个数为参照)

        基准数在中间某位置,两端有指针,找到相应数后,交换。

注意:若令第一个数为基准数,先从右往左找,再从左往右找。

2、优点:平均时间复杂度O(NlogN),相比冒泡排序每次交换可以是跳跃式的

排序过程:

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 分配线程。

代码实现:

#include<stdio.h>
#include<omp.h>
#include<time.h>
#include<stdlib.h>

int Partition(int* data, int start, int end)   //划分数据
{
    int temp = data[start];   //以第一个元素为基准
    while (start < end) {
        while (start < end && data[end] >= temp)end--;   //找到第一个比基准小的数
        data[start] = data[end];
        while (start < end && data[start] <= temp)start++;    //找到第一个比基准大的数
        data[end] = data[start];
    }
    data[start] = temp;   //以基准作为分界线
    return start;
}

void quickSort(int* data, int start, int end)  //并行快排
{
    if (start < end) {
        int pos = Partition(data, start, end);
        #pragma omp parallel sections    //设置并行区域
        {
            #pragma omp section          //该区域对前部分数据进行排序
            quickSort(data, start, pos - 1);
            #pragma omp section          //该区域对后部分数据进行排序
            quickSort(data, pos + 1, end);
        }
    }
}

int main(int argc, char* argv[])
{
    int n = atoi(argv[2]), i;   //线程数
    int size = atoi(argv[1]);   //数据大小
    int* num = (int*)malloc(sizeof(int) * size);

    double starttime = omp_get_wtime();
    srand(time(NULL) + rand());   //生成随机数组
    for (i = 0; i < size; i++)
        num[i] = rand();
    omp_set_num_threads(n);   //设置线程数
    quickSort(num, 0, size - 1);   //并行快排
    double endtime = omp_get_wtime();

    for (i = 0; i < 10 && i<size; i++)//输出前十个元素
        printf("%d ", num[i]);
    printf("\n并行时间:%lfs\n", endtime - starttime);
    return 0;
}

 主要用到的omp加速代码为:

void quickSort(int* data, int start, int end)  //并行快排
{
    if (start < end) {
        int pos = Partition(data, start, end);
        #pragma omp parallel sections    //设置并行区域
        {
            #pragma omp section          //该区域对前部分数据进行排序
            quickSort(data, start, pos - 1);
            #pragma omp section          //该区域对后部分数据进行排序
            quickSort(data, pos + 1, end);
        }
    }
}

运行结果:

Omp快排结果:

仅输出前十个数字。

 编译:g++ ./filename.cpp -o ./filename -fopenmp

运行:./filename n   n为所设置的线程数

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

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

相关文章

【Nexus】上传jar至Nexus的两种方式

目录 一、前言二、pom文件添加推送代码配置1、配置pom.xml文件2、配置maven的settings.xml文件3、执行上传①、点击Maven-Lifecycle-deploy-Run Maven Build②、出现以下提示则上传成功③、这时&#xff0c;在Nexus的nexus-snapshot-hosted&#xff08;快照类型的托管资源库&am…

【Python】函数进阶 ③ ( 函数作为参数传递 )

文章目录 一、函数参数传递类型二、代码示例 - 函数参数传递类型 一、函数参数传递类型 之前介绍的函数 , 都是 接收具体的 变量 或 字面量 数据 作为参数 , 如 : 数字 / 布尔值 / 字典 / 列表 / 元组 等 ; 函数 也可以作为参数 , 传入另一个函数中 ; 在 Python 中&#xff0…

主成分分析——SPSS实例分析

主成分分析是用原始变量的线性组合来表示主成分&#xff0c;且主成分彼此之间互不相关&#xff0c;且能反映出原始数据的绝大部分信息。 一般来说&#xff0c;当研究的问题涉及到多变量且变量之间存在很强的相关性时&#xff0c;我们可考虑使用主成分分析的方法来对数据进行简化…

智能的突破或许在智能之外

人工智能已经取得了不少令人瞩目的成果&#xff0c;但是仍然存在着许多问题和挑战&#xff0c;这些问题和挑战也许只能通过跨学科的合作和人类的智慧来解决&#xff0c;因此智能的突破在智能之外。在人工智能的决策过程中&#xff0c;往往会缺乏人类的道德判断和社会责任感&…

2018年全国硕士研究生入学统一考试管理类专业学位联考英语(二)试题

2018 年全国硕士研究生入学统一考试 管理类专业硕士学位联考 英语&#xff08;二&#xff09;试卷 考生须知 1&#xff0e;考生必须严格遵守各项考场规则。 2&#xff0e;答题前&#xff0c;考生将答题卡上的“姓名”、“考生编号”等信息填写清楚&#xff0c;并与准考证上的致…

【SpringCloud】Eureka 案例上手稍微带点原理

文章目录 1. 前置工作1.1 搭建 user-server1.1.1 pom1.1.2 po&#xff0c;mapper&#xff0c;controller1.1.3 yml1.1.4 启动类1.1.5 启动并访问 1.2 搭建 order-server1.2.1 pom1.2.2 po mapper controller1.2.3 yml1.2.4 启动类1.2.5 启动并访问 1.3 两个服务通信 2. Eureka2…

Qt Xml的读、写、修改、删除

一、说明 Xml文件的创建、读取、修改、删除以下图格式为例。 二、导入xml QT core gui xml三、创建Xml void MainWindow::Xml_Write(QString path) {//! 打开或创建文件QFile file(path);if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return; //! …

【MySQL篇】Select语句原理详解

文章目录 MYSQL体系结构模块详解架构分层连接层服务层存储引擎 SQL的执行流程连接查询缓存语法解析和预处理词法解析语法分析预处理器 查询优化器执行计划存储引擎存储引擎基本介绍如何选择存储引擎&#xff1f; 执行引擎举例说明 对于一个开发工程师来说&#xff0c;了解一下 …

C语言读写ini配置文件

环境 windows 10 64bitClion 2023.1 ini简介 ini 文件格式是一种用于保存配置信息的简单文本格式。它通常由多个节(section)组成&#xff0c;每个节包含多个键值对(key-value pair)。 下面是 ini 文件的基本语法规则 一个ini文件由多个节组成&#xff0c;每个节用方括号([])括起…

《Java黑皮书基础篇第10版》 第17章【笔记】

第十七章 二进制I/O 17.1 引言 文件可以不严谨的分类为文本文件和二进制文件。文本文件指的是可以用文件编辑器进行查看和修改的&#xff0c;二进制文件则不可以使用文本编辑器查看和修改。 例如&#xff0c;Test.java文件储存在文本文件中&#xff0c;因此可以用文本编辑器…

MapReduce程序基本架构

MapReduce程序是以&#xff08;键/值&#xff09;对的形式来处理数据的&#xff0c;即可以通过以下的形式来表示&#xff1a; map: (K1,V1) ➞ list(K2,V2) reduce: (K2,list(V2)) ➞ list(K3,V3) 不令人惊奇的是&#xff0c;这是一种超越一般数据的数据流表示形式。在本文中…

使用PyMC进行时间序列分层建模

在统计建模领域&#xff0c;理解总体趋势的同时解释群体差异的一个强大方法是分层(或多层)建模。这种方法允许参数随组而变化&#xff0c;并捕获组内和组间的变化。在时间序列数据中&#xff0c;这些特定于组的参数可以表示不同组随时间的不同模式。 今天&#xff0c;我们将深…

ood的5C解题法(1)----管理类面试对象设计

管理类 概念 可以模拟/代替管理员日常工作的系统 下面用停车场系统做演示 答题流程 Clarify What&#xff1a;除题目中的名词外&#xff0c;从管理的名词考虑 parking lot是什么类型的&#xff1f;如果楼有多层&#xff0c;停车位也是多层&#xff0c;则parking lot->pa…

Windows Server 2019 OVF, updated Jun 2023 (sysin) - VMware 虚拟机模板

Windows Server 2019 OVF, updated Jun 2023 (sysin) - VMware 虚拟机模板 2023 年 6 月版本更新&#xff0c;现在自动运行 sysprep&#xff0c;支持 ESXi Host Client 部署 请访问原文链接&#xff1a;https://sysin.org/blog/windows-server-2019-ovf/&#xff0c;查看最新…

5、产品经理的工作职责OR主要工作技能和工具

1、产品经理的工作职责 我们通过一个案例来了解产品经理的工作职责。 老板让你给他点餐&#xff0c;你应该怎么做&#xff1f;你需要考虑哪一些方面的问题&#xff1f; 例如&#xff1a;你预算多少&#xff0c;预算是十块钱还是100块还是1000块。有没有忌口&#xff0c;口味…

【MYSQL篇】Update语句原理详解

文章目录 前言缓冲池Buffer PoolInnoDB 内存结构redo logundo logBinlog 总结 前言 前面的文章我们已经对MySQL的查询语句的执行流程进行了说明&#xff0c;感兴趣的可以去看看&#xff1a; 【MySQL篇】Select语句原理详解 本篇文章我们来聊聊 MySQL更新语句的执行原理。更新…

Win7系统提示Windows Defender无法扫描选定的文件解决方法

Win7 64位系统提示“Windows Defender无法扫描选定的文件”怎么办呢?使用Windows Defender扫描文件,结果弹出如下图窗口,该怎么解决呢,参考下文,一起来解决Win7系统提示“Windows Defender无法扫描选定的文件”的解决方法。 原因分析: 这是因为开启Defender扫描压…

java的序列化注解Serial、序列化版本号serialVersionUID

例如&#xff0c;jdk源码NTLMException类的定义&#xff0c;其中涉及到了序列化注解Serial和序列化版本号字段serialVersionUID&#xff1a; 序列化注解java.io.Serial&#xff1a; 序列化注解java.io.Serial是在javaSE-14版本引入的。通常注解实现了序列化类的序列化相关的函…

【JUC进阶】02. volatile关键字

目录 1、回顾JMM 1.1、可见性&#xff08;Visibility&#xff09; 1.2、原子性&#xff08;Atomicity&#xff09; 1.3、有序性&#xff08;Ordering&#xff09; 2、volatile 2.1、保证可见性 2.2、不保证原子性 2.3、防止指令重排 2.4、什么时候使用volatile 3、小…

微服务中「组件」集成

有品&#xff1a;There is no silver bullet&#xff1b; 一、简介 在微服务工程的技术选型中&#xff0c;会涉及到很多组件的集成&#xff0c;最常用包括&#xff1a;缓存、消息队列、搜索、定时任务、存储等几个方面&#xff1b; 如果工程是单服务&#xff0c;对于集成组件…