Commit ba19c7c9 authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Optimizing mesh initializer, replaced EntitySeedKey with EntitySeedHash

parent c1e65642
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+62 −0
Original line number Diff line number Diff line
/***************************************************************************
                          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>
+130 −0
Original line number Diff line number Diff line
/***************************************************************************
                          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
+0 −1
Original line number Diff line number Diff line
SET( headers EntityInitializer.h
             EntitySeed.h 
             EntitySeedKey.h
             Initializer.h
             SubentitySeedsCreator.h
             SuperentityStorageInitializer.h
+53 −4
Original line number Diff line number Diff line
@@ -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
Loading