欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld
技术交流QQ群:433250724,欢迎对算法、技术、应用感兴趣的同学加入


双调排序是data-independent的排序, 即比较顺序与数据无关的排序方法, 特别适合做并行计算,例如用GPU、fpga来计算。

1、双调序列

在了解双调排序算法之前,我们先来看看什么是双调序列。 双调序列是一个先单调递增后单调递减(或者先单调递减后单调递增)的序列。

2、Batcher定理

将任意一个长为2n的双调序列A分为等长的两半X和Y,将X中的元素与Y中的元素一一按原序比较,即a[i]与a[i+n] (i <
n)比较,将较大者放入MAX序列,较小者放入MIN序列。则得到的MAX和MIN序列仍然是双调序列,并且MAX序列中的任意一个元素不小于MIN序列中的任意一个元素[2]。

3、双调排序

假设我们有一个双调序列,则我们根据Batcher定理,将该序列划分成2个双调序列,然后继续对每个双调序列递归划分,得到更短的双调序列,直到得到的子序列长度为1为止。这时的输出序列按单调递增顺序排列。

见下图:升序排序,具体方法是,把一个序列(1…n)对半分,假设n=2^k,然后1和n/2+1比较,小的放上,接下来2和n/2+2比较,小的放上,以此类推;然后看成两个(n/2)长度的序列,因为他们都是双调序列,所以可以重复上面的过程;总共重复k轮,即最后一轮已经是长度是2的序列比较了,就可得到最终的排序结果。

双调排序示意图[1]:

4、任意序列生成双调序列

前面讲了一个双调序列如何排序,那么任意序列如何变成一个双调序列呢?

这个过程叫Bitonic merge, 实际上也是divide and conquer的思路。 和前面sort的思路正相反,
是一个bottom up的过程——将两个相邻的,单调性相反的单调序列看作一个双调序列,
每次将这两个相邻的,单调性相反的单调序列merge生成一个新的双调序列, 然后排序(同3、双调排序)。
这样只要每次两个相邻长度为n的序列的单调性相反,
就可以通过连接得到一个长度为2n的双调序列,然后对这个2n的序列进行一次双调排序变成有序,然后在把两个相邻的2n序列合并(在排序的时候第一个升序,第二个降序)。
n开始为1, 每次翻倍,直到等于数组长度, 最后就只需要再一遍单方向(单调性)排序了。

以16个元素的array为例,
1. 相邻两个元素合并形成8个单调性相反的单调序列,
2. 两两序列合并,形成4个双调序列,分别按相反单调性排序
3. 4个长度为4的相反单调性单调序列,相邻两个合并,生成两个长度为8的双调序列,分别排序
4. 2个长度为8的相反单调性单调序列,相邻两个合并,生成1个长度为16的双调序列,排序

示意图[1]:

详细Bitonic merge图(本图只画到生成一个16长的双调序列,最后排序没有画出):

最后再放一个8个元素排序的示意图[5]:

5、非2的幂次长度序列排序

这样的双调排序算法只能应付长度为2的幂的数组。那如何转化为能针对任意长度的数组呢?一个直观的方法就是使用padding。即使用一个定义的最大或者最小者来填充数组,让数组的大小填充到2的幂长度,再进行排序。最后过滤掉那些最大(最小)值即可。这种方式会使用到额外的空间,而且有时候padding的空间比较大(如数组长度为1025个元素,则需要填充到2048个,浪费了大量空间)。但是这种方法比较容易转化为针对GPU的并行算法。所以一般来说,并行计算中常使用双调排序来对一些较小的数组进行排序[3]。
如果要考虑不用padding,用更复杂的处理方法,参考[4] n!=2^k的双调排序网络,本文略。

参考资料

[1] CUDA(六). 从并行排序方法理解并行化思维——冒泡、归并、双调排序的GPU实现, http://blog.csdn.net/abcjennifer/article/details/47110991
[2] 并行计算】Bitonic Sort(双调排序)基础, http://blog.csdn.net/jiange_zh/article/details/49533477
[3] 双调排序:从串行到并行,以及OpenCL上的实现, http://blog.csdn.net/bryanlai0720/article/details/45094675
[4] n!=2^k的双调排序网络, http://blog.csdn.net/ljiabin/article/details/8630627
[5] 分段双调排序实现, http://blog.csdn.net/u014226072/article/details/56840243

双调排序--GPU/AIPU适合的排序【转载】的更多相关文章

  1. Python线性时间排序——桶排序、基数排序与计数排序

    1. 桶排序 1.1 范围为1-M的桶排序 如果有一个数组A,包含N个整数,值从1到M,我们可以得到一种非常快速的排序,桶排序(bucket sort).留置一个数组S,里面含有M个桶,初始化为0.然 ...

  2. C++ map排序(按照value值排序)_glp_hit_新浪博客

    C++ map排序(按照value值排序)_glp_hit_新浪博客     C++ map排序(按照value值排序)    (2012-07-12 14:19:51)    转载▼    标签:  ...

  3. Java排序算法(四):Shell排序

    [基本的想法] 将原本有大量记录数的记录进行分组.切割成若干个子序列,此时每一个子序列待排序的记录个数就比較少了,然后在这些子序列内分别进行直接插入排序,当整个序列都基本有序时.再对全体记录进行一次直 ...

  4. C++ STL中Map的相关排序操作:按Key排序和按Value排序 - 编程小径 - 博客频道 - CSDN.NET

    C++ STL中Map的相关排序操作:按Key排序和按Value排序 - 编程小径 - 博客频道 - CSDN.NET C++ STL中Map的相关排序操作:按Key排序和按Value排序 分类: C ...

  5. [译]async/await中使用阻塞式代码导致死锁 百万数据排序:优化的选择排序(堆排序)

    [译]async/await中使用阻塞式代码导致死锁 这篇博文主要是讲解在async/await中使用阻塞式代码导致死锁的问题,以及如何避免出现这种死锁.内容主要是从作者Stephen Cleary的 ...

  6. 由Maximum Gap,对话桶排序,基数排序和统计排序

    一些非比较排序 在LeetCode中有个题目叫Maximum Gap.是求一个非排序的正数数列中按顺序排列后的最大间隔.这个题用桶排序和基数排序都能够实现.以下说一下桶排序.基数排序和计数排序这三种非 ...

  7. 备战秋招之十大排序——O(n^2)级排序算法

    一.冒泡排序 冒泡排序是入门级的算法,但也有一些有趣的玩法.通常来说,冒泡排序有三种写法: 一边比较一边向后两两交换,将最大值 / 最小值冒泡到最后一位: 经过优化的写法:使用一个变量记录当前轮次的比 ...

  8. Jtable 表格按多列排序(支持中文汉字排序)

    这两天公司让做一个Jtable表格的排序,首先按A列排序,在A列相等时按B列排序,B列相等时按C列排序,ABC三列可以任意指定,最多分三列,这样的一个需求.由于我是大神,所以必须做了出来.ok,不自恋 ...

  9. SQL语句分组排序,多表关联排序

    SQL语句分组排序,多表关联排序总结几种常见的方法: 案例一: 在查询结果中按人数降序排列,若人数相同,则按课程号升序排列? 分析:单个表内的多个字段排序,一般可以直接用逗号分割实现. select ...

  10. 排序系列 之 简单选择排序及其改进算法 —— Java实现

    简单选择排序算法: 基本思想: 在待排序数据中,选出最小的一个数与第一个位置的数交换:然后在剩下的数中选出最小的数与第二个数交换:依次类推,直至循环到只剩下两个数进行比较为止. 实例: 0.初始状态 ...

随机推荐

  1. vs code for macOS的安装

    参考下载链接:http://www.pc6.com/mac/147684.html 汉化方法: 中文设置方法(如下图)在插件设置的搜索栏中输入"chinese",选择第一个简体中文 ...

  2. Xilinx-英文缩写

    BEL: Basic Element of Logic, BEL是最底层的基本元素,也可以叫atomic unit(原子单位),BEL是FPGA中最小.不可分割的组件. ACP:Accelerator ...

  3. 使用 p7zip 加密解密

    1. 安装 yum install p7zip p7zip-plugins 2. 加密打包 7z a -ptest test.7z test.php -p 密码 test.php 可以是目录 或者 多 ...

  4. 快速搭建maven私服仓库并配置

    1.第一步,通过官方网站下载tar.gz包上传到服务器并解压 随后进入解压目录,并执行./bin/nexus start 此时可能会出现如下异常 处理这个问题很容易,找到bin下的nexus文件,vi ...

  5. python语法中的左值、右值和字符

    位置决定语义 在下面的python代码中,忽略掉语法错误,源码中同样一个单词tsecer在不同的位置有不同的意义 import之后 在import之后的tsecer是作为一个简单的字面字符串来处理:这 ...

  6. SAP 没有开工的产线 闲置成本 处理方案

    SAP  没有开工的产线   闲置成本  处理方案 需要沟通的请联系  wx  :erpworld

  7. redis常用命令之Hash

    redis常用命令之Hash Hash常用命令 redis 可以理解为一个全局的大字典,key就是数据的唯一标识符.对应的key不同,value也不同.redis有5个基本的数据类型. 1 redis ...

  8. RabbitMQ学习第七章:消息确认机制之事务机制

    RabbitMQ消息确认机制之事务机制. RabbitMQ中,我们可以通过持久化数据 解决RabbitMQ服务器异常 的数据丢失问题. 问题:生产者将消息发送出去,消息到底有没有到达RabbitMQ服 ...

  9. JS中有关(...)的介绍

    1,深拷贝一个对象 如上图所示,obj和tmp是完全两个独立的对象,互不影响. 2,数组复制 如上图所示,arr和tmp是两个完全独立的数组,彼此之间的值互不影响. 3,函数形参中的使用 这里的... ...

  10. Python接口测试request

    requests安装 用pip安装requests模块 pip install requests 一.Get的使用 格式:get(url, params=None, **kwargs) Get常见查询 ...