Skip to content

Commit f3ae30a

Browse files
authored
Merge pull request #2231 from DARMA-tasking/2229-add-arbitrary-attributes-to-json-validator
#2229: Add attributes field for rank and object
2 parents a1bfc61 + 81d91e0 commit f3ae30a

File tree

10 files changed

+294
-19
lines changed

10 files changed

+294
-19
lines changed

scripts/JSON_data_files_validator.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def _get_valid_schema(self) -> Schema:
6464
'range': [[int]],
6565
},
6666
},
67+
Optional('attributes'): dict
6768
},
6869
'phases': [
6970
{
@@ -88,7 +89,8 @@ def _get_valid_schema(self) -> Schema:
8889
}
8990
],
9091
'time': float,
91-
Optional('user_defined'): dict
92+
Optional('user_defined'): dict,
93+
Optional('attributes'): dict
9294
},
9395
],
9496
Optional('communications'): [

src/vt/vrt/collection/balance/lb_data_holder.cc

+58
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,26 @@ std::unique_ptr<nlohmann::json> LBDataHolder::metadataToJson() const {
125125
return std::make_unique<nlohmann::json>(std::move(j));
126126
}
127127

128+
std::unique_ptr<nlohmann::json> LBDataHolder::rankAttributesToJson() const {
129+
if (rank_attributes_.empty()) {
130+
return nullptr;
131+
}
132+
133+
nlohmann::json j;
134+
135+
for (auto const& [key, value] : rank_attributes_) {
136+
if (std::holds_alternative<int>(value)) {
137+
j["attributes"][key] = std::get<int>(value);
138+
} else if (std::holds_alternative<double>(value)) {
139+
j["attributes"][key] = std::get<double>(value);
140+
} else if (std::holds_alternative<std::string>(value)) {
141+
j["attributes"][key] = std::get<std::string>(value);
142+
}
143+
}
144+
145+
return std::make_unique<nlohmann::json>(std::move(j));
146+
}
147+
128148
std::unique_ptr<nlohmann::json> LBDataHolder::toJson(PhaseType phase) const {
129149
using json = nlohmann::json;
130150

@@ -150,6 +170,20 @@ std::unique_ptr<nlohmann::json> LBDataHolder::toJson(PhaseType phase) const {
150170
}
151171
outputEntity(j["tasks"][i]["entity"], id);
152172

173+
if (node_user_attributes_.find(phase) != node_user_attributes_.end()) {
174+
if (node_user_attributes_.at(phase).find(id) != node_user_attributes_.at(phase).end()) {
175+
for (auto const& [key, value] : node_user_attributes_.at(phase).at(id)) {
176+
if (std::holds_alternative<int>(value)) {
177+
j["tasks"][i]["attributes"][key] = std::get<int>(value);
178+
} else if (std::holds_alternative<double>(value)) {
179+
j["tasks"][i]["attributes"][key] = std::get<double>(value);
180+
} else if (std::holds_alternative<std::string>(value)) {
181+
j["tasks"][i]["attributes"][key] = std::get<std::string>(value);
182+
}
183+
}
184+
}
185+
}
186+
153187
auto const& subphase_times = elm.second.subphase_loads;
154188
std::size_t const subphases = subphase_times.size();
155189
if (subphases != 0) {
@@ -303,6 +337,18 @@ LBDataHolder::LBDataHolder(nlohmann::json const& j)
303337
}
304338
}
305339
}
340+
341+
if (task.find("attributes") != task.end()) {
342+
for (auto const& [key, value] : task["attributes"].items()) {
343+
if (value.is_number_integer()) {
344+
node_user_attributes_[id][elm][key] = value.get<int>();
345+
} else if (value.is_number_float()) {
346+
node_user_attributes_[id][elm][key] = value.get<double>();
347+
} else if (value.is_string()) {
348+
node_user_attributes_[id][elm][key] = value.get<std::string>();
349+
}
350+
}
351+
}
306352
}
307353
}
308354
}
@@ -441,6 +487,18 @@ void LBDataHolder::readMetadata(nlohmann::json const& j) {
441487
}
442488
}
443489
}
490+
// load rank user atrributes
491+
if (metadata.find("attributes") != metadata.end()) {
492+
for (auto const& [key, value] : metadata["attributes"].items()) {
493+
if (value.is_number_integer()) {
494+
rank_attributes_[key] = value.get<int>();
495+
} else if (value.is_number_float()) {
496+
rank_attributes_[key] = value.get<double>();
497+
} else if (value.is_string()) {
498+
rank_attributes_[key] = value.get<std::string>();
499+
}
500+
}
501+
}
444502
}
445503
}
446504

src/vt/vrt/collection/balance/lb_data_holder.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ struct LBDataHolder {
8585
s | skipped_phases_;
8686
s | identical_phases_;
8787
s | user_defined_lb_info_;
88+
s | node_user_attributes_;
89+
s | rank_attributes_;
8890
}
8991

9092
/**
@@ -97,12 +99,19 @@ struct LBDataHolder {
9799
std::unique_ptr<nlohmann::json> toJson(PhaseType phase) const;
98100

99101
/**
100-
* \brief Output a LB phase's metdadata to JSON
102+
* \brief Output a LB phase's metadata to JSON
101103
*
102104
* \return the json data structure
103105
*/
104106
std::unique_ptr<nlohmann::json> metadataToJson() const;
105107

108+
/**
109+
* \brief Output a LB rank attributes metadata to JSON
110+
*
111+
* \return the json data structure
112+
*/
113+
std::unique_ptr<nlohmann::json> rankAttributesToJson() const;
114+
106115
/**
107116
* \brief Clear all LB data
108117
*/
@@ -125,6 +134,8 @@ struct LBDataHolder {
125134
void readMetadata(nlohmann::json const& j);
126135

127136
public:
137+
/// Node attributes for the current rank
138+
ElmUserDataType rank_attributes_;
128139
/// Node timings for each local object
129140
std::unordered_map<PhaseType, LoadMapType> node_data_;
130141
/// Node communication graph for each local object
@@ -139,6 +150,8 @@ struct LBDataHolder {
139150
std::unordered_map<PhaseType, std::shared_ptr<nlohmann::json>> user_per_phase_json_;
140151
/// User-defined data from each phase for LB
141152
std::unordered_map<PhaseType, DataMapType> user_defined_lb_info_;
153+
/// User-defined attributes from each phase
154+
std::unordered_map<PhaseType, DataMapType> node_user_attributes_;
142155
/// Node indices for each ID along with the proxy ID
143156
std::unordered_map<ElementIDStruct, std::tuple<VirtualProxyType, std::vector<uint64_t>>> node_idx_;
144157
/// Map from id to objgroup proxy

src/vt/vrt/collection/balance/node_lb_data.cc

+19
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ NodeLBData::getUserData() const {
102102
return &lb_data_->user_defined_lb_info_;
103103
}
104104

105+
std::unordered_map<PhaseType, DataMapType> const*
106+
NodeLBData::getPhaseAttributes() const {
107+
return &lb_data_->node_user_attributes_;
108+
}
109+
105110
std::unordered_map<PhaseType, CommMapType> const* NodeLBData::getNodeComm() const {
106111
return &lb_data_->node_comm_;
107112
}
@@ -110,6 +115,10 @@ std::unordered_map<PhaseType, std::unordered_map<SubphaseType, CommMapType>> con
110115
return &lb_data_->node_subphase_comm_;
111116
}
112117

118+
ElmUserDataType const* NodeLBData::getNodeAttributes() const {
119+
return &lb_data_->rank_attributes_;
120+
}
121+
113122
CommMapType* NodeLBData::getNodeComm(PhaseType phase) {
114123
auto iter = lb_data_->node_comm_.find(phase);
115124
return (iter != lb_data_->node_comm_.end()) ? &iter->second : nullptr;
@@ -127,6 +136,7 @@ void NodeLBData::startIterCleanup(PhaseType phase, unsigned int look_back) {
127136
lb_data_->node_comm_.erase(phase - look_back);
128137
lb_data_->node_subphase_comm_.erase(phase - look_back);
129138
lb_data_->user_defined_lb_info_.erase(phase - look_back);
139+
lb_data_->node_user_attributes_.erase(phase - look_back);
130140
}
131141

132142
// Clear migrate lambdas and proxy lookup since LB is complete
@@ -215,6 +225,10 @@ void NodeLBData::createLBDataFile() {
215225
if(phasesMetadata) {
216226
metadata["phases"] = *phasesMetadata;
217227
}
228+
auto attributesMetadata = lb_data_->rankAttributesToJson();
229+
if(attributesMetadata) {
230+
metadata["attributes"] = *attributesMetadata;
231+
}
218232
lb_data_writer_ = std::make_unique<JSONAppender>(
219233
"phases", metadata, file_name, compress
220234
);
@@ -352,6 +366,11 @@ void NodeLBData::addNodeLBData(
352366
lb_data_->user_defined_lb_info_[phase][id][key] = val->toVariant();
353367
}
354368
);
369+
storable->collectAttributes(
370+
[&](std::string const& key, auto val) {
371+
lb_data_->node_user_attributes_[phase][id][key] = val->toVariant();
372+
}
373+
);
355374
}
356375

357376
in->updatePhase(1);

src/vt/vrt/collection/balance/node_lb_data.h

+14
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ struct NodeLBData : runtime::component::Component<NodeLBData> {
188188
*/
189189
std::unordered_map<PhaseType, DataMapType> const* getUserData() const;
190190

191+
/**
192+
* \internal \brief Get the user-defined attributes
193+
*
194+
* \return an observer pointer to the user-defined attributes
195+
*/
196+
std::unordered_map<PhaseType, DataMapType> const* getPhaseAttributes() const;
197+
191198
/**
192199
* \internal \brief Get stored object comm data for a specific phase
193200
*
@@ -204,6 +211,13 @@ struct NodeLBData : runtime::component::Component<NodeLBData> {
204211
*/
205212
std::unordered_map<PhaseType, std::unordered_map<SubphaseType, CommMapType>> const* getNodeSubphaseComm() const;
206213

214+
/**
215+
* \internal \brief Get stored node attributes
216+
*
217+
* \return an observer pointer to the node attributes
218+
*/
219+
ElmUserDataType const* getNodeAttributes() const;
220+
207221
/**
208222
* \internal \brief Test if this node has an object to migrate
209223
*

src/vt/vrt/collection/types/storage/storable.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,14 @@ struct Storable {
9494
* \param[in] u the value
9595
* \param[in] dump_to_json whether to include in json file
9696
* \param[in] provide_to_lb whether to provide the data to the load balancers
97+
* \param[in] dump_to_attributes whether to dump to attributes in JSON output
9798
*
9899
* \note If \c provide_to_lb is enabled, the data must be convertible to an
99100
* integer, double, or string
100101
*/
101102
template <typename U>
102103
void valInsert(
103-
std::string const& str, U&& u, bool dump_to_json, bool provide_to_lb
104+
std::string const& str, U&& u, bool dump_to_json, bool provide_to_lb, bool dump_to_attributes
104105
);
105106

106107
/**
@@ -160,6 +161,20 @@ struct Storable {
160161
}
161162
}
162163

164+
/**
165+
* \brief Traverse the map and calls Callable on each attribute
166+
*
167+
* \param[in] c the callable
168+
*/
169+
template <typename Callable>
170+
void collectAttributes(Callable&& c) {
171+
for (auto const& [key, value] : map_) {
172+
if (value->isAttribute()) {
173+
c(key, value.get());
174+
}
175+
}
176+
}
177+
163178
private:
164179
/// Map of type-erased, stored values
165180
std::unordered_map<std::string, std::unique_ptr<StoreElmBase>> map_;

src/vt/vrt/collection/types/storage/storable.impl.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,22 @@ void Storable::valInsert(std::string const& str, U&& u) {
6060
std::forward_as_tuple(str),
6161
std::forward_as_tuple(
6262
std::make_unique<StoreElm<typename std::decay<U>::type>>(
63-
std::forward<U>(u), false, false
63+
std::forward<U>(u), false, false, false
6464
)
6565
)
6666
);
6767
}
6868

6969
template <typename U>
7070
void Storable::valInsert(
71-
std::string const& str, U&& u, bool dump_to_json, bool provide_to_lb
71+
std::string const& str, U&& u, bool dump_to_json, bool provide_to_lb, bool dump_to_attributes
7272
) {
7373
map_.emplace(
7474
std::piecewise_construct,
7575
std::forward_as_tuple(str),
7676
std::forward_as_tuple(
7777
std::make_unique<StoreElm<typename std::decay<U>::type>>(
78-
std::forward<U>(u), dump_to_json, provide_to_lb
78+
std::forward<U>(u), dump_to_json, provide_to_lb, dump_to_attributes
7979
)
8080
)
8181
);

src/vt/vrt/collection/types/storage/store_elm.h

+21-6
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,12 @@ struct StoreElmBase {
7474
*
7575
* \param[in] dump_to_json whether to dump to JSON output
7676
* \param[in] provide_to_lb whether to provide to the LB
77+
* \param[in] dump_to_attributes whether to dump to attributes in JSON output
7778
*/
78-
StoreElmBase(bool dump_to_json, bool provide_to_lb)
79+
StoreElmBase(bool dump_to_json, bool provide_to_lb, bool dump_to_attributes)
7980
: dump_to_json_(dump_to_json),
80-
provide_to_lb_(provide_to_lb)
81+
provide_to_lb_(provide_to_lb),
82+
dump_to_attributes_(dump_to_attributes)
8183
{}
8284

8385
virtual ~StoreElmBase() {}
@@ -121,6 +123,7 @@ struct StoreElmBase {
121123
void serialize(SerializerT& s) {
122124
s | dump_to_json_;
123125
s | provide_to_lb_;
126+
s | dump_to_attributes_;
124127
}
125128

126129
/**
@@ -139,6 +142,15 @@ struct StoreElmBase {
139142
return provide_to_lb_;
140143
}
141144

145+
/**
146+
* \brief Whether the value should be dumped to the json attributes field
147+
*
148+
* \return whether it is an attribute
149+
*/
150+
bool isAttribute() const {
151+
return dump_to_attributes_;
152+
}
153+
142154
/**
143155
* \brief Generate the json because it is jsonable
144156
*
@@ -177,6 +189,7 @@ struct StoreElmBase {
177189
protected:
178190
bool dump_to_json_ = false;
179191
bool provide_to_lb_ = false;
192+
bool dump_to_attributes_ = false;
180193
};
181194

182195
/**
@@ -209,10 +222,11 @@ struct StoreElm<
209222
* \param[in] u the value
210223
* \param[in] dump_to_json whether to dump to json
211224
* \param[in] provide_to_lb whether to provide to LB
225+
* \param[in] dump_to_attributes whether to dump to attributes in JSON output
212226
*/
213227
template <typename U>
214-
explicit StoreElm(U&& u, bool dump_to_json, bool provide_to_lb)
215-
: StoreElmBase(dump_to_json, provide_to_lb),
228+
explicit StoreElm(U&& u, bool dump_to_json, bool provide_to_lb, bool dump_to_attributes)
229+
: StoreElmBase(dump_to_json, provide_to_lb, dump_to_attributes),
216230
elm_(std::forward<U>(u))
217231
{ }
218232

@@ -328,10 +342,11 @@ struct StoreElm<
328342
* \param[in] u the value
329343
* \param[in] dump_to_json whether to dump to json
330344
* \param[in] provide_to_lb whether to provide to LB
345+
* \param[in] dump_to_attributes whether to dump to attributes in JSON output
331346
*/
332347
template <typename U>
333-
explicit StoreElm(U&& u, bool dump_to_json, bool provide_to_lb)
334-
: StoreElmBase(dump_to_json, provide_to_lb),
348+
explicit StoreElm(U&& u, bool dump_to_json, bool provide_to_lb, bool dump_to_attributes)
349+
: StoreElmBase(dump_to_json, provide_to_lb, dump_to_attributes),
335350
wrapper_(detail::ByteWrapper<T>{std::forward<U>(u)})
336351
{ }
337352

0 commit comments

Comments
 (0)