Skip to content
Snippets Groups Projects
Commit ba19c7c9 authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Optimizing mesh initializer, replaced EntitySeedKey with EntitySeedHash

parent c1e65642
No related branches found
No related tags found
No related merge requests found
......@@ -7,6 +7,8 @@ set( headers Array.h
IndexedMap_impl.h
IndexedSet.h
IndexedSet_impl.h
UnorderedIndexedSet.h
UnorderedIndexedSet_impl.h
List.h
List_impl.h
MultiArray.h
......
/***************************************************************************
UnorderedIndexedSet.h - description
-------------------
begin : Dec 12, 2017
copyright : (C) 2017 by Tomas Oberhuber et al.
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/* See Copyright Notice in tnl/Copyright */
#pragma once
#include <unordered_map>
#include <ostream>
namespace TNL {
namespace Containers {
template< class Key,
class Index,
class Hash = std::hash< Key >,
class KeyEqual = std::equal_to< Key >,
class Allocator = std::allocator< std::pair<const Key, Index> > >
class UnorderedIndexedSet
{
protected:
using map_type = std::unordered_map< Key, Index, Hash, KeyEqual, Allocator >;
map_type map;
public:
using key_type = Key;
using index_type = Index;
using value_type = typename map_type::value_type;
using size_type = typename map_type::size_type;
using hasher = Hash;
using key_equal = KeyEqual;
void clear();
size_type size() const;
Index insert( const Key& key );
std::pair< Index, bool > try_insert( const Key& key );
bool find( const Key& key, Index& index ) const;
size_type count( const Key& key ) const;
size_type erase( const Key& key );
void print( std::ostream& str ) const;
};
template< typename Element,
typename Index >
std::ostream& operator <<( std::ostream& str, UnorderedIndexedSet< Element, Index >& set );
} // namespace Containers
} // namespace TNL
#include <TNL/Containers/UnorderedIndexedSet_impl.h>
/***************************************************************************
UnorderedIndexedSet_impl.h - description
-------------------
begin : Feb 15, 2014
copyright : (C) 2014 by Tomas Oberhuber et al.
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/* See Copyright Notice in tnl/Copyright */
#pragma once
#include <TNL/Containers/UnorderedIndexedSet.h>
namespace TNL {
namespace Containers {
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
void
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::clear()
{
map.clear();
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size() const
{
return map.size();
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
Index
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::insert( const Key& key )
{
auto iter = map.insert( value_type( key, size() ) ).first;
return iter->second;
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
std::pair< Index, bool >
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::try_insert( const Key& key )
{
auto pair = map.insert( value_type( key, size() ) );
return std::pair< Index, bool >{ pair.first->second, pair.second };
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
bool
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::find( const Key& key, Index& index ) const
{
auto iter = map.find( Key( key ) );
if( iter == map.end() )
return false;
index = iter->second.index;
return true;
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::count( const Key& key ) const
{
return map.count( key );
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type
UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::erase( const Key& key )
{
return map.erase( key );
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
void UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::print( std::ostream& str ) const
{
auto iter = map.begin();
str << iter->second.data;
iter++;
while( iter != map.end() )
{
str << ", " << iter->second.data;
iter++;
}
}
template< class Key,
class Index,
class Hash,
class KeyEqual,
class Allocator >
std::ostream& operator<<( std::ostream& str, UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >& set )
{
set.print( str );
return str;
}
} // namespace Containers
} // namespace TNL
SET( headers EntityInitializer.h
EntitySeed.h
EntitySeedKey.h
Initializer.h
SubentitySeedsCreator.h
SuperentityStorageInitializer.h
......
......@@ -17,11 +17,15 @@
#pragma once
#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
#include <TNL/Meshes/MeshDetails/initializer/EntitySeedKey.h>
namespace TNL {
namespace Meshes {
template< typename EntitySeed >
struct EntitySeedHash;
template< typename EntitySeed >
struct EntitySeedEq;
template< typename MeshConfig,
typename EntityTopology >
class EntitySeed
......@@ -33,7 +37,8 @@ class EntitySeed
using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType;
using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType;
using IdArrayType = Containers::StaticArray< SubvertexTraits::count, GlobalIndexType >;
using KeyType = EntitySeedKey< MeshConfig, EntityTopology >;
using HashType = EntitySeedHash< EntitySeed >;
using KeyEqual = EntitySeedEq< EntitySeed >;
static String getType() { return String( "EntitySeed<>" ); }
......@@ -74,7 +79,8 @@ class EntitySeed< MeshConfig, Topologies::Vertex >
using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType;
using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType;
using IdArrayType = Containers::StaticArray< 1, GlobalIndexType >;
using KeyType = EntitySeedKey< MeshConfig, Topologies::Vertex >;
using HashType = EntitySeedHash< EntitySeed >;
using KeyEqual = EntitySeedEq< EntitySeed >;
static String getType() { return String( "EntitySeed<>" ); }
......@@ -112,6 +118,49 @@ std::ostream& operator<<( std::ostream& str, const EntitySeed< MeshConfig, Entit
return str;
};
template< typename EntitySeed >
struct EntitySeedHash
{
std::size_t operator()( const EntitySeed& seed ) const
{
using LocalIndexType = typename EntitySeed::LocalIndexType;
using GlobalIndexType = typename EntitySeed::GlobalIndexType;
// Note that we must use an associative function to combine the hashes,
// because we *want* to ignore the order of the corner IDs.
std::size_t hash = 0;
for( LocalIndexType i = 0; i < EntitySeed::getCornersCount(); i++ )
// hash ^= std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] );
hash += std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] );
return hash;
}
};
template< typename EntitySeed >
struct EntitySeedEq
{
bool operator()( const EntitySeed& left, const EntitySeed& right ) const
{
using IdArrayType = typename EntitySeed::IdArrayType;
IdArrayType sortedLeft( left.getCornerIds() );
IdArrayType sortedRight( right.getCornerIds() );
sortedLeft.sort();
sortedRight.sort();
return sortedLeft == sortedRight;
}
};
template< typename MeshConfig >
struct EntitySeedEq< EntitySeed< MeshConfig, Topologies::Vertex > >
{
using Seed = EntitySeed< MeshConfig, Topologies::Vertex >;
bool operator()( const Seed& left, const Seed& right ) const
{
return left.getCornerIds() == right.getCornerIds();
}
};
} // namespace Meshes
} // namespace TNL
/***************************************************************************
EntitySeedKey.h - description
-------------------
begin : Feb 13, 2014
copyright : (C) 2014 by Tomas Oberhuber et al.
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/* See Copyright Notice in tnl/Copyright */
/***
* Authors:
* Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz
* Zabka Vitezslav, zabkav@gmail.com
*/
#pragma once
namespace TNL {
namespace Meshes {
template< typename MeshConfig,
typename EntityTopology >
class EntitySeed;
/****
* Unique identification of a mesh entity by its vertices.
* Uniqueness is preserved for entities of the same type only.
*/
template< typename MeshConfig,
typename EntityTopology >
class EntitySeedKey
{
using EntitySeedType = EntitySeed< MeshConfig, EntityTopology >;
using IdArrayType = typename EntitySeedType::IdArrayType;
public:
EntitySeedKey( const EntitySeedType& entitySeed )
{
for( typename IdArrayType::IndexType i = 0;
i < entitySeed.getCornersCount();
i++ )
this->sortedCorners[ i ] = entitySeed.getCornerIds()[ i ];
sortedCorners.sort( );
}
bool operator<( const EntitySeedKey& other ) const
{
for( typename IdArrayType::IndexType i = 0;
i < IdArrayType::size;
i++)
{
if( sortedCorners[ i ] < other.sortedCorners[ i ] )
return true;
else
if( sortedCorners[ i ] > other.sortedCorners[ i ] )
return false;
}
return false;
}
private:
IdArrayType sortedCorners;
};
} // namespace Meshes
} // namespace TNL
......@@ -19,7 +19,6 @@
#include <TNL/Meshes/DimensionTag.h>
#include <TNL/Meshes/MeshDetails/initializer/EntityInitializer.h>
#include <TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h>
#include <TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h>
#include <TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h>
#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h>
......@@ -246,13 +245,14 @@ class InitializerLayer< MeshConfig,
using PointArrayType = typename MeshTraitsType::PointArrayType;
using SeedType = EntitySeed< MeshConfig, EntityTopology >;
using SeedIndexedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
using SeedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType;
public:
GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh )
{
using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
std::set< typename SeedIndexedSet::key_type > seedSet;
SeedSet seedSet;
for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
{
......@@ -283,8 +283,10 @@ class InitializerLayer< MeshConfig,
for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ )
{
auto& seed = subentitySeeds[ j ];
if( this->seedsIndexedSet.count( seed ) == 0 ) {
const GlobalIndexType entityIndex = this->seedsIndexedSet.insert( seed );
const auto pair = this->seedsIndexedSet.try_insert( seed );
const GlobalIndexType& entityIndex = pair.first;
if( pair.second ) {
// insertion took place, initialize the entity
EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( entityIndex ), entityIndex, seed, initializer );
}
}
......@@ -331,6 +333,8 @@ class InitializerLayer< MeshConfig,
using LocalIndexType = typename MeshTraitsType::LocalIndexType;
using PointArrayType = typename MeshTraitsType::PointArrayType;
using SeedType = EntitySeed< MeshConfig, EntityTopology >;
using SeedIndexedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
using SeedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType;
using ReferenceOrientationType = typename EntityTraitsType::ReferenceOrientationType;
using ReferenceOrientationArrayType = typename EntityTraitsType::ReferenceOrientationArrayType;
......@@ -339,7 +343,7 @@ class InitializerLayer< MeshConfig,
GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh )
{
using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
std::set< typename SeedIndexedSet::key_type > seedSet;
SeedSet seedSet;
for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
{
......@@ -371,8 +375,10 @@ class InitializerLayer< MeshConfig,
for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ )
{
auto& seed = subentitySeeds[ j ];
if( this->seedsIndexedSet.count( seed ) == 0 ) {
const GlobalIndexType entityIndex = this->seedsIndexedSet.insert( seed );
const auto pair = this->seedsIndexedSet.try_insert( seed );
const GlobalIndexType& entityIndex = pair.first;
if( pair.second ) {
// insertion took place, initialize the entity
EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( entityIndex ), entityIndex, seed, initializer );
this->referenceOrientations[ entityIndex ] = ReferenceOrientationType( seed );
}
......@@ -393,8 +399,6 @@ class InitializerLayer< MeshConfig,
}
private:
using SeedIndexedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
SeedIndexedSet seedsIndexedSet;
ReferenceOrientationArrayType referenceOrientations;
};
......
......@@ -17,7 +17,7 @@
#pragma once
#include <set>
#include <map>
#include <unordered_map>
#include <TNL/Meshes/DimensionTag.h>
#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h>
......@@ -86,7 +86,7 @@ public:
private:
using DynamicIndexSet = std::set< GlobalIndexType >;
std::map< GlobalIndexType, DynamicIndexSet > dynamicStorageNetwork;
std::unordered_map< GlobalIndexType, DynamicIndexSet > dynamicStorageNetwork;
GlobalIndexType getMaxSuperentityIndex()
{
......
......@@ -17,11 +17,13 @@
#pragma once
#include <TNL/Containers/Array.h>
#include <TNL/Containers/IndexedSet.h>
#include <TNL/Containers/UnorderedIndexedSet.h>
#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h>
#include <unordered_set>
namespace TNL {
namespace Meshes {
......@@ -81,7 +83,8 @@ public:
using ReferenceOrientationType = MeshEntityReferenceOrientation< MeshConfig, EntityTopology >;
using StorageArrayType = Containers::Array< EntityType, Device, GlobalIndexType >;
using SeedIndexedSetType = Containers::IndexedSet< typename SeedType::KeyType, GlobalIndexType >;
using SeedIndexedSetType = Containers::UnorderedIndexedSet< SeedType, GlobalIndexType, typename SeedType::HashType, typename SeedType::KeyEqual >;
using SeedSetType = std::unordered_set< typename SeedIndexedSetType::key_type, typename SeedIndexedSetType::hasher, typename SeedIndexedSetType::key_equal >;
using ReferenceOrientationArrayType = Containers::Array< ReferenceOrientationType, Device, GlobalIndexType >;
static constexpr bool storageEnabled = MeshConfig::entityStorage( Dimension );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment