Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/Base/HashMapReducer.hpp 4 : : \copyright 2012-2015 J. Bakosi, 5 : : 2016-2018 Los Alamos National Security, LLC., 6 : : 2019-2021 Triad National Security, LLC. 7 : : All rights reserved. See the LICENSE file for details. 8 : : \brief Custom Charm++ reducer for merging std::unordered_maps across PEs 9 : : \details Custom Charm++ reducer for merging std::unordered_maps across PEs. 10 : : */ 11 : : // ***************************************************************************** 12 : : #ifndef HashMapReducer_h 13 : : #define HashMapReducer_h 14 : : 15 : : #include <vector> 16 : : #include <unordered_map> 17 : : #include <unordered_set> 18 : : #include <memory> 19 : : 20 : : #include "NoWarning/charm++.hpp" 21 : : 22 : : #include "ContainerUtil.hpp" 23 : : 24 : : namespace tk { 25 : : 26 : : //! Serialize std::unordered_map to raw memory stream 27 : : //! \tparam Key Map key 28 : : //! \tparam T Map value 29 : : //! \tparam Hash Map hasher 30 : : //! \tparam Eq Map equality operator 31 : : //! \param[in] m Hash map to serialize 32 : : //! \return Pair of the length and the raw stream containing the serialized map 33 : : template< class Key, 34 : : class T, 35 : : class Hash = std::hash< Key >, 36 : : class Eq = std::equal_to< Key > > 37 : : std::pair< int, std::unique_ptr<char[]> > 38 : 487 : serialize( const std::unordered_map< Key, T, Hash, Eq >& m ) { 39 : : // Prepare for serializing map to a raw binary stream, compute size 40 [ + - ]: 974 : PUP::sizer sizer; 41 [ + - ]: 487 : sizer | const_cast< std::unordered_map< Key, T, Hash, Eq >& >( m ); 42 : : 43 : : // Create raw character stream to store the serialized map 44 [ + - ]: 974 : std::unique_ptr<char[]> flatData = std::make_unique<char[]>( sizer.size() ); 45 : : 46 : : // Serialize map, each message will contain a map 47 [ + - ]: 487 : PUP::toMem packer( flatData.get() ); 48 [ + - ]: 487 : packer | const_cast< std::unordered_map< Key, T, Hash, Eq >& >( m ); 49 : : 50 : : // Return size of and raw stream 51 : 974 : return { sizer.size(), std::move(flatData) }; 52 : : } 53 : : 54 : : //! \brief Charm++ custom reducer for merging std::unordered_maps during 55 : : //! reduction across PEs 56 : : //! \tparam Key Map key 57 : : //! \tparam T Map value 58 : : //! \tparam Hash Map hasher 59 : : //! \tparam Eq Map equality operator 60 : : //! \param[in] nmsg Number of messages in msgs 61 : : //! \param[in] msgs Charm++ reduction message containing the serialized maps 62 : : //! \return Aggregated std::unordered_maps built for further aggregation if 63 : : //! needed 64 : : //! \details During aggregation the map keys are inserted, i.e., the keys remain 65 : : //! unique and the mapped values, assuming containers defining begin() and 66 : : //! end() iterators() are concatenated. 67 : : //! \note The mapped type must be a container, i.e., must provide iterators 68 : : //! begin() and end(). 69 : : template< class Key, 70 : : class T, 71 : : class Hash = std::hash< Key >, 72 : : class Eq = std::equal_to< Key > > 73 : : CkReductionMsg* 74 : 85 : mergeHashMap( int nmsg, CkReductionMsg **msgs ) { 75 : : // Will store deserialized map 76 : 170 : std::unordered_map< Key, T, Hash, Eq > p; 77 : : 78 : : // Create PUP deserializer based on message passed in 79 [ + - ]: 170 : PUP::fromMem creator( msgs[0]->getData() ); 80 : : 81 : : // Deserialize map from raw stream 82 [ + - ]: 85 : creator | p; 83 : : 84 [ + + ]: 327 : for (int m=1; m<nmsg; ++m) { 85 : : // Unpack map 86 : 484 : std::unordered_map< Key, T, Hash, Eq > u; 87 [ + - ]: 484 : PUP::fromMem curCreator( msgs[m]->getData() ); 88 [ + - ]: 242 : curCreator | u; 89 : : // Concatenate maps 90 [ + + ][ + - ]: 520 : for (auto&& c : u) concat( std::move(c.second), p[c.first] ); [ + - ] 91 : : } 92 : : 93 : : // Serialize concatenated maps to raw stream 94 [ + - ]: 170 : auto stream = tk::serialize( p ); 95 : : 96 : : // Forward serialized hash map 97 [ + - ]: 170 : return CkReductionMsg::buildNew( stream.first, stream.second.get() ); 98 : : } 99 : : 100 : : } // tk:: 101 : : 102 : : #endif // HashMapReducer_h