views:

120

answers:

2

I'm using the c++ STL heap algorithms, and I wrote a wrapper class around it so I could do some other stuff. When I tried to use the code below, for example:

//! Min-heap wrapper class.
class FMMHeap{
public:
    FMMHeap(Vector &phi) : _phi(phi) {}
    bool operator()(unsigned p1, unsigned p2) {return fabs(_phi(p1)) > fabs(_phi(p2)); }
    inline void pop(){ pop_heap(_heap.begin(),_heap.end(),*this); _heap.pop_back(); }
    [...lots of other stuff...]
    vectorU32 _heap;
    Vector &_phi;
}

It was wayyyyy slower than when I had a separate function object like this:

struct HeapSort{
public:
    HeapSort(Vector &phi) : _phi(phi) {}
    bool operator()(unsigned p1, unsigned p2) {return fabs(_phi(p1)) > fabs(_phi(p2)); }
private:
    Vector &_phi;
};

class FMMHeap{
public:
    FMMHeap(Vector &phi) : cmp(phi) {}
    inline void pop(){ pop_heap(_heap.begin(),_heap.end(),cmp); _heap.pop_back(); }
    [...lots of other stuff...]
    vectorU32 _heap;
    HeapSort cmp;
}

I'm not sure why this is. Is the slowdown coming from *this because the class has a lot of data? That seems odd. Or is it something to do with how the function object is used?

+8  A: 

I'm not certain: but maybe pop_heap ends up copying the functor object you pass in. The copy for your FMMHeap would be more expensive than the simple HeapSort

Alex Deem
Yes, its passing the comparison function object by value.
Georg Fritzsche
More generally, most STL algorithms pass the predicate object by value, so it's better to use separate objects there.
Matthieu M.
A: 

The biggest speedup of the STL containers is the inlining of them, such that the compiler can work out how to remove and reorder things.

Its a good guess that the compiler manages to inline the external functor in a way that const propogation is stopping it from doing so in the slow version.

What happens to the slow version if the bool operator is const?

Will