diff --git a/src/vt/vrt/collection/balance/lb_data_holder.cc b/src/vt/vrt/collection/balance/lb_data_holder.cc index 8706a15a5f..cde3267d12 100644 --- a/src/vt/vrt/collection/balance/lb_data_holder.cc +++ b/src/vt/vrt/collection/balance/lb_data_holder.cc @@ -68,6 +68,63 @@ void LBDataHolder::outputEntity(nlohmann::json& j, ElementIDStruct const& id) co } } +std::unique_ptr LBDataHolder::metadataToJson() const { + // Find last element of a range for which it's values are incremented by 1 + auto find_last_of_range = []( + const std::set& notEmptySet, + std::set::iterator fromIt) { + vtAssert(!notEmptySet.empty(), "Input Set must be not empty"); + + do { + auto next = std::next(fromIt); + // end of a set or range + if (next == notEmptySet.end() || *fromIt + 1 != *next) { + break; + } + ++fromIt; + } while (fromIt != notEmptySet.end()); + + return fromIt; + }; + + nlohmann::json j; + j["count"] = count_; + + // Generate list and ranges of skipped phases + std::set skipped_list; + std::vector> skipped_ranges; + for (auto it = skipped_phases_.begin(); it != skipped_phases_.end(); it++) { + auto endOfRange = find_last_of_range(skipped_phases_, it); + if (it == endOfRange) { + skipped_list.insert(*it); + } else { + skipped_ranges.emplace_back(*it, *endOfRange); + it = endOfRange; + } + } + + // Generate list and ranges of identical phases + std::set identical_list; + std::vector> identical_ranges; + for (auto it = identical_phases_.begin(); it != identical_phases_.end(); + it++) { + auto endOfRange = find_last_of_range(identical_phases_, it); + if (it == endOfRange) { + identical_list.insert(*it); + } else { + identical_ranges.emplace_back(*it, *endOfRange); + it = endOfRange; + } + } + + // Save metadata + j["skipped"]["list"] = skipped_list; + j["skipped"]["range"] = skipped_ranges; + j["identical_to_previous"]["list"] = identical_list; + j["identical_to_previous"]["range"] = identical_ranges; + return std::make_unique(std::move(j)); +} + std::unique_ptr LBDataHolder::toJson(PhaseType phase) const { using json = nlohmann::json; @@ -164,9 +221,14 @@ std::unique_ptr LBDataHolder::toJson(PhaseType phase) const { return std::make_unique(std::move(j)); } -LBDataHolder::LBDataHolder(nlohmann::json const& j) { +LBDataHolder::LBDataHolder(nlohmann::json const& j) + : count_(0) +{ auto this_node = theContext()->getNode(); + // read metadata for skipped and identical phases + readMetadata(j); + auto phases = j["phases"]; if (phases.is_array()) { for (auto const& phase : phases) { @@ -307,11 +369,56 @@ LBDataHolder::LBDataHolder(nlohmann::json const& j) { // right now, so it will be ignored } +void LBDataHolder::readMetadata(nlohmann::json const& j) { + auto metadata = j["metadata"]; + if (metadata.find("phases") != metadata.end()) { + auto phases = metadata["phases"]; + // load count + vtAssertExpr(phases["count"].is_number()); + count_ = phases["count"]; + // load all skipped phases + auto sl = phases["skipped"]["list"]; + if(sl.is_array()) { + for(PhaseType skipped : sl) { + skipped_phases_.insert(skipped); + } + } + auto sr = phases["skipped"]["range"]; + if(sr.is_array()) { + for(auto const& pair : sr) { + vtAssertExpr(pair.is_array()); + for(PhaseType i = pair[0]; i <= pair[1]; i++){ + skipped_phases_.insert(i); + } + } + } + // load all identical phases + auto il = phases["identical_to_previous"]["list"]; + if(il.is_array()) { + for(PhaseType identical : il) { + identical_phases_.insert(identical); + } + } + auto ir = phases["identical_to_previous"]["range"]; + if(ir.is_array()) { + for(auto const& pair : ir) { + vtAssertExpr(pair.is_array()); + for(PhaseType i = pair[0]; i <= pair[1]; i++){ + identical_phases_.insert(i); + } + } + } + } +} + void LBDataHolder::clear() { node_comm_.clear(); node_data_.clear(); node_subphase_comm_.clear(); node_idx_.clear(); + count_ = 0; + skipped_phases_.clear(); + identical_phases_.clear(); } }}}} /* end namespace vt::vrt::collection::balance */ diff --git a/src/vt/vrt/collection/balance/lb_data_holder.h b/src/vt/vrt/collection/balance/lb_data_holder.h index ad9eeefc45..de51305d07 100644 --- a/src/vt/vrt/collection/balance/lb_data_holder.h +++ b/src/vt/vrt/collection/balance/lb_data_holder.h @@ -78,6 +78,9 @@ struct LBDataHolder { s | node_subphase_comm_; s | user_defined_json_; s | node_idx_; + s | count_; + s | skipped_phases_; + s | identical_phases_; } /** @@ -89,6 +92,13 @@ struct LBDataHolder { */ std::unique_ptr toJson(PhaseType phase) const; + /** + * \brief Output a LB phase's metdadata to JSON + * + * \return the json data structure + */ + std::unique_ptr metadataToJson() const; + /** * \brief Clear all LB data */ @@ -103,6 +113,13 @@ struct LBDataHolder { */ void outputEntity(nlohmann::json& j, ElementIDStruct const& elm_id) const; + /** + * \brief Read the LB phase's metadata + * + * \param[in] j the json + */ + void readMetadata(nlohmann::json const& j); + public: /// Node timings for each local object std::unordered_map node_data_; @@ -118,6 +135,12 @@ struct LBDataHolder { std::unordered_map>> node_idx_; /// Map from id to objgroup proxy std::unordered_map node_objgroup_; + // Number of all phases including skipped and identical + PhaseType count_; + // Set of phases that are skipped + std::set skipped_phases_; + // Set of phases which are identical to previous + std::set identical_phases_; }; }}}} /* end namespace vt::vrt::collection::balance */