C++ 高性能堆排序

C++ 高性能堆排序,c++,performance,sorting,parallel-processing,binary-heap,C++,Performance,Sorting,Parallel Processing,Binary Heap,我有一个大小超过500万的向量,每次我都想从向量中选取一个键最小的元素,并对这个元素进行一些处理。然而,在处理这个特定元素的过程中,向量中的所有剩余元素也将受到影响,因此它们的键将被更新。所以下次如果我想从向量中提取具有最小键的元素,我必须再次对向量排序。问题是从向量中提取最小元素的数量将高达50万,因此程序运行速度非常慢。为了让您更清楚地理解,我可以编写以下代码来说明: void function(vector<MyObj*>& A) { //A.size() is nea

我有一个大小超过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.
    }
}
void函数(向量&A)
{//A.size()接近500万,甚至可能更多,比如5000万。
make_heap(A.begin(),A.end(),compare);//compare函数是自定义的。

对于(inti=0;i,您可以尝试对向量排序并按顺序拾取元素,而不是使用堆


它不会提高big-o的复杂度,但可能会提高常量因子。

如果进程MyObj确实影响了A中所有元素的键,我认为你做不了什么。如果它只修改了一些键,你可以编写代码来更新堆中的各个元素


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

有多少时间在
进程中,以及有多少时间在堆操作中--
50/50%,80/20%?
这很重要,因为你想平衡两者。 考虑下面的一般设置:

Make a Todo list
Loop:
    work on items ...
    update the Todo list
太多的时间更新列表意味着没有足够的时间做真正的工作。 因此,首先测量进程/堆时间的比率。
一个便宜的方法是用它做第二次跑步
处理\u MyObj
比较
两次,例如

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

make_heap
以线性时间运行-- 看-- 因此,加速将是困难的。 如果值是常量,则 64位缓存比指针更高效

在cstheory.stack上列出了几十篇论文,大部分是理论论文, 但是一两个可能与你的问题有关

真正的加速几乎总是针对具体问题,而不是一般问题。 你能告诉我们更多关于真正的问题吗


补充:如果大多数持久性有机污染物都是小的,而且是大的, 尝试在大排序列表前面放置一个小缓存堆。伪代码:

push:
    push( cacheheap )
pop:
    return min( cacheheap, bigsortedlist )
如果
cacheheap
保留在真正的cpu缓存中,这可能会很有效;ymmv。

(你可能会作弊,让
bigsortedlist
不准确,而不是每次都排序。)

是-线性扫描是O(N),因此比排序是O(N log N)要好@user515430同意。构建堆似乎毫无用处。我这么做只是因为它来自一篇著名的论文,这也让我感到困惑。处理过程如何影响所有其他元素有什么模式吗?真的是所有元素(在这种情况下,下限显然是O(N))还是一些?它们可以增加和减少吗?