From ab7dcedb22bfd5f4ab45db44323dd23003e460c1 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 10:18:56 -0700 Subject: [PATCH 01/27] #1376: gossiplb: move enums to a separate file --- .../balance/gossiplb/gossip_enums.h | 147 ++++++++++++++++++ .../collection/balance/gossiplb/gossiplb.h | 94 +---------- 2 files changed, 148 insertions(+), 93 deletions(-) create mode 100644 src/vt/vrt/collection/balance/gossiplb/gossip_enums.h diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h new file mode 100644 index 0000000000..651d7d4433 --- /dev/null +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -0,0 +1,147 @@ +/* +//@HEADER +// ***************************************************************************** +// +// gossiplb.h +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H +#define INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H + +#include "vt/config.h" + +namespace vt { namespace vrt { namespace collection { namespace lb { + +/// Enum for gossiping approach +enum struct InformTypeEnum : uint8_t { + /** + * \brief Synchronous sharing of underloaded processor loads + * + * The round number is defined at the processor level. This approach + * propagates known loads after all messages for a round are received, + * maximizing the amount of information propagated per round, but has a + * synchronization cost. + */ + SyncInform = 0, + /** + * \brief Asynchronous sharing of underloaded processor loads + * + * The round number is defined at the message level. This approach + * propagates known loads when the first message for a round is received, + * avoiding the synchronization cost but delaying the propagation of some + * information until the following round. + */ + AsyncInform = 1 +}; + +/// Enum for the order in which local objects are considered for transfer +enum struct ObjectOrderEnum : uint8_t { + Arbitrary = 0, //< Arbitrary order: iterate as defined by the unordered_map + /** + * \brief By element ID + * + * Sort ascending by the ID member of ElementIDStruct. + */ + ElmID = 1, + /** + * \brief Order for the fewest migrations + * + * Order starting with the object with the smallest load that can be + * transferred to drop the processor load below the average, then by + * descending load for objects with smaller loads, and finally by ascending + * load for objects with larger loads. + */ + FewestMigrations = 2, + /** + * \brief Order for migrating the objects with the smallest loads + * + * Find the object with the smallest load where the sum of its own load and + * all smaller loads meets or exceeds the amount by which this processor's + * load exceeds the target load. Order starting with that object, then by + * descending load for objects with smaller loads, and finally by ascending + * load for objects with larger loads. + */ + SmallObjects = 3, + /** + * \brief Order by descending load + */ + LargestObjects = 4 +}; + +/// Enum for how the CMF is computed +enum struct CMFTypeEnum : uint8_t { + /** + * \brief Original approach + * + * Remove processors from the CMF as soon as they exceed the target (e.g., + * processor-avg) load. Use a CMF factor of 1.0/x, where x is the target load. + */ + Original = 0, + /** + * \brief Compute the CMF factor using the largest processor load in the CMF + * + * Do not remove processors from the CMF that exceed the target load until the + * next iteration. Use a CMF factor of 1.0/x, where x is the greater of the + * target load and the load of the most loaded processor in the CMF. + */ + NormByMax = 1, + /** + * \brief Compute the CMF factor using the load of this processor + * + * Do not remove processors from the CMF that exceed the target load until the + * next iteration. Use a CMF factor of 1.0/x, where x is the load of the + * processor that is computing the CMF. + */ + NormBySelf = 2, + /** + * \brief Narrow the CMF to only include processors that can accommodate the + * transfer + * + * Use a CMF factor of 1.0/x, where x is the greater of the target load and + * the load of the most loaded processor in the CMF. Only include processors + * in the CMF that will pass the chosen Criterion for the object being + * considered for transfer. + */ + NormByMaxExcludeIneligible = 3, +}; + +}}}} /* end namespace vt::vrt::collection::lb */ + +#endif /*INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H*/ diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h index 4d3279db40..a864e692a3 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h @@ -49,6 +49,7 @@ #include "vt/vrt/collection/balance/baselb/baselb.h" #include "vt/vrt/collection/balance/gossiplb/gossip_msg.h" #include "vt/vrt/collection/balance/gossiplb/criterion.h" +#include "vt/vrt/collection/balance/gossiplb/gossip_enums.h" #include #include @@ -58,99 +59,6 @@ namespace vt { namespace vrt { namespace collection { namespace lb { -/// Enum for gossiping approach -enum struct InformTypeEnum : uint8_t { - /** - * \brief Synchronous sharing of underloaded processor loads - * - * The round number is defined at the processor level. This approach - * propagates known loads after all messages for a round are received, - * maximizing the amount of information propagated per round, but has a - * synchronization cost. - */ - SyncInform = 0, - /** - * \brief Asynchronous sharing of underloaded processor loads - * - * The round number is defined at the message level. This approach - * propagates known loads when the first message for a round is received, - * avoiding the synchronization cost but delaying the propagation of some - * information until the following round. - */ - AsyncInform = 1 -}; - -/// Enum for the order in which local objects are considered for transfer -enum struct ObjectOrderEnum : uint8_t { - Arbitrary = 0, //< Arbitrary order: iterate as defined by the unordered_map - /** - * \brief By element ID - * - * Sort ascending by the ID member of ElementIDStruct. - */ - ElmID = 1, - /** - * \brief Order for the fewest migrations - * - * Order starting with the object with the smallest load that can be - * transferred to drop the processor load below the average, then by - * descending load for objects with smaller loads, and finally by ascending - * load for objects with larger loads. - */ - FewestMigrations = 2, - /** - * \brief Order for migrating the objects with the smallest loads - * - * Find the object with the smallest load where the sum of its own load and - * all smaller loads meets or exceeds the amount by which this processor's - * load exceeds the target load. Order starting with that object, then by - * descending load for objects with smaller loads, and finally by ascending - * load for objects with larger loads. - */ - SmallObjects = 3, - /** - * \brief Order by descending load - */ - LargestObjects = 4 -}; - -/// Enum for how the CMF is computed -enum struct CMFTypeEnum : uint8_t { - /** - * \brief Original approach - * - * Remove processors from the CMF as soon as they exceed the target (e.g., - * processor-avg) load. Use a CMF factor of 1.0/x, where x is the target load. - */ - Original = 0, - /** - * \brief Compute the CMF factor using the largest processor load in the CMF - * - * Do not remove processors from the CMF that exceed the target load until the - * next iteration. Use a CMF factor of 1.0/x, where x is the greater of the - * target load and the load of the most loaded processor in the CMF. - */ - NormByMax = 1, - /** - * \brief Compute the CMF factor using the load of this processor - * - * Do not remove processors from the CMF that exceed the target load until the - * next iteration. Use a CMF factor of 1.0/x, where x is the load of the - * processor that is computing the CMF. - */ - NormBySelf = 2, - /** - * \brief Narrow the CMF to only include processors that can accommodate the - * transfer - * - * Use a CMF factor of 1.0/x, where x is the greater of the target load and - * the load of the most loaded processor in the CMF. Only include processors - * in the CMF that will pass the chosen Criterion for the object being - * considered for transfer. - */ - NormByMaxExcludeIneligible = 3, -}; - struct GossipLB : BaseLB { using GossipMsgAsync = balance::GossipMsgAsync; using GossipMsgSync = balance::GossipMsg; From 0a2cc69b7aa24b5df36767cd8f7ded8ab4f78dba Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 10:20:38 -0700 Subject: [PATCH 02/27] #1376: gossiplb: read enum lb args as strings --- .../balance/gossiplb/gossip_enums.h | 61 ++++++++++++++++++ .../collection/balance/gossiplb/gossiplb.cc | 62 ++++++++++++------- 2 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index 651d7d4433..9fae1b3ff9 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -46,9 +46,70 @@ #define INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H #include "vt/config.h" +#include "vt/vrt/collection/balance/read_lb.h" + +#include +#include namespace vt { namespace vrt { namespace collection { namespace lb { +template +struct EnumConverter { + using EnumToStrMap = typename std::unordered_map; + using StrToEnumMap = typename std::unordered_map; + + EnumConverter( + const std::string &par_name, + const std::string &enum_type, + const EnumToStrMap &enum_to_str + ) : enum_to_str_(enum_to_str), + par_name_(par_name), + enum_type_(enum_type) + { + for (const auto &it : enum_to_str_) { + str_to_enum_[it.second] = it.first; + } + } + + virtual ~EnumConverter() = default; + + std::string getString(T e) const { + auto it = enum_to_str_.find(e); + if (it == enum_to_str_.end()) { + auto err = fmt::format( + "GossipLB EnumConverter: enum '{}' value '{}' was not found in the map", + enum_type_, e + ); + vtAbort(err); + } + return it->second; + } + + T getEnum(std::string s) const { + auto it = str_to_enum_.find(s); + if (it == str_to_enum_.end()) { + auto err = fmt::format( + "GossipLB: LB argument '{}' value '{}' is not recognized", + par_name_, s + ); + vtAbort(err); + } + return it->second; + } + + T getFromSpec(balance::SpecEntry* spec, T def_value) const { + std::string spec_value = spec->getOrDefault( + par_name_, getString(def_value) + ); + return getEnum(spec_value); + } + + EnumToStrMap enum_to_str_; + StrToEnumMap str_to_enum_; + std::string par_name_; + std::string enum_type_; +}; + /// Enum for gossiping approach enum struct InformTypeEnum : uint8_t { /** diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index 6be34035e8..89824810bc 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -81,16 +81,6 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { }; spec->checkAllowedKeys(allowed); - using CriterionEnumUnder = typename std::underlying_type::type; - using InformTypeEnumUnder = typename std::underlying_type::type; - using ObjectOrderEnumUnder = typename std::underlying_type::type; - using CMFTypeEnumUnder = typename std::underlying_type::type; - - auto default_c = static_cast(criterion_); - auto default_inform = static_cast(inform_type_); - auto default_order = static_cast(obj_ordering_); - auto default_cmf = static_cast(cmf_type_); - f_ = spec->getOrDefault("f", f_); k_max_ = spec->getOrDefault("k", k_max_); num_iters_ = spec->getOrDefault("i", num_iters_); @@ -99,14 +89,42 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { rollback_ = spec->getOrDefault("rollback", rollback_); target_pole_ = spec->getOrDefault("targetpole", target_pole_); - int32_t c = spec->getOrDefault("c", default_c); - criterion_ = static_cast(c); - int32_t inf = spec->getOrDefault("inform", default_inform); - inform_type_ = static_cast(inf); - int32_t ord = spec->getOrDefault("ordering", default_order); - obj_ordering_ = static_cast(ord); - int32_t cmf = spec->getOrDefault("cmf", default_cmf); - cmf_type_ = static_cast(cmf); + EnumConverter criterion_converter_( + "c", "CriterionEnum", { + {CriterionEnum::Grapevine, "Grapevine"}, + {CriterionEnum::ModifiedGrapevine, "ModifiedGrapevine"} + } + ); + criterion_ = criterion_converter_.getFromSpec(spec, criterion_); + + EnumConverter inform_type_converter_( + "inform", "InformTypeEnum", { + {InformTypeEnum::SyncInform, "SyncInform"}, + {InformTypeEnum::AsyncInform, "AsyncInform"} + } + ); + inform_type_ = inform_type_converter_.getFromSpec(spec, inform_type_); + + EnumConverter obj_ordering_converter_( + "ordering", "ObjectOrderEnum", { + {ObjectOrderEnum::Arbitrary, "Arbitrary"}, + {ObjectOrderEnum::ElmID, "ElmID"}, + {ObjectOrderEnum::FewestMigrations, "FewestMigrations"}, + {ObjectOrderEnum::SmallObjects, "SmallObjects"}, + {ObjectOrderEnum::LargestObjects, "LargestObjects"} + } + ); + obj_ordering_ = obj_ordering_converter_.getFromSpec(spec, obj_ordering_); + + EnumConverter cmf_type_converter_( + "cmf", "CMFTypeEnum", { + {CMFTypeEnum::Original, "Original"}, + {CMFTypeEnum::NormByMax, "NormByMax"}, + {CMFTypeEnum::NormBySelf, "NormBySelf"}, + {CMFTypeEnum::NormByMaxExcludeIneligible, "NormByMaxExcludeIneligible"} + } + ); + cmf_type_ = cmf_type_converter_.getFromSpec(spec, cmf_type_); vtAbortIf( inform_type_ == InformTypeEnum::AsyncInform && deterministic_, @@ -123,9 +141,11 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { "GossipLB::inputParams: using f={}, k={}, i={}, c={}, trials={}, " "deterministic={}, inform={}, ordering={}, cmf={}, rollback={}, " "targetpole={}\n", - f_, k_max_, num_iters_, static_cast(criterion_), num_trials_, - deterministic_, static_cast(inform_type_), - static_cast(obj_ordering_), static_cast(cmf_type_), + f_, k_max_, num_iters_, criterion_converter_.getString(criterion_), + num_trials_, deterministic_, + inform_type_converter_.getString(inform_type_), + obj_ordering_converter_.getString(obj_ordering_), + cmf_type_converter_.getString(cmf_type_), rollback_, target_pole_ ); } From 24ca570200b9801059f2079f9e48080e27aadc14 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 10:30:47 -0700 Subject: [PATCH 03/27] #1376: gossiplb: make lb arg names readable --- .../collection/balance/gossiplb/gossiplb.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index 89824810bc..9e76288b15 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -76,21 +76,21 @@ bool GossipLB::isOverloaded(LoadType load) const { void GossipLB::inputParams(balance::SpecEntry* spec) { std::vector allowed{ - "f", "k", "i", "c", "trials", "deterministic", "inform", "ordering", "cmf", - "rollback", "targetpole" + "fanout", "rounds", "iters", "criterion", "trials", "deterministic", + "inform", "ordering", "cmf", "rollback", "targetpole" }; spec->checkAllowedKeys(allowed); - f_ = spec->getOrDefault("f", f_); - k_max_ = spec->getOrDefault("k", k_max_); - num_iters_ = spec->getOrDefault("i", num_iters_); + f_ = spec->getOrDefault("fanout", f_); + k_max_ = spec->getOrDefault("rounds", k_max_); + num_iters_ = spec->getOrDefault("iters", num_iters_); num_trials_ = spec->getOrDefault("trials", num_trials_); deterministic_ = spec->getOrDefault("deterministic", deterministic_); rollback_ = spec->getOrDefault("rollback", rollback_); target_pole_ = spec->getOrDefault("targetpole", target_pole_); EnumConverter criterion_converter_( - "c", "CriterionEnum", { + "criterion", "CriterionEnum", { {CriterionEnum::Grapevine, "Grapevine"}, {CriterionEnum::ModifiedGrapevine, "ModifiedGrapevine"} } @@ -138,9 +138,9 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { if (theContext()->getNode() == 0) { vt_debug_print( terse, gossiplb, - "GossipLB::inputParams: using f={}, k={}, i={}, c={}, trials={}, " - "deterministic={}, inform={}, ordering={}, cmf={}, rollback={}, " - "targetpole={}\n", + "GossipLB::inputParams: using fanout={}, rounds={}, iters={}, " + "criterion={}, trials={}, deterministic={}, inform={}, ordering={}, " + "cmf={}, rollback={}, targetpole={}\n", f_, k_max_, num_iters_, criterion_converter_.getString(criterion_), num_trials_, deterministic_, inform_type_converter_.getString(inform_type_), From dea700a2f6147b30118382f1fae1dfeb285d9872 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:03:57 -0700 Subject: [PATCH 04/27] #1376: gossiplb: added option for auto setting rounds and fanout LB arg knowledge can choose rounds and/or fanout automatically. The default behavior has been changed to set both automatically. --- .../balance/gossiplb/gossip_enums.h | 23 ++++ .../collection/balance/gossiplb/gossiplb.cc | 104 ++++++++++++++++-- .../collection/balance/gossiplb/gossiplb.h | 1 + 3 files changed, 117 insertions(+), 11 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index 9fae1b3ff9..b62f2ce255 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -203,6 +203,29 @@ enum struct CMFTypeEnum : uint8_t { NormByMaxExcludeIneligible = 3, }; +/// Enum for determining fanout and rounds +enum struct KnowledgeEnum : uint8_t { + /** + * \brief User defined values of fanout and rounds + * + * The fanout and rounds must be set explicitly + */ + UserDefined = 0, + /** + * \brief Full information + * + * The fanout will be as large as possible, with only one round + */ + Complete = 1, + /** + * \brief Choose rounds and/or fanout based on log rule + * + * The relationship between rounds and fanout will be approximately + * rounds = log(num_ranks)/log(fanout). + */ + Log = 2 +}; + }}}} /* end namespace vt::vrt::collection::lb */ #endif /*INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H*/ diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index 9e76288b15..70545ed403 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -76,13 +76,96 @@ bool GossipLB::isOverloaded(LoadType load) const { void GossipLB::inputParams(balance::SpecEntry* spec) { std::vector allowed{ - "fanout", "rounds", "iters", "criterion", "trials", "deterministic", - "inform", "ordering", "cmf", "rollback", "targetpole" + "knowledge", "fanout", "rounds", "iters", "criterion", "trials", + "deterministic", "inform", "ordering", "cmf", "rollback", "targetpole", }; spec->checkAllowedKeys(allowed); - f_ = spec->getOrDefault("fanout", f_); - k_max_ = spec->getOrDefault("rounds", k_max_); + // the following options interact with each other, so we need to know + // which were defaulted and which were explicitly specified + auto params = spec->getParams(); + bool specified_knowledge = params.find("knowledge") != params.end(); + bool specified_fanout = params.find("fanout") != params.end(); + bool specified_rounds = params.find("rounds") != params.end(); + + EnumConverter knowledge_converter_( + "knowledge", "KnowledgeEnum", { + {KnowledgeEnum::UserDefined, "UserDefined"}, + {KnowledgeEnum::Complete, "Complete"}, + {KnowledgeEnum::Log, "Log"} + } + ); + knowledge_ = knowledge_converter_.getFromSpec(spec, knowledge_); + + vtAbortIf( + specified_knowledge && knowledge_ == KnowledgeEnum::Log && + specified_fanout && specified_rounds, + "GossipLB: You must leave fanout and/or rounds unspecified when " + "knowledge=Log" + ); + vtAbortIf( + !specified_knowledge && knowledge_ == KnowledgeEnum::Log && + specified_fanout && specified_rounds, + "GossipLB: You must use knowledge=UserDefined if you want to explicitly " + "set both fanout and rounds" + ); + vtAbortIf( + knowledge_ == KnowledgeEnum::Complete && + (specified_fanout || specified_rounds), + "GossipLB: You must leave fanout and rounds unspecified when " + "knowledge=Complete" + ); + vtAbortIf( + knowledge_ == KnowledgeEnum::UserDefined && + (!specified_fanout || !specified_rounds), + "GossipLB: You must explicitly set both fanout and rounds when " + "knowledge=UserDefined" + ); + + auto num_nodes = theContext()->getNumNodes(); + if (knowledge_ == KnowledgeEnum::Log) { + if (specified_fanout) { + // set the rounds based on the chosen fanout: k=log_f(p) + f_ = spec->getOrDefault("fanout", f_); + k_max_ = static_cast( + std::ceil(std::log(num_nodes)/std::log(f_)) + ); + } else if (specified_rounds) { + // set the fanout based on the chosen rounds: f=p^(1/k) + k_max_ = spec->getOrDefault("rounds", k_max_); + f_ = static_cast(std::ceil(std::pow(num_nodes, 1.0/k_max_))); + } else { + // set both the fanout and the rounds + k_max_ = static_cast( + std::round(std::sqrt(std::log(num_nodes)/std::log(2.0))) + ); + f_ = static_cast(std::ceil(std::pow(num_nodes, 1.0/k_max_))); + } + } else if (knowledge_ == KnowledgeEnum::Complete) { + f_ = num_nodes - 1; + k_max_ = 1; + } else { // knowledge_ == KnowledgeEnum::UserDefined + // if either of these was omitted, a default will be used, which probably + // isn't desirable + f_ = spec->getOrDefault("fanout", f_); + k_max_ = spec->getOrDefault("rounds", k_max_); + } + + if (f_ < 1) { + auto s = fmt::format( + "GossipLB: fanout={} is invalid; fanout must be positive", + f_ + ); + vtAbort(s); + } + if (k_max_ < 1) { + auto s = fmt::format( + "GossipLB: rounds={} is invalid; rounds must be positive", + k_max_ + ); + vtAbort(s); + } + num_iters_ = spec->getOrDefault("iters", num_iters_); num_trials_ = spec->getOrDefault("trials", num_trials_); deterministic_ = spec->getOrDefault("deterministic", deterministic_); @@ -138,15 +221,14 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { if (theContext()->getNode() == 0) { vt_debug_print( terse, gossiplb, - "GossipLB::inputParams: using fanout={}, rounds={}, iters={}, " - "criterion={}, trials={}, deterministic={}, inform={}, ordering={}, " - "cmf={}, rollback={}, targetpole={}\n", - f_, k_max_, num_iters_, criterion_converter_.getString(criterion_), - num_trials_, deterministic_, + "GossipLB::inputParams: using knowledge={}, fanout={}, rounds={}, " + "iters={}, criterion={}, trials={}, deterministic={}, inform={}, " + "ordering={}, cmf={}, rollback={}, targetpole={}\n", + knowledge_converter_.getString(knowledge_), f_, k_max_, num_iters_, + criterion_converter_.getString(criterion_), num_trials_, deterministic_, inform_type_converter_.getString(inform_type_), obj_ordering_converter_.getString(obj_ordering_), - cmf_type_converter_.getString(cmf_type_), - rollback_, target_pole_ + cmf_type_converter_.getString(cmf_type_), rollback_, target_pole_ ); } } diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h index a864e692a3..c29f08f3df 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h @@ -169,6 +169,7 @@ struct GossipLB : BaseLB { InformTypeEnum inform_type_ = InformTypeEnum::SyncInform; ObjectOrderEnum obj_ordering_ = ObjectOrderEnum::FewestMigrations; CMFTypeEnum cmf_type_ = CMFTypeEnum::NormByMax; + KnowledgeEnum knowledge_ = KnowledgeEnum::Log; bool setup_done_ = false; bool propagate_next_round_ = false; std::vector propagated_k_; From 6869f890520d4dda19a5a22950d405b5eff83fc0 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:06:47 -0700 Subject: [PATCH 05/27] #1376: gossiplb: default to async informs --- src/vt/vrt/collection/balance/gossiplb/gossiplb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h index c29f08f3df..cdf94d94b0 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h @@ -166,7 +166,7 @@ struct GossipLB : BaseLB { TimeType new_imbalance_ = 0.0; TimeType target_max_load_ = 0.0; CriterionEnum criterion_ = CriterionEnum::ModifiedGrapevine; - InformTypeEnum inform_type_ = InformTypeEnum::SyncInform; + InformTypeEnum inform_type_ = InformTypeEnum::AsyncInform; ObjectOrderEnum obj_ordering_ = ObjectOrderEnum::FewestMigrations; CMFTypeEnum cmf_type_ = CMFTypeEnum::NormByMax; KnowledgeEnum knowledge_ = KnowledgeEnum::Log; From f4b54aca3814c3ebe94443b89e2b5f5f4da866b5 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:07:55 -0700 Subject: [PATCH 06/27] #1376: gossiplb: default to only one trial --- src/vt/vrt/collection/balance/gossiplb/gossiplb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h index cdf94d94b0..168e22cadb 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h @@ -128,7 +128,7 @@ struct GossipLB : BaseLB { * How many times to repeat the requested number of iterations, hoping to find * a better imbalance. This helps if it's easy to get stuck in a local minimum. */ - uint16_t num_trials_ = 3; + uint16_t num_trials_ = 1; /** * \brief Whether to make migration choices deterministic * From 4fc9fb590cfc2694314d9d1c83aaf401afaea0e3 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:09:43 -0700 Subject: [PATCH 07/27] #1376: gossiplb: omit migrations from terse output --- src/vt/vrt/collection/balance/gossiplb/gossiplb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index 70545ed403..706bbe74b3 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -1108,7 +1108,7 @@ void GossipLB::decide() { void GossipLB::thunkMigrations() { vt_debug_print( - terse, gossiplb, + normal, gossiplb, "thunkMigrations, total num_objs={}\n", cur_objs_.size() ); From a302101c39ce2aa07656bc2bac5c40888b5c4a54 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:23:00 -0700 Subject: [PATCH 08/27] #1376: gossiplb: use true bools for bool lb args --- src/vt/vrt/collection/balance/gossiplb/gossiplb.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index 706bbe74b3..ff24f9c955 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -168,9 +168,10 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { num_iters_ = spec->getOrDefault("iters", num_iters_); num_trials_ = spec->getOrDefault("trials", num_trials_); - deterministic_ = spec->getOrDefault("deterministic", deterministic_); - rollback_ = spec->getOrDefault("rollback", rollback_); - target_pole_ = spec->getOrDefault("targetpole", target_pole_); + + deterministic_ = spec->getOrDefault("deterministic", deterministic_); + rollback_ = spec->getOrDefault("rollback", rollback_); + target_pole_ = spec->getOrDefault("targetpole", target_pole_); EnumConverter criterion_converter_( "criterion", "CriterionEnum", { From bf8900f68747f70a20aaf8da372bee3e7d4ecc64 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:25:04 -0700 Subject: [PATCH 09/27] #1376: gossiplb: improve error messages --- src/vt/vrt/collection/balance/gossiplb/gossiplb.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index ff24f9c955..f41c2e2132 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -212,11 +212,13 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { vtAbortIf( inform_type_ == InformTypeEnum::AsyncInform && deterministic_, - "Asynchronous informs allow race conditions and thus are not deterministic" + "Asynchronous informs allow race conditions and thus are not " + "deterministic; use inform=SyncInform" ); vtAbortIf( obj_ordering_ == ObjectOrderEnum::Arbitrary && deterministic_, - "Arbitrary object ordering is not deterministic" + "Arbitrary object ordering is not deterministic; use ordering=ElmID " + "or another option" ); if (theContext()->getNode() == 0) { From 466957f368839efbf6a533e67935b14a0cc56a95 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:31:14 -0700 Subject: [PATCH 10/27] #1376: gossiplb: removes unused default values --- src/vt/vrt/collection/balance/gossiplb/gossiplb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h index 168e22cadb..8a8efad96e 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.h @@ -116,8 +116,8 @@ struct GossipLB : BaseLB { void setupDone(ReduceMsgType* msg); private: - uint16_t f_ = 4; - uint8_t k_max_ = 4; + uint16_t f_ = 0; + uint8_t k_max_ = 0; uint8_t k_cur_ = 0; uint16_t iter_ = 0; uint16_t trial_ = 0; From 72d12b1be2a3caca0801672e6005a7d7c9d7658e Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 12:46:55 -0700 Subject: [PATCH 11/27] #1376: tests: update lb args for test --- tests/unit/collection/test_lb.extended.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/unit/collection/test_lb.extended.cc b/tests/unit/collection/test_lb.extended.cc index 5c5b481c0b..33089dfd1c 100644 --- a/tests/unit/collection/test_lb.extended.cc +++ b/tests/unit/collection/test_lb.extended.cc @@ -93,12 +93,7 @@ void TestLoadBalancer::runTest() { fmt::print("Testing lb {}\n", lb_name); } if (lb_name.compare("GossipLB") == 0) { - auto nproc = vt::theContext()->getNumNodes(); - int f = std::max(1, std::min(nproc-1, 3)); - int k = nproc < 4 ? 2 : std::ceil(log(nproc)/log(f)); - auto lb_args = fmt::format( - "f={} k={} trials=1 inform=1 ordering=0 rollback=0 targetpole=0", f, k - ); + auto lb_args = fmt::format("ordering=Arbitrary rollback=false"); vt::theConfig()->vt_lb_args = lb_args; if (vt::theContext()->getNode() == 0) { fmt::print("Using lb_args {}\n", lb_args); From 513a772d9001141808eb34ecfcb975614b91339f Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 13:01:25 -0700 Subject: [PATCH 12/27] #1376: gossiplb: add hash for enums --- .../balance/gossiplb/gossip_enums.h | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index b62f2ce255..0afa6e7bd6 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -228,4 +228,44 @@ enum struct KnowledgeEnum : uint8_t { }}}} /* end namespace vt::vrt::collection::lb */ +namespace std { + +using InformTypeEnum = ::vt::vrt::collection::lb::InformTypeEnum; + +template <> +struct hash { + size_t operator()(InformTypeEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + +using ObjectOrderEnum = ::vt::vrt::collection::lb::ObjectOrderEnum; + +template <> +struct hash { + size_t operator()(ObjectOrderEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + +using CMFTypeEnum = ::vt::vrt::collection::lb::CMFTypeEnum; + +template <> +struct hash { + size_t operator()(CMFTypeEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + +using KnowledgeEnum = ::vt::vrt::collection::lb::KnowledgeEnum; + +template <> +struct hash { + size_t operator()(KnowledgeEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + +} /* end namespace std */ + #endif /*INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H*/ From 1b07d35c8c078cbba15574b3d2496332f9e3a710 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 3 May 2021 13:49:11 -0700 Subject: [PATCH 13/27] #1376: gossiplb: fix for serial load balancing tests --- src/vt/vrt/collection/balance/gossiplb/gossiplb.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index f41c2e2132..f125f9dc2a 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -136,9 +136,9 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { f_ = static_cast(std::ceil(std::pow(num_nodes, 1.0/k_max_))); } else { // set both the fanout and the rounds - k_max_ = static_cast( + k_max_ = static_cast(std::max(1.0, std::round(std::sqrt(std::log(num_nodes)/std::log(2.0))) - ); + )); f_ = static_cast(std::ceil(std::pow(num_nodes, 1.0/k_max_))); } } else if (knowledge_ == KnowledgeEnum::Complete) { From a3b34b61feb28dbb8ea9c5759882eca9bbc8051d Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Mon, 17 May 2021 15:01:38 -0700 Subject: [PATCH 14/27] #1376: gossiplb: define hash for criterion enum --- src/vt/vrt/collection/balance/gossiplb/gossip_enums.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index 0afa6e7bd6..663adf910f 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -47,6 +47,7 @@ #include "vt/config.h" #include "vt/vrt/collection/balance/read_lb.h" +#include "vt/vrt/collection/balance/gossiplb/criterion.h" #include #include @@ -230,6 +231,15 @@ enum struct KnowledgeEnum : uint8_t { namespace std { +using CriterionEnum = ::vt::vrt::collection::lb::CriterionEnum; + +template <> +struct hash { + size_t operator()(CriterionEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + using InformTypeEnum = ::vt::vrt::collection::lb::InformTypeEnum; template <> From 3f27cc5c32d1383f60b615d44927bec1a02bd046 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Wed, 26 May 2021 10:35:39 -0700 Subject: [PATCH 15/27] #1376: gossiplb: stop polluting std namespace --- .../balance/gossiplb/gossip_enums.h | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index 663adf910f..db0209d849 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -2,7 +2,7 @@ //@HEADER // ***************************************************************************** // -// gossiplb.h +// gossip_enums.h // DARMA Toolkit v. 1.0.0 // DARMA/vt => Virtual Transport // @@ -231,47 +231,37 @@ enum struct KnowledgeEnum : uint8_t { namespace std { -using CriterionEnum = ::vt::vrt::collection::lb::CriterionEnum; - template <> -struct hash { - size_t operator()(CriterionEnum const& in) const { +struct hash<::vt::vrt::collection::lb::CriterionEnum> { + size_t operator()(::vt::vrt::collection::lb::CriterionEnum const& in) const { return std::hash()(static_cast(in)); } }; -using InformTypeEnum = ::vt::vrt::collection::lb::InformTypeEnum; - template <> -struct hash { - size_t operator()(InformTypeEnum const& in) const { +struct hash<::vt::vrt::collection::lb::InformTypeEnum> { + size_t operator()(::vt::vrt::collection::lb::InformTypeEnum const& in) const { return std::hash()(static_cast(in)); } }; -using ObjectOrderEnum = ::vt::vrt::collection::lb::ObjectOrderEnum; - template <> -struct hash { - size_t operator()(ObjectOrderEnum const& in) const { +struct hash<::vt::vrt::collection::lb::ObjectOrderEnum> { + size_t operator()(::vt::vrt::collection::lb::ObjectOrderEnum const& in) const { return std::hash()(static_cast(in)); } }; -using CMFTypeEnum = ::vt::vrt::collection::lb::CMFTypeEnum; - template <> -struct hash { - size_t operator()(CMFTypeEnum const& in) const { +struct hash<::vt::vrt::collection::lb::CMFTypeEnum> { + size_t operator()(::vt::vrt::collection::lb::CMFTypeEnum const& in) const { return std::hash()(static_cast(in)); } }; -using KnowledgeEnum = ::vt::vrt::collection::lb::KnowledgeEnum; - template <> -struct hash { - size_t operator()(KnowledgeEnum const& in) const { +struct hash<::vt::vrt::collection::lb::KnowledgeEnum> { + size_t operator()(::vt::vrt::collection::lb::KnowledgeEnum const& in) const { return std::hash()(static_cast(in)); } }; From 9138c9c373a7b1d24f6802dc5a1a240c0af23fdb Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Wed, 26 May 2021 10:42:22 -0700 Subject: [PATCH 16/27] #1376: tests: clean up setting lb args --- tests/unit/collection/test_lb.extended.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/collection/test_lb.extended.cc b/tests/unit/collection/test_lb.extended.cc index 33089dfd1c..32c118e84e 100644 --- a/tests/unit/collection/test_lb.extended.cc +++ b/tests/unit/collection/test_lb.extended.cc @@ -93,7 +93,7 @@ void TestLoadBalancer::runTest() { fmt::print("Testing lb {}\n", lb_name); } if (lb_name.compare("GossipLB") == 0) { - auto lb_args = fmt::format("ordering=Arbitrary rollback=false"); + std::string lb_args("ordering=Arbitrary rollback=false"); vt::theConfig()->vt_lb_args = lb_args; if (vt::theContext()->getNode() == 0) { fmt::print("Using lb_args {}\n", lb_args); From 521989d744cd6342bcbaaec688e52eafd2d2ac92 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Wed, 26 May 2021 12:57:51 -0700 Subject: [PATCH 17/27] #1376: tests: test enum converter --- tests/unit/lb/test_gossiplb.nompi.cc | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/unit/lb/test_gossiplb.nompi.cc b/tests/unit/lb/test_gossiplb.nompi.cc index 842dc7c209..27bd0cdb7e 100644 --- a/tests/unit/lb/test_gossiplb.nompi.cc +++ b/tests/unit/lb/test_gossiplb.nompi.cc @@ -45,6 +45,7 @@ #include #include #include +#include #include "test_harness.h" @@ -211,4 +212,55 @@ TEST_F(TestGossipLB, test_gossiplb_ordering_largestobjects) { orderUsingOverloadAndVerify(order, over_avg, soln); } +/////////////////////////////////////////////////////////////////////////// + +enum struct DummyEnum : uint8_t { + One = 1, + Two = 2, + Three = 3 +}; + +}}} // end namespace vt::tests::unit + +namespace std { + +template <> +struct hash<::vt::tests::unit::DummyEnum> { + size_t operator()(::vt::tests::unit::DummyEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + +} // end namespace std + +namespace vt { namespace tests { namespace unit { + +template +void checkEnum(vrt::collection::lb::EnumConverter &conv, E e) { + EXPECT_EQ(conv.getEnum(conv.getString(e)), e); +} + +template +void checkString(vrt::collection::lb::EnumConverter &conv, const std::string &s) { + EXPECT_EQ(conv.getString(conv.getEnum(s)).compare(s), 0); +} + +TEST_F(TestGossipLB, test_enum_converter) { + vrt::collection::lb::EnumConverter dummy_( + "dummy", "DummyEnum", { + {DummyEnum::One, "One"}, + {DummyEnum::Two, "Two"}, + {DummyEnum::Three, "Three"} + } + ); + + checkEnum(dummy_, DummyEnum::One); + checkEnum(dummy_, DummyEnum::Two); + checkEnum(dummy_, DummyEnum::Three); + + checkString(dummy_, "One"); + checkString(dummy_, "Two"); + checkString(dummy_, "Three"); +} + }}} // end namespace vt::tests::unit From 21d861dd5d963ef355942fbee68ad3d12b12f0ad Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 08:52:00 -0700 Subject: [PATCH 18/27] #1376: gossiplb: clean up types --- .../balance/gossiplb/gossip_enums.h | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index db0209d849..c6e088e478 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -86,7 +86,7 @@ struct EnumConverter { return it->second; } - T getEnum(std::string s) const { + T getEnum(const std::string &s) const { auto it = str_to_enum_.find(s); if (it == str_to_enum_.end()) { auto err = fmt::format( @@ -234,35 +234,50 @@ namespace std { template <> struct hash<::vt::vrt::collection::lb::CriterionEnum> { size_t operator()(::vt::vrt::collection::lb::CriterionEnum const& in) const { - return std::hash()(static_cast(in)); + using under = std::underlying_type< + ::vt::vrt::collection::lb::CriterionEnum + >::type; + return std::hash()(static_cast(in)); } }; template <> struct hash<::vt::vrt::collection::lb::InformTypeEnum> { size_t operator()(::vt::vrt::collection::lb::InformTypeEnum const& in) const { - return std::hash()(static_cast(in)); + using under = std::underlying_type< + ::vt::vrt::collection::lb::InformTypeEnum + >::type; + return std::hash()(static_cast(in)); } }; template <> struct hash<::vt::vrt::collection::lb::ObjectOrderEnum> { size_t operator()(::vt::vrt::collection::lb::ObjectOrderEnum const& in) const { - return std::hash()(static_cast(in)); + using under = std::underlying_type< + ::vt::vrt::collection::lb::ObjectOrderEnum + >::type; + return std::hash()(static_cast(in)); } }; template <> struct hash<::vt::vrt::collection::lb::CMFTypeEnum> { size_t operator()(::vt::vrt::collection::lb::CMFTypeEnum const& in) const { - return std::hash()(static_cast(in)); + using under = std::underlying_type< + ::vt::vrt::collection::lb::CMFTypeEnum + >::type; + return std::hash()(static_cast(in)); } }; template <> struct hash<::vt::vrt::collection::lb::KnowledgeEnum> { size_t operator()(::vt::vrt::collection::lb::KnowledgeEnum const& in) const { - return std::hash()(static_cast(in)); + using under = std::underlying_type< + ::vt::vrt::collection::lb::KnowledgeEnum + >::type; + return std::hash()(static_cast(in)); } }; From ca84c8aa6aee87b29d1575cbd59a376fff42033a Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 09:16:47 -0700 Subject: [PATCH 19/27] #1376: gossiplb: document enum converter --- .../balance/gossiplb/gossip_enums.h | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index c6e088e478..cf7625d980 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -74,6 +74,12 @@ struct EnumConverter { virtual ~EnumConverter() = default; + /** + * \brief Convert from an enumerated value to a string + * + * Using the mapping provided at construction, return the string to which the + * passed enumerated value maps. + */ std::string getString(T e) const { auto it = enum_to_str_.find(e); if (it == enum_to_str_.end()) { @@ -86,6 +92,12 @@ struct EnumConverter { return it->second; } + /** + * \brief Convert from string to the enumerated value + * + * Using the reverse of the mapping provided at construction, return the + * enumerated value to which the passed string maps. + */ T getEnum(const std::string &s) const { auto it = str_to_enum_.find(s); if (it == str_to_enum_.end()) { @@ -98,6 +110,12 @@ struct EnumConverter { return it->second; } + /** + * \brief Read string from the spec and convert to enum + * + * Read the string from the spec entry and convert it to an enumerated value + * using the reverse of the mapping provided at construction. + */ T getFromSpec(balance::SpecEntry* spec, T def_value) const { std::string spec_value = spec->getOrDefault( par_name_, getString(def_value) @@ -105,10 +123,10 @@ struct EnumConverter { return getEnum(spec_value); } - EnumToStrMap enum_to_str_; - StrToEnumMap str_to_enum_; - std::string par_name_; - std::string enum_type_; + EnumToStrMap enum_to_str_; //< 1 to 1 mapping of enumerated values to strings + StrToEnumMap str_to_enum_; //< 1 to 1 mapping of strings to enumerated values + std::string par_name_; //< parameter to look for in the spec file + std::string enum_type_; //< name of the enumerated type for error handling }; /// Enum for gossiping approach From a2c9bcfff7a624eb5d38c48ca3d847d522adf877 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 10:03:29 -0700 Subject: [PATCH 20/27] #1376: gossiplb: additional doxygen for enum converter --- .../vrt/collection/balance/gossiplb/gossip_enums.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index cf7625d980..1f1019e753 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -54,11 +54,25 @@ namespace vt { namespace vrt { namespace collection { namespace lb { +/** + * \struct EnumConverter + * + * \brief A VT component that converts enumerated values to their + * stringifications for the purposes of reading LB arguments from the LB + * spec file. + */ template struct EnumConverter { using EnumToStrMap = typename std::unordered_map; using StrToEnumMap = typename std::unordered_map; + /** + * \brief Construct a converter for a specific enumerated type + * + * \param[in] par_name name of the LB arg in the spec file + * \param[in] enum_type name of the enumerated type being converted + * \param[in] enum_to_str unordered map of enumerated values to their strings + */ EnumConverter( const std::string &par_name, const std::string &enum_type, From c304a07c60b2e29bcb69dbbddcac88fc7e777f57 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 11:36:14 -0700 Subject: [PATCH 21/27] #1376: gossiplb: rename enum converter --- .../balance/gossiplb/gossip_enums.h | 22 ++++++++++++------- .../collection/balance/gossiplb/gossiplb.cc | 10 ++++----- tests/unit/lb/test_gossiplb.nompi.cc | 8 ++++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index 1f1019e753..131c6685f2 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -55,14 +55,14 @@ namespace vt { namespace vrt { namespace collection { namespace lb { /** - * \struct EnumConverter + * \struct LBArgsEnumConverter * * \brief A VT component that converts enumerated values to their * stringifications for the purposes of reading LB arguments from the LB * spec file. */ template -struct EnumConverter { +struct LBArgsEnumConverter { using EnumToStrMap = typename std::unordered_map; using StrToEnumMap = typename std::unordered_map; @@ -73,7 +73,7 @@ struct EnumConverter { * \param[in] enum_type name of the enumerated type being converted * \param[in] enum_to_str unordered map of enumerated values to their strings */ - EnumConverter( + LBArgsEnumConverter( const std::string &par_name, const std::string &enum_type, const EnumToStrMap &enum_to_str @@ -86,7 +86,7 @@ struct EnumConverter { } } - virtual ~EnumConverter() = default; + virtual ~LBArgsEnumConverter() = default; /** * \brief Convert from an enumerated value to a string @@ -97,9 +97,12 @@ struct EnumConverter { std::string getString(T e) const { auto it = enum_to_str_.find(e); if (it == enum_to_str_.end()) { + // this error indicates that you need to update the constructor for + // this converter to include all options auto err = fmt::format( - "GossipLB EnumConverter: enum '{}' value '{}' was not found in the map", - enum_type_, e + "LBArgsEnumConverter: enum '{}' value '{}' corresponding to LB " + "argument '{}' does not have a string associated with it", + enum_type_, e, par_name_ ); vtAbort(err); } @@ -115,9 +118,12 @@ struct EnumConverter { T getEnum(const std::string &s) const { auto it = str_to_enum_.find(s); if (it == str_to_enum_.end()) { + // either the user typed something in wrong or you need to update the + // constructor for this converter to include all options auto err = fmt::format( - "GossipLB: LB argument '{}' value '{}' is not recognized", - par_name_, s + "LBArgsEnumConverter: LB argument '{}' string '{}' is not a recognized " + "option for enum '{}'", + par_name_, s, enum_type_ ); vtAbort(err); } diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index f125f9dc2a..7ed43ae7e8 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -88,7 +88,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { bool specified_fanout = params.find("fanout") != params.end(); bool specified_rounds = params.find("rounds") != params.end(); - EnumConverter knowledge_converter_( + LBArgsEnumConverter knowledge_converter_( "knowledge", "KnowledgeEnum", { {KnowledgeEnum::UserDefined, "UserDefined"}, {KnowledgeEnum::Complete, "Complete"}, @@ -173,7 +173,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { rollback_ = spec->getOrDefault("rollback", rollback_); target_pole_ = spec->getOrDefault("targetpole", target_pole_); - EnumConverter criterion_converter_( + LBArgsEnumConverter criterion_converter_( "criterion", "CriterionEnum", { {CriterionEnum::Grapevine, "Grapevine"}, {CriterionEnum::ModifiedGrapevine, "ModifiedGrapevine"} @@ -181,7 +181,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { ); criterion_ = criterion_converter_.getFromSpec(spec, criterion_); - EnumConverter inform_type_converter_( + LBArgsEnumConverter inform_type_converter_( "inform", "InformTypeEnum", { {InformTypeEnum::SyncInform, "SyncInform"}, {InformTypeEnum::AsyncInform, "AsyncInform"} @@ -189,7 +189,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { ); inform_type_ = inform_type_converter_.getFromSpec(spec, inform_type_); - EnumConverter obj_ordering_converter_( + LBArgsEnumConverter obj_ordering_converter_( "ordering", "ObjectOrderEnum", { {ObjectOrderEnum::Arbitrary, "Arbitrary"}, {ObjectOrderEnum::ElmID, "ElmID"}, @@ -200,7 +200,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { ); obj_ordering_ = obj_ordering_converter_.getFromSpec(spec, obj_ordering_); - EnumConverter cmf_type_converter_( + LBArgsEnumConverter cmf_type_converter_( "cmf", "CMFTypeEnum", { {CMFTypeEnum::Original, "Original"}, {CMFTypeEnum::NormByMax, "NormByMax"}, diff --git a/tests/unit/lb/test_gossiplb.nompi.cc b/tests/unit/lb/test_gossiplb.nompi.cc index 27bd0cdb7e..93be54b5bf 100644 --- a/tests/unit/lb/test_gossiplb.nompi.cc +++ b/tests/unit/lb/test_gossiplb.nompi.cc @@ -236,17 +236,19 @@ struct hash<::vt::tests::unit::DummyEnum> { namespace vt { namespace tests { namespace unit { template -void checkEnum(vrt::collection::lb::EnumConverter &conv, E e) { +void checkEnum(vrt::collection::lb::LBArgsEnumConverter &conv, E e) { EXPECT_EQ(conv.getEnum(conv.getString(e)), e); } template -void checkString(vrt::collection::lb::EnumConverter &conv, const std::string &s) { +void checkString( + vrt::collection::lb::LBArgsEnumConverter &conv, const std::string &s +) { EXPECT_EQ(conv.getString(conv.getEnum(s)).compare(s), 0); } TEST_F(TestGossipLB, test_enum_converter) { - vrt::collection::lb::EnumConverter dummy_( + vrt::collection::lb::LBArgsEnumConverter dummy_( "dummy", "DummyEnum", { {DummyEnum::One, "One"}, {DummyEnum::Two, "Two"}, From f759b6064d091d5edb87a9e1b3bcb780c5cc4753 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 11:42:34 -0700 Subject: [PATCH 22/27] #1376: gossiplb: move enum converter out of gossiplb --- .../balance/gossiplb/gossip_enums.h | 99 ------------ .../collection/balance/gossiplb/gossiplb.cc | 11 +- .../balance/lb_args_enum_converter.h | 153 ++++++++++++++++++ tests/unit/lb/test_gossiplb.nompi.cc | 2 +- 4 files changed, 160 insertions(+), 105 deletions(-) create mode 100644 src/vt/vrt/collection/balance/lb_args_enum_converter.h diff --git a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h index 131c6685f2..b084385b5d 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h +++ b/src/vt/vrt/collection/balance/gossiplb/gossip_enums.h @@ -46,109 +46,10 @@ #define INCLUDED_VT_VRT_COLLECTION_BALANCE_GOSSIPLB_GOSSIPLB_ENUMS_H #include "vt/config.h" -#include "vt/vrt/collection/balance/read_lb.h" #include "vt/vrt/collection/balance/gossiplb/criterion.h" -#include -#include - namespace vt { namespace vrt { namespace collection { namespace lb { -/** - * \struct LBArgsEnumConverter - * - * \brief A VT component that converts enumerated values to their - * stringifications for the purposes of reading LB arguments from the LB - * spec file. - */ -template -struct LBArgsEnumConverter { - using EnumToStrMap = typename std::unordered_map; - using StrToEnumMap = typename std::unordered_map; - - /** - * \brief Construct a converter for a specific enumerated type - * - * \param[in] par_name name of the LB arg in the spec file - * \param[in] enum_type name of the enumerated type being converted - * \param[in] enum_to_str unordered map of enumerated values to their strings - */ - LBArgsEnumConverter( - const std::string &par_name, - const std::string &enum_type, - const EnumToStrMap &enum_to_str - ) : enum_to_str_(enum_to_str), - par_name_(par_name), - enum_type_(enum_type) - { - for (const auto &it : enum_to_str_) { - str_to_enum_[it.second] = it.first; - } - } - - virtual ~LBArgsEnumConverter() = default; - - /** - * \brief Convert from an enumerated value to a string - * - * Using the mapping provided at construction, return the string to which the - * passed enumerated value maps. - */ - std::string getString(T e) const { - auto it = enum_to_str_.find(e); - if (it == enum_to_str_.end()) { - // this error indicates that you need to update the constructor for - // this converter to include all options - auto err = fmt::format( - "LBArgsEnumConverter: enum '{}' value '{}' corresponding to LB " - "argument '{}' does not have a string associated with it", - enum_type_, e, par_name_ - ); - vtAbort(err); - } - return it->second; - } - - /** - * \brief Convert from string to the enumerated value - * - * Using the reverse of the mapping provided at construction, return the - * enumerated value to which the passed string maps. - */ - T getEnum(const std::string &s) const { - auto it = str_to_enum_.find(s); - if (it == str_to_enum_.end()) { - // either the user typed something in wrong or you need to update the - // constructor for this converter to include all options - auto err = fmt::format( - "LBArgsEnumConverter: LB argument '{}' string '{}' is not a recognized " - "option for enum '{}'", - par_name_, s, enum_type_ - ); - vtAbort(err); - } - return it->second; - } - - /** - * \brief Read string from the spec and convert to enum - * - * Read the string from the spec entry and convert it to an enumerated value - * using the reverse of the mapping provided at construction. - */ - T getFromSpec(balance::SpecEntry* spec, T def_value) const { - std::string spec_value = spec->getOrDefault( - par_name_, getString(def_value) - ); - return getEnum(spec_value); - } - - EnumToStrMap enum_to_str_; //< 1 to 1 mapping of enumerated values to strings - StrToEnumMap str_to_enum_; //< 1 to 1 mapping of strings to enumerated values - std::string par_name_; //< parameter to look for in the spec file - std::string enum_type_; //< name of the enumerated type for error handling -}; - /// Enum for gossiping approach enum struct InformTypeEnum : uint8_t { /** diff --git a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc index 7ed43ae7e8..83e43ba6a1 100644 --- a/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc +++ b/src/vt/vrt/collection/balance/gossiplb/gossiplb.cc @@ -48,6 +48,7 @@ #include "vt/vrt/collection/balance/gossiplb/gossip_msg.h" #include "vt/vrt/collection/balance/gossiplb/gossip_constants.h" #include "vt/vrt/collection/balance/gossiplb/criterion.h" +#include "vt/vrt/collection/balance/lb_args_enum_converter.h" #include "vt/context/context.h" #include @@ -88,7 +89,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { bool specified_fanout = params.find("fanout") != params.end(); bool specified_rounds = params.find("rounds") != params.end(); - LBArgsEnumConverter knowledge_converter_( + balance::LBArgsEnumConverter knowledge_converter_( "knowledge", "KnowledgeEnum", { {KnowledgeEnum::UserDefined, "UserDefined"}, {KnowledgeEnum::Complete, "Complete"}, @@ -173,7 +174,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { rollback_ = spec->getOrDefault("rollback", rollback_); target_pole_ = spec->getOrDefault("targetpole", target_pole_); - LBArgsEnumConverter criterion_converter_( + balance::LBArgsEnumConverter criterion_converter_( "criterion", "CriterionEnum", { {CriterionEnum::Grapevine, "Grapevine"}, {CriterionEnum::ModifiedGrapevine, "ModifiedGrapevine"} @@ -181,7 +182,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { ); criterion_ = criterion_converter_.getFromSpec(spec, criterion_); - LBArgsEnumConverter inform_type_converter_( + balance::LBArgsEnumConverter inform_type_converter_( "inform", "InformTypeEnum", { {InformTypeEnum::SyncInform, "SyncInform"}, {InformTypeEnum::AsyncInform, "AsyncInform"} @@ -189,7 +190,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { ); inform_type_ = inform_type_converter_.getFromSpec(spec, inform_type_); - LBArgsEnumConverter obj_ordering_converter_( + balance::LBArgsEnumConverter obj_ordering_converter_( "ordering", "ObjectOrderEnum", { {ObjectOrderEnum::Arbitrary, "Arbitrary"}, {ObjectOrderEnum::ElmID, "ElmID"}, @@ -200,7 +201,7 @@ void GossipLB::inputParams(balance::SpecEntry* spec) { ); obj_ordering_ = obj_ordering_converter_.getFromSpec(spec, obj_ordering_); - LBArgsEnumConverter cmf_type_converter_( + balance::LBArgsEnumConverter cmf_type_converter_( "cmf", "CMFTypeEnum", { {CMFTypeEnum::Original, "Original"}, {CMFTypeEnum::NormByMax, "NormByMax"}, diff --git a/src/vt/vrt/collection/balance/lb_args_enum_converter.h b/src/vt/vrt/collection/balance/lb_args_enum_converter.h new file mode 100644 index 0000000000..f9f6ed6059 --- /dev/null +++ b/src/vt/vrt/collection/balance/lb_args_enum_converter.h @@ -0,0 +1,153 @@ +/* +//@HEADER +// ***************************************************************************** +// +// lb_args_enum_converter.h +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_VRT_COLLECTION_BALANCE_LB_ARGS_ENUM_CONVERTER_H +#define INCLUDED_VT_VRT_COLLECTION_BALANCE_LB_ARGS_ENUM_CONVERTER_H + +#include "vt/config.h" +#include "vt/vrt/collection/balance/read_lb.h" + +#include +#include + +namespace vt { namespace vrt { namespace collection { namespace balance { + +/** + * \struct LBArgsEnumConverter + * + * \brief A VT component that converts enumerated values to their + * stringifications for the purposes of reading LB arguments from the LB + * spec file. + */ +template +struct LBArgsEnumConverter { + using EnumToStrMap = typename std::unordered_map; + using StrToEnumMap = typename std::unordered_map; + + /** + * \brief Construct a converter for a specific enumerated type + * + * \param[in] par_name name of the LB arg in the spec file + * \param[in] enum_type name of the enumerated type being converted + * \param[in] enum_to_str unordered map of enumerated values to their strings + */ + LBArgsEnumConverter( + const std::string &par_name, + const std::string &enum_type, + const EnumToStrMap &enum_to_str + ) : enum_to_str_(enum_to_str), + par_name_(par_name), + enum_type_(enum_type) + { + for (const auto &it : enum_to_str_) { + str_to_enum_[it.second] = it.first; + } + } + + virtual ~LBArgsEnumConverter() = default; + + /** + * \brief Convert from an enumerated value to a string + * + * Using the mapping provided at construction, return the string to which the + * passed enumerated value maps. + */ + std::string getString(T e) const { + auto it = enum_to_str_.find(e); + if (it == enum_to_str_.end()) { + // this error indicates that you need to update the constructor for + // this converter to include all options + auto err = fmt::format( + "LBArgsEnumConverter: enum '{}' value '{}' corresponding to LB " + "argument '{}' does not have a string associated with it", + enum_type_, e, par_name_ + ); + vtAbort(err); + } + return it->second; + } + + /** + * \brief Convert from string to the enumerated value + * + * Using the reverse of the mapping provided at construction, return the + * enumerated value to which the passed string maps. + */ + T getEnum(const std::string &s) const { + auto it = str_to_enum_.find(s); + if (it == str_to_enum_.end()) { + // either the user typed something in wrong or you need to update the + // constructor for this converter to include all options + auto err = fmt::format( + "LBArgsEnumConverter: LB argument '{}' string '{}' is not a recognized " + "option for enum '{}'", + par_name_, s, enum_type_ + ); + vtAbort(err); + } + return it->second; + } + + /** + * \brief Read string from the spec and convert to enum + * + * Read the string from the spec entry and convert it to an enumerated value + * using the reverse of the mapping provided at construction. + */ + T getFromSpec(balance::SpecEntry* spec, T def_value) const { + std::string spec_value = spec->getOrDefault( + par_name_, getString(def_value) + ); + return getEnum(spec_value); + } + + EnumToStrMap enum_to_str_; //< 1 to 1 mapping of enumerated values to strings + StrToEnumMap str_to_enum_; //< 1 to 1 mapping of strings to enumerated values + std::string par_name_; //< parameter to look for in the spec file + std::string enum_type_; //< name of the enumerated type for error handling +}; + +}}}} /* end namespace vt::vrt::collection::balance */ + +#endif /*INCLUDED_VT_VRT_COLLECTION_BALANCE_LB_ARGS_ENUM_CONVERTER_H*/ diff --git a/tests/unit/lb/test_gossiplb.nompi.cc b/tests/unit/lb/test_gossiplb.nompi.cc index 93be54b5bf..40410b7aad 100644 --- a/tests/unit/lb/test_gossiplb.nompi.cc +++ b/tests/unit/lb/test_gossiplb.nompi.cc @@ -45,7 +45,7 @@ #include #include #include -#include +#include "vt/vrt/collection/balance/lb_args_enum_converter.h" #include "test_harness.h" From b6514877df4015116a0cc0eddae892d33e758b5f Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 11:48:33 -0700 Subject: [PATCH 23/27] #1376: tests: split off lb args enum converter tests --- tests/unit/lb/test_gossiplb.nompi.cc | 54 ---------- tests/unit/lb/test_lbargs_enum_conv.nompi.cc | 104 +++++++++++++++++++ 2 files changed, 104 insertions(+), 54 deletions(-) create mode 100644 tests/unit/lb/test_lbargs_enum_conv.nompi.cc diff --git a/tests/unit/lb/test_gossiplb.nompi.cc b/tests/unit/lb/test_gossiplb.nompi.cc index 40410b7aad..842dc7c209 100644 --- a/tests/unit/lb/test_gossiplb.nompi.cc +++ b/tests/unit/lb/test_gossiplb.nompi.cc @@ -45,7 +45,6 @@ #include #include #include -#include "vt/vrt/collection/balance/lb_args_enum_converter.h" #include "test_harness.h" @@ -212,57 +211,4 @@ TEST_F(TestGossipLB, test_gossiplb_ordering_largestobjects) { orderUsingOverloadAndVerify(order, over_avg, soln); } -/////////////////////////////////////////////////////////////////////////// - -enum struct DummyEnum : uint8_t { - One = 1, - Two = 2, - Three = 3 -}; - -}}} // end namespace vt::tests::unit - -namespace std { - -template <> -struct hash<::vt::tests::unit::DummyEnum> { - size_t operator()(::vt::tests::unit::DummyEnum const& in) const { - return std::hash()(static_cast(in)); - } -}; - -} // end namespace std - -namespace vt { namespace tests { namespace unit { - -template -void checkEnum(vrt::collection::lb::LBArgsEnumConverter &conv, E e) { - EXPECT_EQ(conv.getEnum(conv.getString(e)), e); -} - -template -void checkString( - vrt::collection::lb::LBArgsEnumConverter &conv, const std::string &s -) { - EXPECT_EQ(conv.getString(conv.getEnum(s)).compare(s), 0); -} - -TEST_F(TestGossipLB, test_enum_converter) { - vrt::collection::lb::LBArgsEnumConverter dummy_( - "dummy", "DummyEnum", { - {DummyEnum::One, "One"}, - {DummyEnum::Two, "Two"}, - {DummyEnum::Three, "Three"} - } - ); - - checkEnum(dummy_, DummyEnum::One); - checkEnum(dummy_, DummyEnum::Two); - checkEnum(dummy_, DummyEnum::Three); - - checkString(dummy_, "One"); - checkString(dummy_, "Two"); - checkString(dummy_, "Three"); -} - }}} // end namespace vt::tests::unit diff --git a/tests/unit/lb/test_lbargs_enum_conv.nompi.cc b/tests/unit/lb/test_lbargs_enum_conv.nompi.cc new file mode 100644 index 0000000000..69605c19ea --- /dev/null +++ b/tests/unit/lb/test_lbargs_enum_conv.nompi.cc @@ -0,0 +1,104 @@ +/* +//@HEADER +// ***************************************************************************** +// +// test_lbargs_enum_conv.nompi.cc +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#include "vt/vrt/collection/balance/lb_args_enum_converter.h" + +#include "test_harness.h" + +namespace vt { namespace tests { namespace unit { + +using TestLBArgsEnumConverter = TestHarness; + +enum struct DummyEnum : uint8_t { + One = 1, + Two = 2, + Three = 3 +}; + +}}} // end namespace vt::tests::unit + +namespace std { + +template <> +struct hash<::vt::tests::unit::DummyEnum> { + size_t operator()(::vt::tests::unit::DummyEnum const& in) const { + return std::hash()(static_cast(in)); + } +}; + +} // end namespace std + +namespace vt { namespace tests { namespace unit { + +template +void checkEnum(vrt::collection::balance::LBArgsEnumConverter &conv, E e) { + EXPECT_EQ(conv.getEnum(conv.getString(e)), e); +} + +template +void checkString( + vrt::collection::balance::LBArgsEnumConverter &conv, const std::string &s +) { + EXPECT_EQ(conv.getString(conv.getEnum(s)).compare(s), 0); +} + +TEST_F(TestLBArgsEnumConverter, test_enum_converter_mapping) { + vrt::collection::balance::LBArgsEnumConverter dummy_( + "dummy", "DummyEnum", { + {DummyEnum::One, "One"}, + {DummyEnum::Two, "Two"}, + {DummyEnum::Three, "Three"} + } + ); + + checkEnum(dummy_, DummyEnum::One); + checkEnum(dummy_, DummyEnum::Two); + checkEnum(dummy_, DummyEnum::Three); + + checkString(dummy_, "One"); + checkString(dummy_, "Two"); + checkString(dummy_, "Three"); +} + +}}} // end namespace vt::tests::unit From e69157251040c7f97a76b7c174ac83bfd1f58e94 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Thu, 27 May 2021 12:10:07 -0700 Subject: [PATCH 24/27] #1376: tests: add spec-related to enum conversion --- tests/unit/lb/test_lbargs_enum_conv.nompi.cc | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/unit/lb/test_lbargs_enum_conv.nompi.cc b/tests/unit/lb/test_lbargs_enum_conv.nompi.cc index 69605c19ea..913c1b80ff 100644 --- a/tests/unit/lb/test_lbargs_enum_conv.nompi.cc +++ b/tests/unit/lb/test_lbargs_enum_conv.nompi.cc @@ -43,6 +43,7 @@ */ #include "vt/vrt/collection/balance/lb_args_enum_converter.h" +#include "vt/vrt/collection/balance/read_lb.h" #include "test_harness.h" @@ -101,4 +102,33 @@ TEST_F(TestLBArgsEnumConverter, test_enum_converter_mapping) { checkString(dummy_, "Three"); } +TEST_F(TestLBArgsEnumConverter, test_enum_converter_spec) { + vrt::collection::balance::LBArgsEnumConverter dummy_( + "dummy", "DummyEnum", { + {DummyEnum::One, "One"}, + {DummyEnum::Two, "Two"}, + {DummyEnum::Three, "Three"} + } + ); + // normally this wouldn't reuse the same enum, but we're just testing + // spec-related stuff here so it's fine + vrt::collection::balance::LBArgsEnumConverter count_( + "count", "DummyEnum", { + {DummyEnum::One, "One"}, + {DummyEnum::Two, "Two"}, + {DummyEnum::Three, "Three"} + } + ); + + std::string spec_string("dummy=Two"); // deliberately omit 'count=' + auto spec = vrt::collection::balance::ReadLBSpec::makeSpecFromParams( + spec_string + ); + + // explicitly specified should return specified value + EXPECT_EQ(dummy_.getFromSpec(&spec, DummyEnum::One), DummyEnum::Two); + // unspecified should return default value + EXPECT_EQ(count_.getFromSpec(&spec, DummyEnum::One), DummyEnum::One); +} + }}} // end namespace vt::tests::unit From 47989b17022dc382dd8c0e6328ed40be72b223c5 Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Fri, 28 May 2021 10:38:30 -0700 Subject: [PATCH 25/27] #1376: tests: add throw tests for enum conversion --- tests/unit/lb/test_lbargs_enum_conv.nompi.cc | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/unit/lb/test_lbargs_enum_conv.nompi.cc b/tests/unit/lb/test_lbargs_enum_conv.nompi.cc index 913c1b80ff..bfb56b20f4 100644 --- a/tests/unit/lb/test_lbargs_enum_conv.nompi.cc +++ b/tests/unit/lb/test_lbargs_enum_conv.nompi.cc @@ -100,6 +100,23 @@ TEST_F(TestLBArgsEnumConverter, test_enum_converter_mapping) { checkString(dummy_, "One"); checkString(dummy_, "Two"); checkString(dummy_, "Three"); + + ASSERT_THROW( + dummy_.getString(static_cast(0)), + std::runtime_error + ); + ASSERT_THROW( + dummy_.getString(static_cast(4)), + std::runtime_error + ); + ASSERT_THROW( + dummy_.getEnum("Zero"), + std::runtime_error + ); + ASSERT_THROW( + dummy_.getEnum("Four"), + std::runtime_error + ); } TEST_F(TestLBArgsEnumConverter, test_enum_converter_spec) { @@ -129,6 +146,20 @@ TEST_F(TestLBArgsEnumConverter, test_enum_converter_spec) { EXPECT_EQ(dummy_.getFromSpec(&spec, DummyEnum::One), DummyEnum::Two); // unspecified should return default value EXPECT_EQ(count_.getFromSpec(&spec, DummyEnum::One), DummyEnum::One); + + std::string bad_spec_string("dummy=Four"); + auto bad_spec = vrt::collection::balance::ReadLBSpec::makeSpecFromParams( + bad_spec_string + ); + + ASSERT_THROW( + dummy_.getFromSpec(&bad_spec, DummyEnum::One), + std::runtime_error + ); + ASSERT_THROW( + dummy_.getFromSpec(&spec, static_cast(0)), + std::runtime_error + ); } }}} // end namespace vt::tests::unit From af88059c53c32bc1a0dde031184b0e1ffde513ef Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Fri, 28 May 2021 10:40:35 -0700 Subject: [PATCH 26/27] #1456: config: remove throw_on_abort from feature list --- src/vt/configs/features/features_defines.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vt/configs/features/features_defines.h b/src/vt/configs/features/features_defines.h index b36f99af32..82f7762bc6 100644 --- a/src/vt/configs/features/features_defines.h +++ b/src/vt/configs/features/features_defines.h @@ -73,6 +73,5 @@ #define vt_feature_diagnostics_runtime 0 || vt_feature_cmake_diagnostics_runtime #define vt_feature_libfort 0 || vt_feature_cmake_libfort #define vt_feature_production_build 0 || vt_feature_cmake_production_build -#define vt_feature_throw_on_abort 0 || vt_feature_cmake_throw_on_abort #endif /*INCLUDED_VT_CONFIGS_FEATURES_FEATURES_DEFINES_H*/ From feba7b7c71fd8c54488720a9571a5049a8f9919c Mon Sep 17 00:00:00 2001 From: Nicole Lemaster Slattengren Date: Fri, 28 May 2021 10:56:21 -0700 Subject: [PATCH 27/27] #1376: balance: make data members private --- src/vt/vrt/collection/balance/lb_args_enum_converter.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vt/vrt/collection/balance/lb_args_enum_converter.h b/src/vt/vrt/collection/balance/lb_args_enum_converter.h index f9f6ed6059..db139a824a 100644 --- a/src/vt/vrt/collection/balance/lb_args_enum_converter.h +++ b/src/vt/vrt/collection/balance/lb_args_enum_converter.h @@ -142,6 +142,7 @@ struct LBArgsEnumConverter { return getEnum(spec_value); } +private: EnumToStrMap enum_to_str_; //< 1 to 1 mapping of enumerated values to strings StrToEnumMap str_to_enum_; //< 1 to 1 mapping of strings to enumerated values std::string par_name_; //< parameter to look for in the spec file