mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
HashTable performance: find(), found() check nElmts_ instead of tableSize_
- much better performance on empty tables (4-6x speedup), neutral performance change on filled tables. Since tableSize_ is non-zero when nElmts_ is, there is no modulus zero problem.
This commit is contained in:
@ -32,6 +32,7 @@ Description
|
||||
#include "boolList.H"
|
||||
#include "PackedBoolList.H"
|
||||
#include "HashSet.H"
|
||||
#include "StaticHashTable.H"
|
||||
#include "cpuTime.H"
|
||||
#include <vector>
|
||||
|
||||
@ -55,11 +56,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
labelHashSet emptyHash;
|
||||
labelHashSet fullHash(1000);
|
||||
for(label i = 0; i < n; i++)
|
||||
for (label i = 0; i < n; i++)
|
||||
{
|
||||
fullHash.insert(i);
|
||||
}
|
||||
|
||||
// don't use fullStaticHash, it's too slow
|
||||
StaticHashTable<nil, label, Hash<label> > emptyStaticHash;
|
||||
|
||||
cpuTime timer;
|
||||
|
||||
for (label iter = 0; iter < nIters; ++iter)
|
||||
@ -235,6 +239,22 @@ int main(int argc, char *argv[])
|
||||
Info<< " sum " << sum << endl;
|
||||
|
||||
|
||||
// Read empty static hash
|
||||
sum = 0;
|
||||
for (label iter = 0; iter < nIters; ++iter)
|
||||
{
|
||||
forAll(unpacked, i)
|
||||
{
|
||||
sum += emptyStaticHash.found(i);
|
||||
}
|
||||
}
|
||||
Info<< "Reading empty StaticHash:" << timer.cpuTimeIncrement()
|
||||
<< " s" << endl;
|
||||
Info<< " sum " << sum << endl;
|
||||
|
||||
|
||||
Info<< "Starting write tests" << endl;
|
||||
|
||||
//
|
||||
// Write
|
||||
//
|
||||
|
||||
@ -33,14 +33,14 @@ License
|
||||
|
||||
template<class Key, class Hash>
|
||||
template<class AnyType>
|
||||
Foam::HashSet<Key, Hash>::HashSet(const HashTable<AnyType, Key, Hash>& ht)
|
||||
Foam::HashSet<Key, Hash>::HashSet(const HashTable<AnyType, Key, Hash>& h)
|
||||
:
|
||||
HashTable<nil, Key, Hash>(ht.size())
|
||||
HashTable<nil, Key, Hash>(h.size())
|
||||
{
|
||||
for
|
||||
(
|
||||
typename HashTable<AnyType, Key, Hash>::const_iterator cit = ht.begin();
|
||||
cit != ht.end();
|
||||
typename HashTable<AnyType, Key, Hash>::const_iterator cit = h.cbegin();
|
||||
cit != h.cend();
|
||||
++cit
|
||||
)
|
||||
{
|
||||
@ -62,7 +62,7 @@ template<class Key, class Hash>
|
||||
bool Foam::HashSet<Key, Hash>::operator==(const HashSet<Key, Hash>& rhs) const
|
||||
{
|
||||
// Are all lhs elements in rhs?
|
||||
for (const_iterator iter = this->begin(); iter != this->end(); ++iter)
|
||||
for (const_iterator iter = this->cbegin(); iter != this->cend(); ++iter)
|
||||
{
|
||||
if (!rhs.found(iter.key()))
|
||||
{
|
||||
@ -71,7 +71,7 @@ bool Foam::HashSet<Key, Hash>::operator==(const HashSet<Key, Hash>& rhs) const
|
||||
}
|
||||
|
||||
// Are all rhs elements in lhs?
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
if (!found(iter.key()))
|
||||
{
|
||||
@ -94,7 +94,7 @@ template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::operator|=(const HashSet<Key, Hash>& rhs)
|
||||
{
|
||||
// Add rhs elements into lhs
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
insert(iter.key());
|
||||
}
|
||||
@ -105,7 +105,7 @@ template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::operator&=(const HashSet<Key, Hash>& rhs)
|
||||
{
|
||||
// Remove elements not also found in rhs
|
||||
for (iterator iter = this->begin(); iter != this->end(); ++iter)
|
||||
for (iterator iter = this->cbegin(); iter != this->cend(); ++iter)
|
||||
{
|
||||
if (!rhs.found(iter.key()))
|
||||
{
|
||||
@ -119,7 +119,7 @@ template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::operator^=(const HashSet<Key, Hash>& rhs)
|
||||
{
|
||||
// Add missed rhs elements, remove duplicate elements
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
if (found(iter.key()))
|
||||
{
|
||||
@ -138,7 +138,7 @@ template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
|
||||
{
|
||||
// Remove rhs elements from lhs
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
erase(iter.key());
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
||||
table_[hashIdx] = 0;
|
||||
}
|
||||
|
||||
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter)
|
||||
for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter)
|
||||
{
|
||||
insert(iter.key(), *iter);
|
||||
}
|
||||
@ -113,9 +113,9 @@ Foam::HashTable<T, Key, Hash>::~HashTable()
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (tableSize_)
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, tableSize_);
|
||||
const label hashIdx = Hash()(key, tableSize_);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
@ -145,9 +145,9 @@ Foam::HashTable<T, Key, Hash>::find
|
||||
const Key& key
|
||||
)
|
||||
{
|
||||
if (tableSize_)
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, tableSize_);
|
||||
const label hashIdx = Hash()(key, tableSize_);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
@ -177,7 +177,7 @@ Foam::HashTable<T, Key, Hash>::find
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
if (tableSize_)
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, tableSize_);
|
||||
|
||||
@ -198,7 +198,7 @@ Foam::HashTable<T, Key, Hash>::find
|
||||
}
|
||||
# endif
|
||||
|
||||
return end();
|
||||
return cend();
|
||||
}
|
||||
|
||||
|
||||
@ -209,7 +209,7 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
|
||||
List<Key> tofc(nElmts_);
|
||||
label i = 0;
|
||||
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter)
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
tofc[i++] = iter.key();
|
||||
}
|
||||
@ -351,7 +351,7 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
|
||||
else
|
||||
{
|
||||
// No previous found. Mark with special value which is
|
||||
// - not end()
|
||||
// - not end()/cend()
|
||||
// - handled by operator++
|
||||
it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||
it.hashIndex_ = -1;
|
||||
@ -466,7 +466,7 @@ void Foam::HashTable<T, Key, Hash>::resize(const label newSize)
|
||||
|
||||
HashTable<T, Key, Hash>* newTable = new HashTable<T, Key, Hash>(newSize);
|
||||
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter)
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
newTable->insert(iter.key(), *iter);
|
||||
}
|
||||
@ -565,7 +565,7 @@ void Foam::HashTable<T, Key, Hash>::operator=
|
||||
clear();
|
||||
}
|
||||
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
insert(iter.key(), *iter);
|
||||
}
|
||||
@ -579,22 +579,22 @@ bool Foam::HashTable<T, Key, Hash>::operator==
|
||||
) const
|
||||
{
|
||||
// Are all my elements in rhs?
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter)
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = rhs.find(iter.key());
|
||||
|
||||
if (fnd == rhs.end() || fnd() != iter())
|
||||
if (fnd == rhs.cend() || fnd() != iter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Are all rhs elements in me?
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = find(iter.key());
|
||||
|
||||
if (fnd == end() || fnd() != iter())
|
||||
if (fnd == cend() || fnd() != iter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
|
||||
{
|
||||
const_iterator iter = find(key);
|
||||
|
||||
if (iter == end())
|
||||
if (iter == cend())
|
||||
{
|
||||
FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&) const")
|
||||
<< key << " not found in table. Valid entries: "
|
||||
@ -283,8 +283,15 @@ Foam::HashTable<T, Key, Hash>::begin()
|
||||
{
|
||||
label i = 0;
|
||||
|
||||
if (nElmts_)
|
||||
{
|
||||
while (table_ && !table_[i] && ++i < tableSize_)
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = tableSize_;
|
||||
}
|
||||
|
||||
if (i == tableSize_)
|
||||
{
|
||||
@ -456,8 +463,15 @@ Foam::HashTable<T, Key, Hash>::cbegin() const
|
||||
{
|
||||
label i = 0;
|
||||
|
||||
if (nElmts_)
|
||||
{
|
||||
while (table_ && !table_[i] && ++i < tableSize_)
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = tableSize_;
|
||||
}
|
||||
|
||||
if (i == tableSize_)
|
||||
{
|
||||
|
||||
@ -39,7 +39,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
|
||||
endIter_(*this, NULL, 0),
|
||||
endConstIter_(*this, NULL, 0)
|
||||
{
|
||||
for (label i=0; i<tableSize_; i++)
|
||||
for (label i=0; i < tableSize_; i++)
|
||||
{
|
||||
table_[i] = 0;
|
||||
}
|
||||
@ -133,10 +133,13 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
|
||||
)
|
||||
{
|
||||
is.putBack(lastToken);
|
||||
|
||||
Key key;
|
||||
is >> key;
|
||||
|
||||
T element;
|
||||
is >> element;
|
||||
|
||||
L.insert(key, element);
|
||||
|
||||
is.fatalCheck
|
||||
@ -174,8 +177,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const HashTable<T, Key, Hash>& L)
|
||||
// Write contents
|
||||
for
|
||||
(
|
||||
typename HashTable<T, Key, Hash>::const_iterator iter = L.begin();
|
||||
iter != L.end();
|
||||
typename HashTable<T, Key, Hash>::const_iterator iter = L.cbegin();
|
||||
iter != L.cend();
|
||||
++iter
|
||||
)
|
||||
{
|
||||
|
||||
@ -101,6 +101,8 @@ Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, keys_.size());
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
@ -111,6 +113,7 @@ bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
@ -131,6 +134,8 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
||||
const Key& key
|
||||
)
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, keys_.size());
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
@ -141,6 +146,7 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
||||
return iterator(*this, hashIdx, elemIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
|
||||
@ -102,7 +102,7 @@ inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
|
||||
{
|
||||
const_iterator iter = find(key);
|
||||
|
||||
if (iter == end())
|
||||
if (iter == cend())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
|
||||
@ -142,10 +142,13 @@ Foam::Istream& Foam::operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
|
||||
)
|
||||
{
|
||||
is.putBack(lastToken);
|
||||
|
||||
Key key;
|
||||
is >> key;
|
||||
|
||||
T element;
|
||||
is >> element;
|
||||
|
||||
L.insert(key, element);
|
||||
|
||||
is.fatalCheck
|
||||
|
||||
Reference in New Issue
Block a user