Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sorting 修改少量元素后,重新排序向量_Sorting_Sorting Network - Fatal编程技术网

Sorting 修改少量元素后,重新排序向量

Sorting 修改少量元素后,重新排序向量,sorting,sorting-network,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

如果我们有一个大小为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
例如,如果先前排序的向量是
011
,并且第四个元素被修改,则输入可能是
01101
,但无法将
01101
形成为有效输入,因为它至少在两个元素上与任何排序的向量不同

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

>--*---*-----*-------->
   |   |     | 
>--*---|-----|-*---*-->
       |     | |   |
>--*---|-*---*-|---*-->
   |   | |     |
>--*---*-|-----*---*-->
         |         |
>--------*---------*-->
我们不关心此网络无法对一些无效输入进行排序(例如
0 1 0

该网络的深度为4,与一般情况相比节省了1(.)

不幸的是,蛮力方法不适用于较大的输入大小

是否有一种已知的方法来构建网络以对较大的向量进行重新排序?


我的N值大约为几百,M不超过√N.

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

您应该尝试以下方法:

  • 在本地内存上实现一个简单的顺序排序(插入排序或类似的)。如果你不知道怎么做,我可以帮你
  • 仅让一个工作项对N个元素的块执行排序
  • 计算每个工作组本地内存的最大大小(使用
    CL\u DEVICE\u local\u MEM\u size
    调用
    clGetDeviceInfo
    ),并得出每个工作组的最大工作项数, 因为使用这种方法,您的工作项数量很可能会受到本地内存量的限制
我怀疑这可能会很好地发挥作用,因为:

  • 简单的排序可能非常好,特别是因为数组已经进行了很大程度的排序
  • 为这么少的项目并行化不值得这么麻烦(但是使用本地内存是!)
  • 由于您正在处理数十亿这样的小型阵列,因此即使只有单个工作项处理这样的阵列,您也会获得很大的占用率
如果你对我的想法有疑问,请告诉我

编辑1: 我刚刚意识到我使用了一种可能会让其他人感到困惑的技术: 我建议使用本地内存不是为了同步,也不是为了单个输入向量/数组使用多个工作项。我只是使用它来获得较低的读/写内存延迟。由于我们使用了相当大的内存块,我担心使用私有内存可能会导致在我们没有意识到的情况下交换来降低全局内存的速度。这也意味着您必须为每个工作项分配本地内存。每个工作项都将访问自己的本地内存块,并将其用于排序(独占)。
我不确定这个主意有多好,但我读到过,使用太多的私有内存可能会导致交换到全局内存,唯一能注意到的方法是查看性能(不确定我的说法是否正确)。

这里有一个算法,应该可以生成非常好的排序网络。对于所有输入大小来说,可能不是绝对最好的网络,但对于实际用途来说,希望足够好

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


    值得指出的是#2的(双音)网络可以并行运行,较小的网络将首先完成。这很好,因为当它们完成时,来自#5-6的网络可以开始执行。

    我认为一些排序方法将数据分成部分,并仅对这些部分执行测试。也许您可以调整它,并通过知道每个桶不能有超过一定数量的未排序元素来降低该方法的成本。对于较小的M值,您还可以查找未排序的元素,将它们分开排序,然后再次将它们合并到完整列表中。但是这种方法是不可并行的。@DarkZeros我认为你的第一个建议是正确的。我正在试验一个Shell排序。一些额外的信息会很好:-N真的会在几百范围内吗?-一般来说,您希望从排序中获得什么样的性能?如果你的问题规模真的没有那么大,那么一个复杂的网络可能不值得你这么麻烦。-到目前为止,你一直在尝试什么类型的食物关于你的问题,我假设你的意思是:“我只更改了一些元素,如果已知这些信息,是否有一种方法可以使排序比常规的快得多,或者如果大多数元素已经排序,那么排序的执行速度会快得多。”。我说的对吗?另外:-您对分拣和分拣网络领域的理解有多深?我这样问是为了不浪费您的时间,因为我的知识相当有限。如果您希望对几乎排序的数据进行排序,插入排序实际上是一个不错的选择