Skip to content

Commit a79e581

Browse files
committed
revise isomorphismSubGScheduler
update update update update update update update update fix
1 parent 68432ad commit a79e581

File tree

4 files changed

+204
-79
lines changed

4 files changed

+204
-79
lines changed

include/osp/dag_divider/isomorphism_divider/IsomorphicSubgraphScheduler.hpp

Lines changed: 51 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,26 @@ class IsomorphicSubgraphScheduler {
3636

3737
private:
3838

39-
static constexpr bool verbose = false;
40-
39+
static constexpr bool verbose = false;
4140
size_t symmetry_ = 2;
4241
Scheduler<Constr_Graph_t> * bsp_scheduler_;
43-
42+
bool use_max_group_size_ = false;
43+
unsigned max_group_size_ = 0;
4444
bool plot_dot_graphs_ = false;
4545

4646
public:
4747

4848
IsomorphicSubgraphScheduler(Scheduler<Constr_Graph_t> & bsp_scheduler) : symmetry_(2), bsp_scheduler_(&bsp_scheduler), plot_dot_graphs_(false) {}
4949
virtual ~IsomorphicSubgraphScheduler() {}
5050

51-
void set_symmetry(size_t symmetry) {
52-
symmetry_ = symmetry;
51+
void set_symmetry(size_t symmetry) { symmetry_ = symmetry; }
52+
void set_plot_dot_graphs(bool plot) { plot_dot_graphs_ = plot; }
53+
void disable_use_max_group_size() { use_max_group_size_ = false; }
54+
void enable_use_max_group_size(const unsigned max_group_size) {
55+
use_max_group_size_ = true;
56+
max_group_size_ = max_group_size;
5357
}
5458

55-
void set_plot_dot_graphs(bool plot) {
56-
plot_dot_graphs_ = plot;
57-
}
5859

5960
std::vector<vertex_idx_t<Graph_t>> compute_partition(const BspInstance<Graph_t>& instance) {
6061
OrbitGraphProcessor<Graph_t, Constr_Graph_t> orbit_processor(symmetry_);
@@ -66,7 +67,7 @@ class IsomorphicSubgraphScheduler {
6667
writer.write_colored_graph("isomorphic_groups.dot", instance.getComputationalDag(), orbit_processor.get_final_contraction_map());
6768
}
6869

69-
const unsigned min_proc_type_count = instance.getArchitecture().getMinProcessorTypeCount();
70+
const unsigned min_proc_type_count = use_max_group_size_ ? max_group_size_ : instance.getArchitecture().getMinProcessorTypeCount();
7071
trim_subgraph_groups(isomorphic_groups, min_proc_type_count);
7172

7273
auto input = prepare_subgraph_scheduling_input(instance, isomorphic_groups);
@@ -192,28 +193,23 @@ class IsomorphicSubgraphScheduler {
192193
continue;
193194
}
194195

195-
// --- Schedule Representative and Create Pattern ---
196+
// Schedule the Representative Subgraph to get a BSP schedule pattern ---
196197
auto rep_subgraph_vertices_sorted = group.subgraphs[0];
197198
std::sort(rep_subgraph_vertices_sorted.begin(), rep_subgraph_vertices_sorted.end());
198199

199200
BspInstance<Constr_Graph_t> representative_instance;
200-
201201
create_induced_subgraph(instance.getComputationalDag(), representative_instance.getComputationalDag(), rep_subgraph_vertices_sorted);
202202

203-
// Create a map from original vertex ID to its local index in the induced subgraph
204-
std::unordered_map<vertex_idx_t<Graph_t>, vertex_idx_t<Constr_Graph_t>> vertex_to_local_idx;
205-
for (size_t j = 0; j < rep_subgraph_vertices_sorted.size(); ++j) {
206-
vertex_to_local_idx[rep_subgraph_vertices_sorted[j]] = static_cast<vertex_idx_t<Constr_Graph_t>>(j);
207-
}
208-
209203
representative_instance.setArchitecture(instance.getArchitecture());
210204
std::vector<v_memw_t<Constr_Graph_t>> dummy_mem_weights(sub_sched.node_assigned_worker_per_type[grou_idx].size(), 0);
211205
for (unsigned proc_type = 0; proc_type < sub_sched.node_assigned_worker_per_type[grou_idx].size(); ++proc_type) {
212206
dummy_mem_weights[proc_type] = static_cast<v_memw_t<Constr_Graph_t>>(instance.getArchitecture().maxMemoryBoundProcType(proc_type));
213207
}
214-
representative_instance.getArchitecture().set_processors_consequ_types(sub_sched.node_assigned_worker_per_type[grou_idx], dummy_mem_weights);
208+
const auto& procs_for_group = sub_sched.node_assigned_worker_per_type[grou_idx];
209+
representative_instance.getArchitecture().set_processors_consequ_types(procs_for_group, dummy_mem_weights);
215210
representative_instance.setNodeProcessorCompatibility(instance.getProcessorCompatibilityMatrix());
216211

212+
// Schedule the representative to get the pattern
217213
BspSchedule<Constr_Graph_t> bsp_schedule(representative_instance);
218214

219215
if constexpr (verbose) {
@@ -232,65 +228,58 @@ class IsomorphicSubgraphScheduler {
232228
std::cout << " Sync cost: " << sub_arch.synchronisationCosts() << ", Comm cost: " << sub_arch.communicationCosts() << std::endl;
233229
}
234230
bsp_scheduler_->computeSchedule(bsp_schedule);
235-
SetSchedule<Constr_Graph_t> set_schedule(bsp_schedule);
236231

237-
// --- Build Pattern Map ---
232+
// Build data structures for applying the pattern ---
233+
// Map (superstep, processor) -> relative partition ID
238234
std::map<std::pair<unsigned, unsigned>, vertex_idx_t<Graph_t>> sp_proc_to_relative_partition;
239235
vertex_idx_t<Graph_t> num_partitions_per_subgraph = 0;
240-
for (unsigned s = 0; s < set_schedule.step_processor_vertices.size(); ++s) {
241-
const auto& procs = set_schedule.step_processor_vertices[s];
242-
for (unsigned p = 0; p < procs.size(); ++p) {
243-
if (!procs[p].empty()) {
244-
sp_proc_to_relative_partition[{s, p}] = num_partitions_per_subgraph;
245-
num_partitions_per_subgraph++;
246-
}
236+
for (size_t j = 0; j < rep_subgraph_vertices_sorted.size(); ++j) {
237+
const auto sp_pair = std::make_pair(bsp_schedule.assignedSuperstep(j), bsp_schedule.assignedProcessor(j));
238+
if (sp_proc_to_relative_partition.find(sp_pair) == sp_proc_to_relative_partition.end()) {
239+
sp_proc_to_relative_partition[sp_pair] = num_partitions_per_subgraph++;
247240
}
248241
}
249242

250-
// --- Replicate Pattern for ALL Subgraphs in the Group ---
243+
// Pre-compute hashes for the representative to use for mapping
244+
MerkleHashComputer<Constr_Graph_t> rep_hasher(representative_instance.getComputationalDag());
245+
246+
// Replicate the schedule pattern for ALL subgraphs in the group ---
251247
for (size_t i = 0; i < group.subgraphs.size(); ++i) {
252248
auto current_subgraph_vertices_sorted = group.subgraphs[i];
253249
std::sort(current_subgraph_vertices_sorted.begin(), current_subgraph_vertices_sorted.end());
254250

255-
for (size_t j = 0; j < current_subgraph_vertices_sorted.size(); ++j) {
256-
vertex_idx_t<Graph_t> original_rep_vertex = rep_subgraph_vertices_sorted[j];
257-
vertex_idx_t<Constr_Graph_t> local_idx = vertex_to_local_idx.at(original_rep_vertex);
258-
vertex_idx_t<Graph_t> relative_partition = sp_proc_to_relative_partition.at({bsp_schedule.assignedSuperstep(local_idx), bsp_schedule.assignedProcessor(local_idx)});
259-
partition[current_subgraph_vertices_sorted[j]] = current_partition_idx + relative_partition;
251+
// Map from a vertex in the current subgraph to its corresponding local index (0, 1, ...) in the representative's schedule
252+
std::unordered_map<vertex_idx_t<Graph_t>, vertex_idx_t<Constr_Graph_t>> current_vertex_to_rep_local_idx;
253+
254+
if (i == 0) { // The first subgraph is the representative itself
255+
for (size_t j = 0; j < rep_subgraph_vertices_sorted.size(); ++j) {
256+
current_vertex_to_rep_local_idx[rep_subgraph_vertices_sorted[j]] = static_cast<vertex_idx_t<Constr_Graph_t>>(j);
257+
}
258+
} else { // For other subgraphs, build the isomorphic mapping
259+
Constr_Graph_t current_subgraph_graph;
260+
create_induced_subgraph(instance.getComputationalDag(), current_subgraph_graph, current_subgraph_vertices_sorted);
261+
262+
MerkleHashComputer<Constr_Graph_t> current_hasher(current_subgraph_graph);
263+
264+
for(const auto& [hash, rep_orbit_nodes] : rep_hasher.get_orbits()) {
265+
const auto& current_orbit_nodes = current_hasher.get_orbit_from_hash(hash);
266+
for(size_t k = 0; k < rep_orbit_nodes.size(); ++k) {
267+
// Map: current_subgraph_vertex -> representative_subgraph_local_idx
268+
current_vertex_to_rep_local_idx[current_subgraph_vertices_sorted[current_orbit_nodes[k]]] = static_cast<vertex_idx_t<Constr_Graph_t>>(rep_orbit_nodes[k]);
269+
}
270+
}
271+
}
272+
273+
// Apply the partition pattern
274+
for (const auto& current_vertex : current_subgraph_vertices_sorted) {
275+
const auto rep_local_idx = current_vertex_to_rep_local_idx.at(current_vertex);
276+
const auto sp_pair = std::make_pair(bsp_schedule.assignedSuperstep(rep_local_idx), bsp_schedule.assignedProcessor(rep_local_idx));
277+
partition[current_vertex] = current_partition_idx + sp_proc_to_relative_partition.at(sp_pair);
260278
}
261279
current_partition_idx += num_partitions_per_subgraph;
262280
}
263281
}
264282
}
265-
266-
267-
268-
269-
270-
271-
272-
273-
274-
275-
276-
277-
278-
279-
280-
281-
282-
283-
284-
285-
286-
287-
288-
289-
290-
291-
292-
293-
294283
};
295284

296285
}

include/osp/dag_divider/isomorphism_divider/OrbitGraphProcessor.hpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ class OrbitGraphProcessor {
7272
std::vector<VertexType> final_contraction_map_;
7373
std::vector<Group> final_groups_;
7474

75-
// --- Algorithm Parameters ---
7675
size_t symmetry_threshold_ = 2;
7776
static constexpr bool verbose = false;
7877

@@ -118,11 +117,10 @@ class OrbitGraphProcessor {
118117

119118
coarser_util::construct_coarse_dag(dag, coarse_graph_, contraction_map_);
120119

121-
Constr_Graph_t transitive_reduction;
122-
transitive_reduction_sparse(coarse_graph_, transitive_reduction);
123-
coarse_graph_ = std::move(transitive_reduction);
120+
// Constr_Graph_t transitive_reduction;
121+
// transitive_reduction_sparse(coarse_graph_, transitive_reduction);
122+
// coarse_graph_ = std::move(transitive_reduction);
124123

125-
// --- Step 2: Perform specialized coarsening on the orbit graph ---
126124
perform_coarsening(dag, coarse_graph_);
127125
}
128126

@@ -164,15 +162,15 @@ class OrbitGraphProcessor {
164162
std::vector<std::vector<VertexType>> new_subgraphs;
165163

166164
// --- Check Constraints ---
167-
// 1. Symmetry Threshold
165+
// Symmetry Threshold
168166
const bool merge_viable = is_merge_viable(original_dag, current_groups[u], current_groups[v], new_subgraphs);
169167
const bool both_below_symmetry_threshold = (current_groups[u].size() < symmetry_threshold_) && (current_groups[v].size() < symmetry_threshold_);
170168
if (!merge_viable && !both_below_symmetry_threshold) {
171169
if constexpr (verbose) { std::cout << " - Merge of " << u << " and " << v << " not viable (symmetry threshold)\n"; }
172170
continue;
173171
}
174172

175-
// 2. Acyclicity & Critical Path
173+
// Acyclicity & Critical Path
176174
Constr_Graph_t temp_coarse_graph;
177175
std::vector<VertexType> temp_contraction_map(current_coarse_graph.num_vertices());
178176
VertexType new_idx = 0;
@@ -261,28 +259,24 @@ class OrbitGraphProcessor {
261259
*/
262260
bool is_merge_viable(const Graph_t& original_dag, const Group& group_u, const Group& group_v,
263261
std::vector<std::vector<VertexType>>& out_new_subgraphs) const {
264-
// 1. Collect all vertices from both groups.
262+
265263
std::vector<VertexType> all_nodes;
266-
all_nodes.reserve(group_u.subgraphs.size() + group_v.subgraphs.size()); // Approximation
264+
all_nodes.reserve(group_u.subgraphs.size() + group_v.subgraphs.size());
267265
for (const auto& sg : group_u.subgraphs) {
268266
all_nodes.insert(all_nodes.end(), sg.begin(), sg.end());
269267
}
270268
for (const auto& sg : group_v.subgraphs) {
271269
all_nodes.insert(all_nodes.end(), sg.begin(), sg.end());
272270
}
273271

274-
// In debug builds, verify that the groups are disjoint as expected.
275-
// This lambda is evaluated only when assertions are enabled.
276272
assert([&]() {
277273
std::vector<VertexType> temp_nodes_for_check = all_nodes;
278274
std::sort(temp_nodes_for_check.begin(), temp_nodes_for_check.end());
279275
return std::unique(temp_nodes_for_check.begin(), temp_nodes_for_check.end()) == temp_nodes_for_check.end();
280276
}() && "Assumption failed: Vertices in groups being merged are not disjoint.");
281277

282-
// Sort nodes to use the create_induced_subgraph overload that provides an implicit mapping.
283278
std::sort(all_nodes.begin(), all_nodes.end());
284279

285-
// 2. Create an induced subgraph and find its weakly connected components.
286280
Constr_Graph_t induced_subgraph;
287281
create_induced_subgraph(original_dag, induced_subgraph, all_nodes);
288282

@@ -298,7 +292,6 @@ class OrbitGraphProcessor {
298292
return false;
299293
}
300294

301-
// 3. Verify that all new components are isomorphic and have the same size.
302295
if (num_components > 1) {
303296
const size_t first_sg_size = out_new_subgraphs[0].size();
304297
Constr_Graph_t rep_sg;

0 commit comments

Comments
 (0)