Skip to content

Commit 7ca53ff

Browse files
Merge pull request #1292 from sstsimulator/devel
Automatically Merged using SST Master Branch Merger
2 parents 73f53e3 + 6fc989d commit 7ca53ff

File tree

9 files changed

+368
-327
lines changed

9 files changed

+368
-327
lines changed

src/sst/core/cfgoutput/jsonConfigOutput.cc

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ JSONConfigGraphOutput::JSONConfigGraphOutput(const char* path) : ConfigGraphOutp
3232
namespace {
3333
struct CompWrapper
3434
{
35-
SST::ConfigComponent const* comp;
36-
bool output_parition_info;
35+
SST::ConfigComponent const* comp;
36+
std::map<SST::StatisticId_t, std::string>& sharedStatMap;
37+
bool output_parition_info;
3738
};
3839

3940
struct SubCompWrapper
4041
{
41-
SST::ConfigComponent const* comp;
42+
SST::ConfigComponent const* comp;
43+
std::map<SST::StatisticId_t, std::string>& sharedStatMap;
4244
};
4345

4446
struct LinkConfPair
@@ -50,6 +52,7 @@ struct LinkConfPair
5052
struct StatPair
5153
{
5254
std::pair<std::string, unsigned long> const& statkey;
55+
std::map<SST::StatisticId_t, std::string>& sharedStatMap;
5356
SST::ConfigComponent const* comp;
5457
};
5558

@@ -69,10 +72,22 @@ struct StatGroupParamPair
6972
void
7073
to_json(json::ordered_json& j, StatPair const& sp)
7174
{
72-
auto const& name = sp.statkey.first;
73-
j = json::ordered_json { { "name", name } };
74-
7575
auto* si = sp.comp->findStatistic(sp.statkey.second);
76+
if ( si->shared ) {
77+
if ( sp.sharedStatMap.find(si->id) == sp.sharedStatMap.end() ) {
78+
std::string name = "statObj" + std::to_string(sp.sharedStatMap.size()) + "_" + si->name;
79+
sp.sharedStatMap[si->id].assign(name);
80+
j = json::ordered_json { { "name", name } };
81+
}
82+
else {
83+
std::string name = sp.sharedStatMap.find(si->id)->second;
84+
j = json::ordered_json { { "name", name } };
85+
}
86+
}
87+
else {
88+
auto const& name = sp.statkey.first;
89+
j = json::ordered_json { { "name", name } };
90+
}
7691
for ( auto const& parmItr : si->params.getKeys() ) {
7792
j["params"][parmItr] = si->params.find<std::string>(parmItr);
7893
}
@@ -93,11 +108,11 @@ to_json(json::ordered_json& j, SubCompWrapper const& comp_wrapper)
93108
}
94109

95110
for ( auto const& scItr : comp->subComponents ) {
96-
j["subcomponents"].push_back(SubCompWrapper { scItr });
111+
j["subcomponents"].push_back(SubCompWrapper { scItr, comp_wrapper.sharedStatMap });
97112
}
98113

99114
for ( auto const& pair : comp->enabledStatNames ) {
100-
j["statistics"].push_back(StatPair { pair, comp });
115+
j["statistics"].push_back(StatPair { pair, comp_wrapper.sharedStatMap, comp });
101116
}
102117
}
103118

@@ -116,11 +131,11 @@ to_json(json::ordered_json& j, CompWrapper const& comp_wrapper)
116131
}
117132

118133
for ( auto const& scItr : comp->subComponents ) {
119-
j["subcomponents"].push_back(SubCompWrapper { scItr });
134+
j["subcomponents"].push_back(SubCompWrapper { scItr, comp_wrapper.sharedStatMap });
120135
}
121136

122137
for ( auto const& pair : comp->enabledStatNames ) {
123-
j["statistics"].push_back(StatPair { pair, comp });
138+
j["statistics"].push_back(StatPair { pair, comp_wrapper.sharedStatMap, comp });
124139
}
125140

126141
if ( comp_wrapper.output_parition_info ) {
@@ -256,7 +271,7 @@ JSONConfigGraphOutput::generate(const Config* cfg, ConfigGraph* graph)
256271
if ( const_cast<ConfigComponentMap_t&>(compMap).size() == 0 ) { outputJson["components"]; }
257272

258273
for ( const auto& compItr : compMap ) {
259-
outputJson["components"].emplace_back(CompWrapper { compItr, cfg->output_partition() });
274+
outputJson["components"].emplace_back(CompWrapper { compItr, sharedStatMap, cfg->output_partition() });
260275
}
261276

262277
// no links exist in this rank
@@ -273,4 +288,6 @@ JSONConfigGraphOutput::generate(const Config* cfg, ConfigGraph* graph)
273288
// lifetime extension, but this temp is the careful way.
274289
std::string outputString = ss.str();
275290
fprintf(outputFile, "%s", outputString.c_str());
291+
292+
sharedStatMap.clear();
276293
}

src/sst/core/cfgoutput/jsonConfigOutput.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class JSONConfigGraphOutput : public ConfigGraphOutput
2424
public:
2525
JSONConfigGraphOutput(const char* path);
2626
virtual void generate(const Config* cfg, ConfigGraph* graph) override;
27+
28+
private:
29+
std::map<SST::StatisticId_t, std::string> sharedStatMap;
2730
};
2831

2932
} // namespace SST::Core

src/sst/core/serialization/impl/serialize_insertable.h

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class serialize_impl<
6060
// whether end() method exists
6161
decltype(std::declval<T>().end()),
6262

63+
// whether a clear() method exists
64+
decltype(std::declval<T>().clear()),
65+
6366
// whether get_size() can determine size because it has a matching overload
6467
decltype(get_size(std::declval<T>())),
6568

@@ -85,13 +88,22 @@ class serialize_impl<
8588
// Note: the following use struct templates because of a GCC bug which does
8689
// not allow static constexpr variable templates defined inside of a class.
8790

91+
// Whether it is a std::vector
92+
template <typename>
93+
struct is_vector : std::false_type
94+
{};
95+
96+
template <typename... Ts>
97+
struct is_vector<std::vector<Ts...>> : std::true_type
98+
{};
99+
88100
// Whether it is a std::vector<bool>
89101
template <typename>
90102
struct is_vector_bool : std::false_type
91103
{};
92104

93-
template <typename U>
94-
struct is_vector_bool<std::vector<bool, U>> : std::true_type
105+
template <typename... Ts>
106+
struct is_vector_bool<std::vector<bool, Ts...>> : std::true_type
95107
{};
96108

97109
// Whether it is a std::forward_list
@@ -103,16 +115,29 @@ class serialize_impl<
103115
struct is_forward_list<std::forward_list<Ts...>> : std::true_type
104116
{};
105117

106-
// Whether it is a "map" (i.e. has [key, value] elements)
118+
// Whether it is a simple map (not a multimap and has integral, floating-point, enum, or convertible to string keys)
107119
template <typename, typename = void>
108-
struct is_map : std::false_type
120+
struct is_simple_map : std::false_type
109121
{};
110122

111-
template <template <typename...> class U, typename... Us>
112-
struct is_map<
113-
U<Us...>, std::enable_if_t<
114-
is_same_template_v<U, std::map> || is_same_template_v<U, std::multimap> ||
115-
is_same_template_v<U, std::unordered_map> || is_same_template_v<U, std::unordered_multimap>>> :
123+
template <template <typename...> class MAP, typename KEY, typename... REST>
124+
struct is_simple_map<
125+
MAP<KEY, REST...>,
126+
std::enable_if_t<(is_same_template_v<MAP, std::map> || is_same_template_v<MAP, std::unordered_map>)&&(
127+
std::is_arithmetic_v<KEY> || std::is_enum_v<KEY> || std::is_convertible_v<KEY, std::string>)>> :
128+
std::true_type
129+
{};
130+
131+
// Whether it is a simple set (not a multiset and has integral, floating-point, enum, or convertible to string keys)
132+
template <typename, typename = void>
133+
struct is_simple_set : std::false_type
134+
{};
135+
136+
template <template <typename...> class SET, typename KEY, typename... REST>
137+
struct is_simple_set<
138+
SET<KEY, REST...>,
139+
std::enable_if_t<(is_same_template_v<SET, std::set> || is_same_template_v<SET, std::unordered_set>)&&(
140+
std::is_arithmetic_v<KEY> || std::is_enum_v<KEY> || std::is_convertible_v<KEY, std::string>)>> :
116141
std::true_type
117142
{};
118143

@@ -145,15 +170,16 @@ class serialize_impl<
145170

146171
case serializer::UNPACK:
147172
{
148-
t.~T(); // Destroy the old container
149-
new (&t) T {}; // Create an empty new container
173+
size_t size;
174+
ser.unpack(size);
175+
176+
t.clear(); // Clear the container
177+
if constexpr ( is_vector<T>::value ) t.reserve(size); // Reserve size of vector
150178

151179
// For std::forward_list, last is iterator of last element inserted
152180
decltype(t.begin()) last [[maybe_unused]];
153181
if constexpr ( is_forward_list<T>::value ) last = t.before_begin();
154182

155-
size_t size;
156-
ser.unpack(size);
157183
for ( size_t i = 0; i < size; ++i ) {
158184
value_type e {}; // For now, elements have to be default-initializable
159185
ser& e; // Unpack the element
@@ -175,26 +201,26 @@ class serialize_impl<
175201
auto* obj_map = new ObjectMapContainer<T>(&t);
176202
ser.mapper().map_hierarchy_start(name, obj_map);
177203

178-
if constexpr ( is_map<T>::value ) {
179-
// (key, value) mappings
180-
// TODO: how to handle std::multimap and std::unordered_multimap with equal keys
181-
// auto [ begin, end ] = equal_range(key) returns range of elements equal to key
204+
if constexpr ( is_vector_bool<T>::value ) {
205+
// std::vector<bool>
206+
size_t i = 0;
207+
for ( bool e : t )
208+
sst_map_object(ser, e, to_string(i++));
209+
}
210+
else if constexpr ( is_simple_map<T>::value ) {
211+
// non-multi maps with a simple key
182212
for ( auto& [key, value] : t )
183213
sst_map_object(ser, value, to_string(key));
184214
}
185-
else if constexpr ( !is_vector_bool<T>::value ) {
186-
// std::vector, std::deque, std::list, std::forward_list, std::set, std::multiset
187-
// std::unordered_set, std::unordered_multiset
215+
// TODO: handle is_simple_set
216+
else {
217+
// std::vector, std::deque, std::list, std::forward_list, std::multimap,
218+
// std::unordered_multimap, std::multiset, std::unordered_multiset, and
219+
// std::map, std::set, std::unordered_map std::unordered_set with non-simple keys
188220
size_t i = 0;
189221
for ( auto& e : t )
190222
sst_map_object(ser, (value_type&)e, to_string(i++));
191223
}
192-
else {
193-
// std::vector<bool>
194-
size_t i = 0;
195-
for ( bool e : t )
196-
sst_map_object(ser, e, to_string(i++));
197-
}
198224
ser.mapper().map_hierarchy_end();
199225
break;
200226
}

src/sst/core/testingframework/sst_unittest.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,18 @@
2222
test developer. More support functions exist within sst_unittest_support.py
2323
"""
2424

25-
import sys
25+
import multiprocessing
2626
import os
27-
import unittest
28-
import threading
2927
import signal
28+
import sys
3029
import time
31-
import multiprocessing
30+
import unittest
3231
from typing import Optional
3332

3433
import test_engine_globals
3534
from sst_unittest_support import *
36-
from test_engine_support import OSCommand
37-
from test_engine_support import check_param_type
38-
from test_engine_support import strclass
39-
from test_engine_support import strqual
40-
from test_engine_junit import JUnitTestSuite
41-
from test_engine_junit import junit_to_xml_report_file
42-
#from test_engine_junit import junit_to_xml_report_string
35+
from test_engine_junit import JUnitTestSuite, junit_to_xml_report_file
36+
from test_engine_support import check_param_type, strclass, strqual
4337

4438
if not sys.warnoptions:
4539
import warnings
@@ -370,7 +364,7 @@ def run_sst(
370364
log_fatal("OpenMPI IS NOT FOUND/AVAILABLE")
371365

372366
# Launch SST
373-
rtn = OSCommand(oscmd, output_file_path = out_file,
367+
rtn = os_command(oscmd, output_file_path = out_file,
374368
error_file_path = err_file,
375369
set_cwd = set_cwd).run(timeout_sec=timeout_sec, send_signal=send_signal, signal_sec=signal_sec)
376370
if num_ranks > 1:

0 commit comments

Comments
 (0)