18 const std::unique_ptr<View>& prev_view,
View& curr_view) {
22 for(
const auto& subgroup_type : subgroup_type_order) {
27 return subgroup_layouts;
30 const std::unique_ptr<View>& prev_view,
View& curr_view) {
32 for(
const auto& subgroup_type : subgroup_type_order) {
37 return subgroup_layouts;
41 const std::string conf_profile_prefix =
"SUBGROUP/" + profile +
"/";
49 int max_nodes_per_shard,
const std::string& profile) {
51 num_shards,
true, min_nodes_per_shard, max_nodes_per_shard,
Mode::ORDERED, profile, {}, {}, {}, {}};
56 const std::string& profile) {
58 num_shards,
true, nodes_per_shard, nodes_per_shard,
Mode::ORDERED, profile, {}, {}, {}, {}};
62 const std::string& profile) {
64 num_shards,
true, nodes_per_shard, nodes_per_shard,
Mode::UNORDERED, profile, {}, {}, {}, {}};
68 const std::vector<std::string>& profiles_by_shard) {
69 std::vector<int> min_nodes_by_shard;
70 std::vector<int> max_nodes_by_shard;
71 for(
const std::string& profile : profiles_by_shard) {
72 const std::string conf_profile_prefix =
"SUBGROUP/" + profile +
"/";
77 delivery_modes_by_shard, profiles_by_shard);
81 const std::vector<int>& max_nodes_by_shard,
82 const std::vector<Mode>& delivery_modes_by_shard,
83 const std::vector<std::string>& profiles_by_shard) {
85 Mode::ORDERED,
"default", min_nodes_by_shard, max_nodes_by_shard,
86 delivery_modes_by_shard, profiles_by_shard};
98 const std::vector<std::type_index>& subgroup_type_order,
99 const std::unique_ptr<View>& prev_view,
103 std::map<std::type_index, std::vector<std::vector<uint32_t>>> shard_sizes
108 for(
const auto& subgroup_type : subgroup_type_order) {
110 if(!std::holds_alternative<SubgroupAllocationPolicy>(
policies.at(subgroup_type))) {
113 subgroup_layouts[subgroup_type] =
117 for(uint32_t subgroup_type_id = 0; subgroup_type_id < subgroup_type_order.size();
118 ++subgroup_type_id) {
120 const std::type_index& subgroup_type = subgroup_type_order[subgroup_type_id];
121 if(!std::holds_alternative<SubgroupAllocationPolicy>(
policies.at(subgroup_type))) {
124 subgroup_layouts[subgroup_type] =
126 prev_view, curr_view, shard_sizes);
131 std::map<std::type_index, std::vector<std::vector<uint32_t>>>
133 const std::vector<std::type_index>& subgroup_type_order,
134 const std::unique_ptr<View>& prev_view,
135 const View& curr_view)
const {
137 int nodes_needed = 0;
138 std::map<std::type_index, std::vector<std::vector<uint32_t>>> shard_sizes;
139 for(uint32_t subgroup_type_id = 0; subgroup_type_id < subgroup_type_order.size(); ++subgroup_type_id) {
140 const std::type_index& subgroup_type = subgroup_type_order[subgroup_type_id];
142 if(!std::holds_alternative<SubgroupAllocationPolicy>(
policies.at(subgroup_type))) {
146 = std::get<SubgroupAllocationPolicy>(
policies.at(subgroup_type));
148 shard_sizes.emplace(subgroup_type,
149 std::vector<std::vector<uint32_t>>(subgroup_type_policy.
num_subgroups));
150 for(
int subgroup_num = 0; subgroup_num < subgroup_type_policy.
num_subgroups; ++subgroup_num) {
155 shard_sizes[subgroup_type][subgroup_num].resize(sharding_policy.
num_shards);
156 for(
int shard_num = 0; shard_num < sharding_policy.
num_shards; ++shard_num) {
162 = prev_view->subgroup_ids_by_type_id.at(subgroup_type_id)[0];
163 const SubView& previous_shard_assignment
164 = prev_view->subgroup_shard_views[previous_assignment_offset + subgroup_num]
166 int num_nonfailed_nodes = 0;
167 for(std::size_t rank = 0; rank < previous_shard_assignment.
members.size(); ++rank) {
168 if(curr_view.
rank_of(previous_shard_assignment.
members[rank]) != -1) {
169 num_nonfailed_nodes++;
172 if(num_nonfailed_nodes > min_shard_size) {
173 min_shard_size = num_nonfailed_nodes;
176 shard_sizes[subgroup_type][subgroup_num][shard_num] = min_shard_size;
177 nodes_needed += min_shard_size;
188 bool done_adding =
false;
189 while(!done_adding) {
191 bool all_at_max =
true;
192 for(
const auto& subgroup_type : subgroup_type_order) {
193 if(!std::holds_alternative<SubgroupAllocationPolicy>(
policies.at(subgroup_type))) {
197 = std::get<SubgroupAllocationPolicy>(
policies.at(subgroup_type));
198 for(
int subgroup_num = 0; subgroup_num < subgroup_type_policy.
num_subgroups; ++subgroup_num) {
203 for(
int shard_num = 0; shard_num < sharding_policy.
num_shards; ++shard_num) {
204 uint max_shard_members = sharding_policy.
even_shards 211 if(shard_sizes[subgroup_type][subgroup_num][shard_num] < max_shard_members) {
212 shard_sizes[subgroup_type][subgroup_num][shard_num]++;
215 all_at_max = all_at_max
216 && shard_sizes[subgroup_type][subgroup_num][shard_num]
217 == max_shard_members;
229 const std::type_index subgroup_type,
231 const std::map<std::type_index, std::vector<std::vector<uint32_t>>>& shard_sizes)
const {
234 for(uint32_t subgroup_num = 0; subgroup_num < subgroup_allocation.size(); ++subgroup_num) {
236 for(uint32_t shard_num = 0; shard_num < shard_sizes.at(subgroup_type)[subgroup_num].size();
238 uint32_t shard_size = shard_sizes.at(subgroup_type)[subgroup_num][shard_num];
245 = std::get<SubgroupAllocationPolicy>(
policies.at(subgroup_type));
250 Mode delivery_mode = sharding_policy.even_shards
251 ? sharding_policy.shards_mode
252 : sharding_policy.modes_by_shard[shard_num];
253 std::string profile = sharding_policy.shards_profile;
254 if (!sharding_policy.even_shards) {
255 profile = sharding_policy.profiles_by_shard[shard_num];
259 subgroup_allocation[subgroup_num].emplace_back(
260 curr_view.
make_subview(desired_nodes, delivery_mode, {}, profile));
263 return subgroup_allocation;
267 const std::type_index subgroup_type,
269 const std::unique_ptr<View>& prev_view,
271 const std::map<std::type_index, std::vector<std::vector<uint32_t>>>& shard_sizes)
const {
276 const subgroup_id_t previous_assignment_offset = prev_view->subgroup_ids_by_type_id.at(subgroup_type_id)[0];
278 for(uint32_t subgroup_num = 0; subgroup_num < next_assignment.size(); ++subgroup_num) {
280 for(uint32_t shard_num = 0; shard_num < shard_sizes.at(subgroup_type)[subgroup_num].size();
282 const SubView& previous_shard_assignment
283 = prev_view->subgroup_shard_views[previous_assignment_offset + subgroup_num]
285 std::vector<node_id_t> next_shard_members;
286 std::vector<int> next_is_sender;
287 uint32_t allocated_shard_size = shard_sizes.at(subgroup_type)[subgroup_num][shard_num];
289 for(std::size_t rank = 0; rank < previous_shard_assignment.
members.size(); ++rank) {
290 if(curr_view.
rank_of(previous_shard_assignment.
members[rank]) == -1) {
293 next_shard_members.push_back(previous_shard_assignment.
members[rank]);
294 next_is_sender.push_back(previous_shard_assignment.
is_sender[rank]);
297 while(next_shard_members.size() < allocated_shard_size) {
303 next_is_sender.push_back(
true);
305 next_assignment[subgroup_num].emplace_back(curr_view.
make_subview(next_shard_members,
306 previous_shard_assignment.
mode,
308 previous_shard_assignment.
profile));
311 return next_assignment;
315 const std::vector<std::type_index>& subgroup_type_order,
316 const std::unique_ptr<View>& prev_view,
319 for(uint32_t subgroup_type_id = 0; subgroup_type_id < subgroup_type_order.size(); ++subgroup_type_id) {
321 const std::type_index& subgroup_type = subgroup_type_order[subgroup_type_id];
323 if(!std::holds_alternative<CrossProductPolicy>(
policies.at(subgroup_type))) {
327 = std::get<CrossProductPolicy>(
policies.at(subgroup_type));
335 >= subgroup_layouts[cross_product_policy.
target_subgroup.first].size()) {
339 const std::vector<SubView>& source_subgroup_layout
342 const std::vector<SubView>& target_subgroup_layout
348 int num_source_members = 0;
349 for(
const auto& shard_view : source_subgroup_layout) {
350 num_source_members += shard_view.members.size();
352 int num_target_shards = target_subgroup_layout.size();
357 int source_member_index = 0;
358 for(std::size_t source_shard = 0; source_shard < source_subgroup_layout.size(); ++source_shard) {
359 for(
const auto& source_node : source_subgroup_layout[source_shard].members) {
360 for(
int target_shard = 0; target_shard < num_target_shards; ++target_shard) {
361 const SubView& target_shard_view = target_subgroup_layout[target_shard];
362 std::vector<node_id_t> desired_nodes(target_shard_view.
members.size() + 1);
363 desired_nodes[0] = source_node;
364 std::copy(target_shard_view.
members.begin(),
365 target_shard_view.
members.end(),
366 desired_nodes.begin() + 1);
367 std::vector<int> sender_flags(desired_nodes.size(),
false);
368 sender_flags[0] =
true;
370 assignment[source_member_index * num_target_shards + target_shard].push_back(
375 source_member_index++;
378 subgroup_layouts[subgroup_type] = std::move(assignment);
382 const std::vector<std::type_index>& subgroup_type_order,
383 const std::unique_ptr<View>& prev_view,
384 View& curr_view)
const {
388 return subgroup_allocations;
uint32_t subgroup_id_t
Type alias for the internal Subgroup IDs generated by ViewManager.
const std::map< std::type_index, std::variant< SubgroupAllocationPolicy, CrossProductPolicy > > policies
The entry for each type of subgroup is either a SubgroupAllocationPolicy if that type should use the ...
std::map< std::type_index, std::vector< std::vector< uint32_t > > > compute_standard_shard_sizes(const std::vector< std::type_index > &subgroup_type_order, const std::unique_ptr< View > &prev_view, const View &curr_view) const
Determines how many members each shard can have in the current view, based on each shard's policy (mi...
A data structure defining the parameters of the default subgroup allocation function for a single sub...
const std::vector< node_id_t > members
Node IDs of members in the current view, indexed by their SST rank.
std::vector< int > is_sender
vector selecting the senders, 0 for non-sender, non-0 for sender
ShardAllocationPolicy fixed_even_shards(int num_shards, int nodes_per_shard, const std::string &profile="default")
Returns a ShardAllocationPolicy that specifies num_shards shards with the same fixed number of nodes ...
uint32_t subgroup_type_id_t
Type of the numeric ID used to refer to subgroup types within a Group; this is currently computed as ...
int32_t next_unassigned_rank
The rank of the lowest-ranked member that is not assigned to a subgroup in this View.
ShardAllocationPolicy raw_fixed_even_shards(int num_shards, int nodes_per_shard, const std::string &profile="default")
Returns a ShardAllocationPolicy that specifies num_shards shards with the same fixed number of nodes ...
void compute_cross_product_memberships(const std::vector< std::type_index > &subgroup_type_order, const std::unique_ptr< View > &prev_view, View &curr_view, subgroup_allocation_map_t &subgroup_layouts) const
Helper function that implements the subgroup allocation algorithm for all cross-product subgroups...
constexpr char max_nodes_profile_field[]
void compute_standard_memberships(const std::vector< std::type_index > &subgroup_type_order, const std::unique_ptr< View > &prev_view, View &curr_view, subgroup_allocation_map_t &subgroup_layouts) const
Helper function that implements the subgroup allocation algorithm for all "standard" (non-cross-produ...
ShardAllocationPolicy custom_shards_policy(const std::vector< int > &min_nodes_by_shard, const std::vector< int > &max_nodes_by_shard, const std::vector< Mode > &delivery_modes_by_shard, const std::vector< std::string > &profiles_by_shard)
Returns a ShardAllocationPolicy for a subgroup that has a different number of members in each shard...
std::vector< std::vector< SubView > > subgroup_shard_layout_t
The data structure used to store a subgroups-and-shards layout for a single subgroup type (i...
subgroup_allocation_map_t operator()(const std::vector< std::type_index > &subgroup_type_order, const std::unique_ptr< View > &prev_view, View &curr_view) const
subgroup_shard_layout_t allocate_standard_subgroup_type(const std::type_index subgroup_type, View &curr_view, const std::map< std::type_index, std::vector< std::vector< uint32_t >>> &shard_sizes) const
Creates and returns an initial membership allocation for a single subgroup type, based on the input m...
const std::string profile
Settings for the subview.
std::pair< std::type_index, uint32_t > source_subgroup
The (type, index) pair identifying the "source" subgroup of the cross-product.
subgroup_allocation_map_t one_subgroup_entire_view(const std::vector< std::type_index > &subgroup_type_order, const std::unique_ptr< View > &prev_view, View &curr_view)
A simple implementation of shard_view_generator_t that creates a single, un-sharded subgroup containi...
const uint32_t getConfUInt32(const std::string &key)
std::vector< int > min_num_nodes_by_shard
If even_shards is false, this will contain an entry for each shard indicating the minimum number of m...
int num_subgroups
The number of subgroups of the same Replicated type to create.
std::pair< std::type_index, uint32_t > target_subgroup
The (type, index) pair identifying the "target" subgroup of the cross-product.
SubgroupAllocationPolicy one_subgroup_policy(const ShardAllocationPolicy &policy)
Returns a SubgroupAllocationPolicy for a replicated type that only has a single subgroup.
int rank_of(const std::tuple< ip_addr_t, uint16_t, uint16_t, uint16_t, uint16_t > &who) const
Looks up the SST rank of an IP address.
int num_shards
The number of shards; set to 1 for a non-sharded subgroup.
constexpr char num_shards_profile_field[]
An exception that indicates that a subgroup membership function was unable to finish executing becaus...
std::map< std::type_index, subgroup_shard_layout_t > subgroup_allocation_map_t
The data structure used to store the subgroups-and-shards layouts for all subgroup types in a Group (...
subgroup_allocation_map_t one_subgroup_entire_view_raw(const std::vector< std::type_index > &subgroup_type_order, const std::unique_ptr< View > &prev_view, View &curr_view)
A simple implementation of shard_view_generator_t that returns a single, un-sharded subgroup in Unord...
bool even_shards
Whether all shards should contain the same number of members.
subgroup_shard_layout_t update_standard_subgroup_type(const std::type_index subgroup_type, const subgroup_type_id_t subgroup_type_id, const std::unique_ptr< View > &prev_view, View &curr_view, const std::map< std::type_index, std::vector< std::vector< uint32_t >>> &shard_sizes) const
Creates and returns a new membership allocation for a single subgroup type, based on its previous all...
SubView make_subview(const std::vector< node_id_t > &with_members, const Mode mode=Mode::ORDERED, const std::vector< int > &is_sender={}, std::string profile="default") const
Constructs a SubView containing the provided subset of this View's members.
The subset of a View associated with a single shard, or a single subgroup if the subgroup is non-shar...
std::vector< node_id_t > members
Node IDs of members in this subgroup/shard, indexed by their order in the SST.
An alternate type of subgroup allocation policy for subgroup types whose membership will be defined a...
ShardAllocationPolicy flexible_even_shards(int num_shards, int min_nodes_per_shard, int max_nodes_per_shard, const std::string &profile="default")
Returns a ShardAllocationPolicy that specifies num_shards "flexible" or fault-tolerant shards...
Mode mode
Operation mode, raw mode does not do stability and delivery.
std::vector< ShardAllocationPolicy > shard_policy_by_subgroup
If identical_subgroups is true, contains a single entry with the allocation policy for all subgroups ...
A data structure defining the parameters of the default subgroup allocation function for a single sub...
SubgroupAllocationPolicy identical_subgroups_policy(int num_subgroups, const ShardAllocationPolicy &subgroup_policy)
Returns a SubgroupAllocationPolicy for a replicated type that needs n subgroups with identical shardi...
std::vector< int > max_num_nodes_by_shard
If even_shards is false, this will contain an entry for each shard indicating the maximum number of m...
int max_nodes_per_shard
If even_shards is true, this is the maximum number of nodes per shard.
ShardAllocationPolicy custom_shard_policy(const std::vector< Mode > &delivery_modes_by_shard, const std::vector< std::string > &profiles_by_shard)
Returns a ShardAllocationPolicy for a subgroup that has a different number of members in each shard...
constexpr char min_nodes_profile_field[]
bool identical_subgroups
Whether all subgroups of this type will have an identical shard layout.
int min_nodes_per_shard
If even_shards is true, this is the minimum number of nodes per shard.
const int32_t num_members
Number of members in this view.