设A是位于主存储器中的n个整数的数组,让k<< n并假设我有一个带有m个内核的单插槽CPU,每个内核都有自己的L1缓存,并且都有一个共同的L2缓存。
我想从n中获取k个最高值的元素(比如说,进入预分配的输出数组B);而且 - 我希望这在实际上是快速的(所以渐近O(*)都必须是好的并且常数必须很低)。而且我也有一个约束:核心之间没有同步,也没有复杂的原子指令(例如比较和交换测试和设置);整数读写都是原子的。
两种直接的方法是:
如果每个核心的堆都适合其L1,则方法1更有前景;否则它可能不值得麻烦(取决于我想的内存带宽和插入频率)。
另外,我考虑从某种抽样开始,对保守猜测一个截止值,我们不打算插入堆中,以避免插入过多。
您会考虑采用完全不同的方法吗?或者通过某种额外的技巧进一步改善我的想法?
备注:
答案 0 :(得分:0)
您可以将答案基于https://en.wikipedia.org/wiki/Quickselect而不是堆。由于quickselect是线性时间,这将为您节省渐近复杂度的log n因子。您还可以选择使用并行处理来运行quickselect的每个阶段,而不是将数据分成m个部分并运行m个独立的quickselects。 (从这里编辑)
将数据拆分成m个部分并分别处理每个部分相对容易,这样做是适用于其他问题的,所以为了保持一致性,这样做可能是值得的,所以让我们继续。
在O(mk)可写空间(实际上每个处理器为2k)而不是O(n)中执行此操作。只考虑一个处理器。将数据划分为大小为k的块。取前两个块并运行quickselect以找到那些2k中的前k个。附加下一个k项的块以获得大小为2k的块并重复以获得前3k数据项的前k项。继续使用大块的k项,直到达到该处理器的工作量结束。有n / m项需要考虑,我们总共只有不到n /(mk)的quickselect运行要做,每个运行需要时间O(m)所以这个成本是O(n / m) - 这个处理器需要处理的数据是线性的。