From 2d2a5580b3dad894326ca3c095bdac4c9e2e5e79 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 12 Jun 2024 17:28:00 -0600 Subject: [PATCH] IOSS: Reduce memory usage of line decomp --- .../libraries/ioss/src/Ioss_ChainGenerator.C | 3 +- .../libraries/ioss/src/Ioss_FaceGenerator.C | 43 ++++++++++++------- .../libraries/ioss/src/Ioss_FaceGenerator.h | 12 ++++-- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C index 92d762eae9..c2d976f04c 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C @@ -195,7 +195,6 @@ namespace Ioss { { debug = debug_level; size_t numel = region.get_property("element_count").get_int(); - Ioss::chain_t element_chains(numel); // Determine which element block(s) are adjacent to the faceset specifying "lines" // The `adjacent_blocks` contains the names of all element blocks that are adjacent to the @@ -225,6 +224,7 @@ namespace Ioss { Ioss::FaceGenerator face_generator(region); face_generator.generate_block_faces(adjacent_blocks, (INT)0, true); + Ioss::chain_t element_chains(numel); for (const auto *block : adjacent_blocks) { // Get the offset into the element_chains vector... auto offset = block->get_offset() + 1; @@ -239,6 +239,7 @@ namespace Ioss { connectivity_t face_connectivity(count); generate_face_connectivity(face_generator.faces(block), static_cast(offset), face_connectivity); + face_generator.clear(block); // For each face on the "front" (at the beginning the boundary sideset faces) // Set `element_chains` to the `face` "ID" diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.C b/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.C index b167d1aae8..04bd1effab 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.C +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.C @@ -69,11 +69,7 @@ namespace { eb->get_field_data("connectivity_raw", connectivity); std::vector elem_ids; - if (local_ids) { - elem_ids.resize(eb->entity_count()); - std::iota(elem_ids.begin(), elem_ids.end(), static_cast(eb->get_offset() + 1)); - } - else { + if (!local_ids) { eb->get_field_data("ids", elem_ids); } @@ -90,6 +86,7 @@ namespace { size_t num_elem = eb->entity_count(); for (size_t elem = 0, offset = 0; elem < num_elem; elem++, offset += num_node_per_elem) { + auto elem_id = local_ids ? eb->get_offset() + elem + 1 : elem_ids[elem]; for (int face = 0; face < num_face_per_elem; face++) { size_t id = 0; assert(face_node_count[face] <= 4); @@ -97,10 +94,10 @@ namespace { for (int j = 0; j < face_node_count[face]; j++) { size_t fnode = offset + face_conn[face][j]; size_t lnode = connectivity[fnode]; // local since "connectivity_raw" - conn[j] = ids[lnode - 1]; // Convert to global + conn[j] = local_ids ? lnode : ids[lnode - 1]; // Convert to global id += hash_ids[lnode - 1]; } - create_face(faces, id, conn, elem_ids[elem], face); + create_face(faces, id, conn, elem_id, face); } } } @@ -333,6 +330,12 @@ namespace Ioss { return faces_[name]; } + void FaceGenerator::clear(const Ioss::ElementBlock *block) + { + auto name = block->name(); + faces_[name].clear(); + } + template IOSS_EXPORT void FaceGenerator::generate_faces(int, bool, bool); template IOSS_EXPORT void FaceGenerator::generate_faces(int64_t, bool, bool); @@ -356,6 +359,14 @@ namespace Ioss { } } + void FaceGenerator::hash_local_node_ids(size_t count) + { + hashIds_.reserve(count); + for (size_t i = 1; i <= count; i++) { + hashIds_.push_back(id_hash(i)); + } + } + template IOSS_EXPORT void FaceGenerator::generate_block_faces(const Ioss::ElementBlockContainer &, int, bool); template IOSS_EXPORT void FaceGenerator::generate_block_faces(const Ioss::ElementBlockContainer &, @@ -368,27 +379,27 @@ namespace Ioss { // Convert ids into hashed-ids Ioss::NodeBlock *nb = region_.get_node_blocks()[0]; +#if DO_TIMING + auto starth = std::chrono::steady_clock::now(); +#endif std::vector ids; if (local_ids) { - ids.resize(nb->entity_count()); - std::iota(ids.begin(), ids.end(), 1); + hash_local_node_ids(nb->entity_count()); } else { nb->get_field_data("ids", ids); + hash_node_ids(ids); } #if DO_TIMING - auto starth = std::chrono::steady_clock::now(); -#endif - hash_node_ids(ids); -#if DO_TIMING - auto endh = std::chrono::steady_clock::now(); + auto endh = std::chrono::steady_clock::now(); #endif for (const auto &eb : ebs) { const std::string &name = eb->name(); size_t numel = eb->entity_count(); - size_t reserve = 3.2 * numel; + size_t reserve = 2.0 * numel; faces_[name].reserve(reserve); + faces_[name].max_load_factor(0.9); internal_generate_faces(eb, faces_[name], ids, hashIds_, local_ids, (INT)0); } @@ -426,6 +437,7 @@ namespace Ioss { fmt::print("Total time: \t{:.6} ms\n\n", std::chrono::duration(endp - starth).count()); #endif + hashIds_.clear(); } template void FaceGenerator::generate_model_faces(INT /*dummy*/, bool local_ids) @@ -487,6 +499,7 @@ namespace Ioss { fmt::print("Total time: \t{:.3f} ms\n\n", std::chrono::duration(endp - starth).count()); #endif + hashIds_.clear(); } } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h b/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h index 2881b08f43..ed9ada94a1 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h @@ -108,11 +108,11 @@ namespace Ioss { #if defined FG_USE_STD using FaceUnorderedSet = std::unordered_set; #elif defined FG_USE_HOPSCOTCH - using FaceUnorderedSet = tsl::hopscotch_set; - // using FaceUnorderedSet = tsl::hopscotch_pg_set; + //using FaceUnorderedSet = tsl::hopscotch_set; + using FaceUnorderedSet = tsl::hopscotch_pg_set; #elif defined FG_USE_ROBIN - using FaceUnorderedSet = tsl::robin_set; - // using FaceUnorderedSet = tsl::robin_pg_set; + // using FaceUnorderedSet = tsl::robin_set; + using FaceUnorderedSet = tsl::robin_pg_set; #endif class IOSS_EXPORT FaceGenerator { @@ -130,11 +130,15 @@ namespace Ioss { FaceUnorderedSet &faces(const std::string &name = "ALL") { return faces_[name]; } FaceUnorderedSet &faces(const ElementBlock *block); + void clear(const std::string &name) {faces_[name].clear();} + void clear(const ElementBlock *block); + //! Given a local node id (0-based), return the hashed value. size_t node_id_hash(size_t local_node_id) const { return hashIds_[local_node_id]; } private: template void hash_node_ids(const std::vector &node_ids); + void hash_local_node_ids(size_t count); template void generate_model_faces(INT /*dummy*/, bool local_ids); Ioss::Region ®ion_;