在修改了少量元素后重新排序向量

时间:2014-09-15 19:31:05

标签: sorting sorting-network

如果我们有一个先前已排序的 N 大小的向量,并用任意值替换 M 元素(其中 M 是比 N 小得多,是否有一种简单的方法可以以较低的成本对其进行重新排序(即生成深度较小的分拣网络)而非完全排序?

例如,如果 N = 10且 M = 2,则输入可能

10 20 30 40 999 60 70 80 90 -1

注意:修改元素的索引是未知的(直到我们将它们与周围元素进行比较。)


以下是我知道解决方案的示例,因为输入大小很小,我可以通过强力搜索找到它:

如果N = 5且M为1,则这些是有效输入:

0 0 0 0 0     0 0 1 0 0     0 1 0 0 0     0 1 1 1 0     1 0 0 1 1     1 1 1 1 0

0 0 0 0 1     0 0 1 0 1     0 1 0 0 1     0 1 1 1 1     1 0 1 1 1     1 1 1 1 1

0 0 0 1 0     0 0 1 1 0     0 1 0 1 1     1 0 0 0 0     1 1 0 1 1

0 0 0 1 1     0 0 1 1 1     0 1 1 0 1     1 0 0 0 1     1 1 1 0 1

例如,如果先前排序的向量为0 1 1 0 1且第4个元素已被修改,则输入可能为0 1 1 1 1 ,但无法将0 1 0 1 0形成为有效输入,因为它与任何排序的矢量至少有2个元素不同。

这将是一个有效的排序网络,用于重新排序这些输入:

>--*---*-----*-------->
   |   |     | 
>--*---|-----|-*---*-->
       |     | |   |
>--*---|-*---*-|---*-->
   |   | |     |
>--*---*-|-----*---*-->
         |         |
>--------*---------*-->

我们并不关心此网络无法对某些无效输入进行排序(例如0 1 0 1 0。)

此网络的深度为4,与一般情况(a depth of 5 generally necessary to sort a 5-element vector相比,节省1。)

不幸的是,对于较大的输入尺寸,蛮力方法是不可行的。

是否有一种已知的方法可用于构建网络以重新排序较大的向量?

我的 N 值将在几百的数量级, M 不会超过√ N

2 个答案:

答案 0 :(得分:3)

好的,我发布这个作为答案,因为对长度的评论限制让我疯狂:)

你应该尝试一下:

  • 实现对本地内存工作的简单顺序排序(插入排序或类似的)。如果你不知道如何 - 我可以帮忙解决这个问题。
  • 只有一个工作项在N个元素块上执行排序
  • 计算每个工作组的本地内存的最大大小(使用clGetDeviceInfo调用CL_DEVICE_LOCAL_MEM_SIZE)并导出每个工作组的最大工作项数, 因为通过这种方法,您的工作项数量很可能会受到本地内存量的限制。

我怀疑这可能会运作得相当好,因为:

  • 一个简单的排序可能完全没问题,特别是因为数组已经在很大程度上排序了
  • 并行化这么少的项目是不值得的(不过使用本地内存!)
  • 因为您正在处理数十亿个这样的小型阵列,即使只有一个工作项处理这样的数组,您也会获得很大的占用率

如果您对我的想法有疑问,请告诉我。

编辑1:

我刚刚意识到我使用的技术可能让其他人感到困惑: 我对使用本地内存的提议不适用于单个输入向量/数组的同步或使用多个工作项。我只是用它来获得较低的读/写内存延迟。由于我们使用相当大的内存块,我担心使用私有内存可能会导致交换减慢全局内存,而我们却没有意识到这一点。这也意味着您必须为每个工作项分配本地内存。每个工作项将访问其自己的本地内存块并使用它进行排序(排他)。 我不确定这个想法有多好,但是我已经读过,使用过多的私有内存可能会导致交换到全局内存,唯一需要注意的方法是查看性能(不确定我是否&# 39;关于这个问题。)

答案 1 :(得分:1)

这是一种应该产生非常好的排序网络的算法。可能不是所有输入尺寸的绝对最佳网络,但希望足够实用。

  1. 存储(或可用)预先计算的网络,其中n
  2. 使用最佳网络对最大的2 ^ k个元素进行排序。例如:最大功率小于等于n的比特分类。
  3. 对于剩余的元素,重复#2直到m <1。 16,其中m是未排序元素的数量
  4. 使用#1中已知的最佳网络对任何剩余元素进行排序
  5. 使用合并排序网络合并排序最小和第二小的子列表
  6. 重复#5直到只剩下一个排序列表
  7. 所有这些步骤都可以人工完成,比较存储在主网络中,而不是作用于数据。

    值得指出的是,来自#2的(bitonic)网络可以并行运行,较小的网络将首先完成。这很好,因为完成后,#5-6的网络就可以开始执行了。