Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::vector faster than std::unordered_set?

In my custom physics engine, the biggest bottleneck is a method that gets all bodies from the spatial partitioning (a 2D grid), and returns a collection containing only unique pointers to body.

template<typename T, typename V> bool contains(const T& mContainer, const V& mValue)
{
    return std::find(std::begin(mContainer), 
                     std::end(mContainer), mValue) != std::end(mContainer);
}

const vector<Body*>& GridInfo::getBodiesToCheck()
{
    bodiesToCheck.clear();
    for(auto& query : queries)
        for(auto& body : *query)
            if(!contains(bodiesToCheck, body)) bodiesToCheck.push_back(body);
    return bodiesToCheck;
}

Using a profiler shows that the bottleneck is in the "contains" method.

Obviously, an std::unordered_set would be the "ideal" solution here. However, it is a lot slower than the current solution. I've also tried google::dense_hash_set, which is faster than std::unordered_set, but still slower than the current solution.

const unordered_set<Body*>& GridInfo::getBodiesToCheck()
{
    bodiesToCheck.clear();
    for(auto& query : queries)
        for(auto& body : *query)
            /*if(!contains(bodiesToCheck, body))*/ bodiesToCheck.insert(body);
    return bodiesToCheck;
}

Why are the "correct" containers slower than a std::vector?

Is there any way I can speed up this method further?

like image 578
Vittorio Romeo Avatar asked Apr 08 '13 13:04

Vittorio Romeo


People also ask

Is std :: vector fast?

A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.

Is Unordered_set faster than set?

Even though unordered set is faster in the average case, set is almost always guaranteed to have lower worst-case complexities (for example insert). If you want to access the elements in order, that set sorts them. Different sets can be lexicographically compared using <,<=, >, and >=.

What is the time complexity of Unordered_set?

The time complexity of set operations is O(log n) while for unordered_set, it is O(1).

Is unordered set faster than vector?

vector is fast and is the best choice 99% of the time. Unless, of course, if correctness is more important than performance, then use unordered_set and switch to vector only if performance problems arise from the use of unordered_set .


2 Answers

There are two possibilities I can think of:

  1. You have a small enough number of data elements that a linear search is faster than a hash-plus compare lookup.
  2. You're using the same contains function to find an element in the unordered_set, instead of using the member function find.
like image 51
Mark B Avatar answered Oct 05 '22 01:10

Mark B


If the number of duplicate bodies isn't that high compared to the others, one option might be to just push all your bodies into the vector and remove the duplicates afterwards. But this will require a std::sort followed by an erase(std::unique, end).

But it may be worth a try, considering that your vector seems to outplay a std::unordered_set anyway, which doesn't have the same memory locality and trivial access like a std::vector.

like image 22
Christian Rau Avatar answered Oct 05 '22 00:10

Christian Rau