如果我们有一个先前已排序的 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 。
答案 0 :(得分:3)
好的,我发布这个作为答案,因为对长度的评论限制让我疯狂:)
你应该尝试一下:
clGetDeviceInfo
调用CL_DEVICE_LOCAL_MEM_SIZE
)并导出每个工作组的最大工作项数,
因为通过这种方法,您的工作项数量很可能会受到本地内存量的限制。我怀疑这可能会运作得相当好,因为:
如果您对我的想法有疑问,请告诉我。
我刚刚意识到我使用的技术可能让其他人感到困惑: 我对使用本地内存的提议不适用于单个输入向量/数组的同步或使用多个工作项。我只是用它来获得较低的读/写内存延迟。由于我们使用相当大的内存块,我担心使用私有内存可能会导致交换减慢全局内存,而我们却没有意识到这一点。这也意味着您必须为每个工作项分配本地内存。每个工作项将访问其自己的本地内存块并使用它进行排序(排他)。 我不确定这个想法有多好,但是我已经读过,使用过多的私有内存可能会导致交换到全局内存,唯一需要注意的方法是查看性能(不确定我是否&# 39;关于这个问题。)
答案 1 :(得分:1)
这是一种应该产生非常好的排序网络的算法。可能不是所有输入尺寸的绝对最佳网络,但希望足够实用。
所有这些步骤都可以人工完成,比较存储在主网络中,而不是作用于数据。
值得指出的是,来自#2的(bitonic)网络可以并行运行,较小的网络将首先完成。这很好,因为完成后,#5-6的网络就可以开始执行了。