W moim niestandardowym silniku fizycznym największym wąskim gardłem jest metoda, która pobiera wszystkie obiekty z partycjonowania przestrzennego (siatka 2D) i zwraca kolekcję zawierającą tylko unikalne wskaźniki do treści.std :: wektor szybciej niż std :: unordered_set?
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;
}
Korzystanie z profilera pokazuje, że wąskie gardło występuje w metodzie "zawiera".
Oczywiście, rozwiązanie "idealne" byłoby tutaj: std::unordered_set
. Jest to jednak znacznie wolniejsze niż obecne rozwiązanie. Próbowałem też google::dense_hash_set
, który jest szybszy niż std::unordered_set
, ale nadal wolniejszy niż obecne rozwiązanie.
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;
}
Dlaczego są "poprawne" kontenery wolniej niż std::vector
?
Czy mogę w jakiś sposób przyspieszyć tę metodę?
Wyniki profilowania są tylko dla 'zawiera'? Pamiętaj, że wyszukiwanie może być szybsze, ale wstawianie jest wolniejsze niż wektor. –
Zakładam, że nie popełniłeś takiego błędu, ale po prostu, aby być naprawdę naprawdę pewnym, nie użyłeś 'std :: find' przy próbie' std :: unordered_map', prawda? –
@stardust_ Profiler pokazuje "getBodiesToCheck()" jako wąskie gardło. Jeśli używam wersji std :: vector, wąskim gardłem wewnątrz getBodiesToCheck() (wąskie gardło wąskiego gardła: P) jest wywołanie "zawiera" –