高性能堆排序

时间:2014-03-10 18:59:18

标签: c++ performance sorting parallel-processing binary-heap

我有一个大小超过500万的向量,每次我想从向量中拾取一个具有最小键的元素,并对此元素进行一些处理。但是,对于该特定元素的处理,向量中的所有剩余元素也将受到影响,以便其密钥更新。所以下次如果我想从向量中获取具有最小键的元素,我必须再次对向量进行排序。问题是从矢量中拾取最小元素的数量将高达50万,因此程序运行速度很慢。为了更清楚地理解,我可以编写以下代码来说明:

void function(vector<MyObj*>& A)
{ //A.size() is near 5 million, maybe even more such as 50 million.
    make_heap(A.begin(), A.end(), compare); // compare function is self-defined.
    for (int i=0; i<500000; i++)
    {
        MyObj* smallest_elem = A.front();
        pop_heap(A.begin(), A.end());
        A.pop_back();
        Process_MyObj(smallest_elem); // here all of the elements 
                                      // in A will be affect, causing 
                                      // their keys changed.

        make_heap(A.begin(), A.end()); // Since all elements' keys in A changed,
                                       // so heap sorting A once again is 
                                       // necessary in my viewpoint.
    }
}

有没有办法让代码尽可能高效运行?任何想法都是受欢迎的,而不是有限的算法改进,例如,并行或其他任何东西。非常感谢你!

3 个答案:

答案 0 :(得分:2)

如果Process_MyObj确实影响了A中所有元素的键,我认为你无能为力。如果它只修改了一些键,你可以编写代码来更新堆中的各个元素。

现在你的代码我看不到你从构建堆中获得了什么。我只是进行线性扫描以找到最小元素,将其与最后一个元素交换,然后弹出最后一个元素。

答案 1 :(得分:0)

您可以尝试按顺序对向量进行排序并选择元素,而不是使用堆。

它不会改善大的复杂性,但它可能会改善常数因素。

答案 2 :(得分:0)

Process_MyObj中有多少时间,以及堆操作中有多少时间 - 50/50%,80/20%?
这很重要,因为你想要平衡两者。 请考虑以下常规设置:

Make a Todo list
Loop:
    work on items ...
    update the Todo list

更新列表的时间过长意味着没有足够的时间进行实际工作。 因此,首先测量过程/堆时间的比率 一个便宜的方法是做第二次运行 Process_MyObjcompare两次完成,例如

 P + H = 1.0 sec
2P + H = 1.7 sec
=> P = .7, H = .3: P / H = 70 % / 30 %.


make_heap以线性时间运行 - 见how-can-stdmake-heap-be-implemented-while-making-at-most-3n-comparisons - 所以加速将会很艰难。 如果值是常量,则堆 64位&lt; 32值,32索引&gt;比指针更有效率。

whats-new-in-purely-functional-data-structures-since-okasaki 在cstheory.stack上列出了数十篇论文,主要是理论论文, 但是一两个可能与你的问题有关。

真正的加速几乎总是针对特定问题,而不是一般的。 你能告诉我们更多有关真正问题的信息吗?

<小时/> 补充:如果大多数流行音乐很小,并推大, 尝试在大排序列表前面放一个小缓存。伪代码:

push:
    push( cacheheap )
pop:
    return min( cacheheap, bigsortedlist )

如果 cacheheap保留在真正的cpu缓存中,这可能是有效的;因人而异。
(您可能会作弊,并使bigsortedlist不准确,而不是每次都进行排序。)