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 "boolList.H"
|
||||||
#include "PackedBoolList.H"
|
#include "PackedBoolList.H"
|
||||||
#include "HashSet.H"
|
#include "HashSet.H"
|
||||||
|
#include "StaticHashTable.H"
|
||||||
#include "cpuTime.H"
|
#include "cpuTime.H"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -60,6 +61,9 @@ int main(int argc, char *argv[])
|
|||||||
fullHash.insert(i);
|
fullHash.insert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't use fullStaticHash, it's too slow
|
||||||
|
StaticHashTable<nil, label, Hash<label> > emptyStaticHash;
|
||||||
|
|
||||||
cpuTime timer;
|
cpuTime timer;
|
||||||
|
|
||||||
for (label iter = 0; iter < nIters; ++iter)
|
for (label iter = 0; iter < nIters; ++iter)
|
||||||
@ -235,6 +239,22 @@ int main(int argc, char *argv[])
|
|||||||
Info<< " sum " << sum << endl;
|
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
|
// Write
|
||||||
//
|
//
|
||||||
|
|||||||
@ -33,14 +33,14 @@ License
|
|||||||
|
|
||||||
template<class Key, class Hash>
|
template<class Key, class Hash>
|
||||||
template<class AnyType>
|
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
|
for
|
||||||
(
|
(
|
||||||
typename HashTable<AnyType, Key, Hash>::const_iterator cit = ht.begin();
|
typename HashTable<AnyType, Key, Hash>::const_iterator cit = h.cbegin();
|
||||||
cit != ht.end();
|
cit != h.cend();
|
||||||
++cit
|
++cit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ template<class Key, class Hash>
|
|||||||
bool Foam::HashSet<Key, Hash>::operator==(const HashSet<Key, Hash>& rhs) const
|
bool Foam::HashSet<Key, Hash>::operator==(const HashSet<Key, Hash>& rhs) const
|
||||||
{
|
{
|
||||||
// Are all lhs elements in rhs?
|
// 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()))
|
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?
|
// 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()))
|
if (!found(iter.key()))
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ template<class Key, class Hash>
|
|||||||
void Foam::HashSet<Key, Hash>::operator|=(const HashSet<Key, Hash>& rhs)
|
void Foam::HashSet<Key, Hash>::operator|=(const HashSet<Key, Hash>& rhs)
|
||||||
{
|
{
|
||||||
// Add rhs elements into lhs
|
// 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());
|
insert(iter.key());
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ template<class Key, class Hash>
|
|||||||
void Foam::HashSet<Key, Hash>::operator&=(const HashSet<Key, Hash>& rhs)
|
void Foam::HashSet<Key, Hash>::operator&=(const HashSet<Key, Hash>& rhs)
|
||||||
{
|
{
|
||||||
// Remove elements not also found in 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()))
|
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)
|
void Foam::HashSet<Key, Hash>::operator^=(const HashSet<Key, Hash>& rhs)
|
||||||
{
|
{
|
||||||
// Add missed rhs elements, remove duplicate elements
|
// 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()))
|
if (found(iter.key()))
|
||||||
{
|
{
|
||||||
@ -138,7 +138,7 @@ template<class Key, class Hash>
|
|||||||
void Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
|
void Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
|
||||||
{
|
{
|
||||||
// Remove rhs elements from lhs
|
// 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());
|
erase(iter.key());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,7 +71,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
|||||||
table_[hashIdx] = 0;
|
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);
|
insert(iter.key(), *iter);
|
||||||
}
|
}
|
||||||
@ -113,9 +113,9 @@ Foam::HashTable<T, Key, Hash>::~HashTable()
|
|||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
|
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_)
|
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||||
{
|
{
|
||||||
@ -145,9 +145,9 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
const Key& key
|
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_)
|
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||||
{
|
{
|
||||||
@ -177,7 +177,7 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
const Key& key
|
const Key& key
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
if (tableSize_)
|
if (nElmts_)
|
||||||
{
|
{
|
||||||
label hashIdx = Hash()(key, tableSize_);
|
label hashIdx = Hash()(key, tableSize_);
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return end();
|
return cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
|
|||||||
List<Key> tofc(nElmts_);
|
List<Key> tofc(nElmts_);
|
||||||
label i = 0;
|
label i = 0;
|
||||||
|
|
||||||
for (const_iterator iter = begin(); iter != end(); ++iter)
|
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||||
{
|
{
|
||||||
tofc[i++] = iter.key();
|
tofc[i++] = iter.key();
|
||||||
}
|
}
|
||||||
@ -351,7 +351,7 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No previous found. Mark with special value which is
|
// No previous found. Mark with special value which is
|
||||||
// - not end()
|
// - not end()/cend()
|
||||||
// - handled by operator++
|
// - handled by operator++
|
||||||
it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||||
it.hashIndex_ = -1;
|
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);
|
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);
|
newTable->insert(iter.key(), *iter);
|
||||||
}
|
}
|
||||||
@ -565,7 +565,7 @@ void Foam::HashTable<T, Key, Hash>::operator=
|
|||||||
clear();
|
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);
|
insert(iter.key(), *iter);
|
||||||
}
|
}
|
||||||
@ -579,22 +579,22 @@ bool Foam::HashTable<T, Key, Hash>::operator==
|
|||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Are all my elements in rhs?
|
// 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());
|
const_iterator fnd = rhs.find(iter.key());
|
||||||
|
|
||||||
if (fnd == rhs.end() || fnd() != iter())
|
if (fnd == rhs.cend() || fnd() != iter())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are all rhs elements in me?
|
// 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());
|
const_iterator fnd = find(iter.key());
|
||||||
|
|
||||||
if (fnd == end() || fnd() != iter())
|
if (fnd == cend() || fnd() != iter())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,7 +112,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
|
|||||||
{
|
{
|
||||||
const_iterator iter = find(key);
|
const_iterator iter = find(key);
|
||||||
|
|
||||||
if (iter == end())
|
if (iter == cend())
|
||||||
{
|
{
|
||||||
FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&) const")
|
FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&) const")
|
||||||
<< key << " not found in table. Valid entries: "
|
<< key << " not found in table. Valid entries: "
|
||||||
@ -283,8 +283,15 @@ Foam::HashTable<T, Key, Hash>::begin()
|
|||||||
{
|
{
|
||||||
label i = 0;
|
label i = 0;
|
||||||
|
|
||||||
|
if (nElmts_)
|
||||||
|
{
|
||||||
while (table_ && !table_[i] && ++i < tableSize_)
|
while (table_ && !table_[i] && ++i < tableSize_)
|
||||||
{}
|
{}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = tableSize_;
|
||||||
|
}
|
||||||
|
|
||||||
if (i == tableSize_)
|
if (i == tableSize_)
|
||||||
{
|
{
|
||||||
@ -456,8 +463,15 @@ Foam::HashTable<T, Key, Hash>::cbegin() const
|
|||||||
{
|
{
|
||||||
label i = 0;
|
label i = 0;
|
||||||
|
|
||||||
|
if (nElmts_)
|
||||||
|
{
|
||||||
while (table_ && !table_[i] && ++i < tableSize_)
|
while (table_ && !table_[i] && ++i < tableSize_)
|
||||||
{}
|
{}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = tableSize_;
|
||||||
|
}
|
||||||
|
|
||||||
if (i == tableSize_)
|
if (i == tableSize_)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -133,10 +133,13 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
is.putBack(lastToken);
|
is.putBack(lastToken);
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
is >> key;
|
is >> key;
|
||||||
|
|
||||||
T element;
|
T element;
|
||||||
is >> element;
|
is >> element;
|
||||||
|
|
||||||
L.insert(key, element);
|
L.insert(key, element);
|
||||||
|
|
||||||
is.fatalCheck
|
is.fatalCheck
|
||||||
@ -174,8 +177,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const HashTable<T, Key, Hash>& L)
|
|||||||
// Write contents
|
// Write contents
|
||||||
for
|
for
|
||||||
(
|
(
|
||||||
typename HashTable<T, Key, Hash>::const_iterator iter = L.begin();
|
typename HashTable<T, Key, Hash>::const_iterator iter = L.cbegin();
|
||||||
iter != L.end();
|
iter != L.cend();
|
||||||
++iter
|
++iter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -100,6 +100,8 @@ Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
|
|||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||||
|
{
|
||||||
|
if (nElmts_)
|
||||||
{
|
{
|
||||||
label hashIdx = Hash()(key, keys_.size());
|
label hashIdx = Hash()(key, keys_.size());
|
||||||
const List<Key>& localKeys = keys_[hashIdx];
|
const List<Key>& localKeys = keys_[hashIdx];
|
||||||
@ -111,6 +113,7 @@ bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# ifdef FULLDEBUG
|
# ifdef FULLDEBUG
|
||||||
if (debug)
|
if (debug)
|
||||||
@ -130,6 +133,8 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
|||||||
(
|
(
|
||||||
const Key& key
|
const Key& key
|
||||||
)
|
)
|
||||||
|
{
|
||||||
|
if (nElmts_)
|
||||||
{
|
{
|
||||||
label hashIdx = Hash()(key, keys_.size());
|
label hashIdx = Hash()(key, keys_.size());
|
||||||
const List<Key>& localKeys = keys_[hashIdx];
|
const List<Key>& localKeys = keys_[hashIdx];
|
||||||
@ -141,6 +146,7 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
|||||||
return iterator(*this, hashIdx, elemIdx);
|
return iterator(*this, hashIdx, elemIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# ifdef FULLDEBUG
|
# ifdef FULLDEBUG
|
||||||
if (debug)
|
if (debug)
|
||||||
|
|||||||
@ -102,7 +102,7 @@ inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
|
|||||||
{
|
{
|
||||||
const_iterator iter = find(key);
|
const_iterator iter = find(key);
|
||||||
|
|
||||||
if (iter == end())
|
if (iter == cend())
|
||||||
{
|
{
|
||||||
FatalErrorIn
|
FatalErrorIn
|
||||||
(
|
(
|
||||||
|
|||||||
@ -142,10 +142,13 @@ Foam::Istream& Foam::operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
is.putBack(lastToken);
|
is.putBack(lastToken);
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
is >> key;
|
is >> key;
|
||||||
|
|
||||||
T element;
|
T element;
|
||||||
is >> element;
|
is >> element;
|
||||||
|
|
||||||
L.insert(key, element);
|
L.insert(key, element);
|
||||||
|
|
||||||
is.fatalCheck
|
is.fatalCheck
|
||||||
|
|||||||
Reference in New Issue
Block a user