Skip to content

Commit 3f0681d

Browse files
committed
revision trim reverse
1 parent 6a82b32 commit 3f0681d

File tree

3 files changed

+31
-154
lines changed

3 files changed

+31
-154
lines changed

include/osp/dag_divider/isomorphism_divider/IsomorphicSubgraphScheduler.hpp

Lines changed: 24 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ class IsomorphicSubgraphScheduler {
7171

7272
std::vector<vertex_idx_t<Graph_t>> compute_partition(const BspInstance<Graph_t>& instance) {
7373
OrbitGraphProcessor<Graph_t, Constr_Graph_t> orbit_processor(symmetry_);
74-
orbit_processor.set_work_threshold(work_threshold_);
75-
orbit_processor.setMergeDifferentNodeTypes(merge_different_node_types);
7674

7775
std::unique_ptr<HashComputer<vertex_idx_t<Graph_t>>> local_hasher;
7876
if (!hash_computer_) {
@@ -84,26 +82,37 @@ class IsomorphicSubgraphScheduler {
8482

8583
auto isomorphic_groups = orbit_processor.get_final_groups();
8684

87-
trim_subgraph_groups(isomorphic_groups, instance); // Apply trimming based on dynamic min_proc_type_count
85+
if (plot_dot_graphs_) {
86+
DotFileWriter writer;
87+
writer.write_colored_graph("isomorphic_groups.dot", instance.getComputationalDag(), orbit_processor.get_final_contraction_map());
88+
writer.write_colored_graph("orbits_colored.dot", instance.getComputationalDag(), orbit_processor.get_contraction_map());
89+
}
90+
91+
const unsigned min_proc_type_count = use_max_group_size_ ? max_group_size_ : instance.getArchitecture().getMinProcessorTypeCount();
92+
trim_subgraph_groups(isomorphic_groups, min_proc_type_count);
8893

8994
auto input = prepare_subgraph_scheduling_input(instance, isomorphic_groups);
9095

96+
if (plot_dot_graphs_) {
97+
DotFileWriter writer;
98+
writer.write_graph("iso_groups_contracted.dot", input.instance.getComputationalDag());
99+
}
100+
91101
EftSubgraphScheduler<Constr_Graph_t> etf_scheduler;
92102
SubgraphSchedule subgraph_schedule = etf_scheduler.run(input.instance, input.multiplicities, input.required_proc_types);
93103

94104
std::vector<vertex_idx_t<Graph_t>> partition(instance.numberOfVertices(), 0);
105+
95106
schedule_isomorphic_group(instance, isomorphic_groups, subgraph_schedule, partition);
96107

97108
if (plot_dot_graphs_) {
98109
DotFileWriter writer;
99-
writer.write_colored_graph("isomorphic_groups.dot", instance.getComputationalDag(), orbit_processor.get_final_contraction_map());
100-
writer.write_colored_graph("orbits_colored.dot", instance.getComputationalDag(), orbit_processor.get_contraction_map());
101-
writer.write_graph("iso_groups_contracted.dot", input.instance.getComputationalDag());
102110
writer.write_colored_graph("graph_partition.dot", instance.getComputationalDag(), partition);
103111
Constr_Graph_t corase_graph;
104112
coarser_util::construct_coarse_dag(instance.getComputationalDag(), corase_graph, partition);
105113
writer.write_graph("block_graph.dot", corase_graph);
106114
}
115+
107116
return partition;
108117
}
109118

@@ -117,125 +126,35 @@ class IsomorphicSubgraphScheduler {
117126
};
118127

119128
void trim_subgraph_groups(std::vector<typename OrbitGraphProcessor<Graph_t, Constr_Graph_t>::Group>& isomorphic_groups,
120-
const BspInstance<Graph_t>& instance) {
121-
if constexpr (verbose) {
122-
std::cout << "\n--- Trimming Isomorphic Subgraph Groups ---" << std::endl;
123-
}
124-
size_t group_idx_debug = 0;
125-
for (auto& group : isomorphic_groups) {
126-
const unsigned group_size = static_cast<unsigned>(group.size());
127-
if (group_size <= 1)
128-
continue;
129-
130-
unsigned effective_min_proc_type_count = 0;
129+
const unsigned min_proc_type_count) {
130+
if (min_proc_type_count <= 1) return;
131131

132-
if (use_max_group_size_) {
133-
if constexpr (verbose) {
134-
std::cout << "Group " << group_idx_debug << " (size " << group_size << "): Using fixed max_group_size_ = " << max_group_size_ << " for trimming." << std::endl;
135-
}
136-
effective_min_proc_type_count = max_group_size_;
137-
} else {
138-
// Determine if the group consists of a single node type
139-
bool is_single_type_group = true;
140-
v_type_t<Graph_t> common_node_type = 0;
141-
142-
if constexpr (has_typed_vertices_v<Graph_t>) {
143-
if (!group.subgraphs.empty() && !group.subgraphs[0].empty()) {
144-
common_node_type = instance.getComputationalDag().vertex_type(group.subgraphs[0][0]);
145-
const auto& rep_subgraph = group.subgraphs[0];
146-
for (const auto& vertex : rep_subgraph) {
147-
if (instance.getComputationalDag().vertex_type(vertex) != common_node_type) {
148-
is_single_type_group = false;
149-
break;
150-
}
151-
}
152-
} else {
153-
is_single_type_group = false;
154-
}
155-
} else {
156-
is_single_type_group = false;
157-
}
158-
159-
if (is_single_type_group) {
160-
// Dynamically determine min_proc_type_count based on compatible processors for this type
161-
unsigned min_compatible_processors = std::numeric_limits<unsigned>::max();
162-
const auto& proc_type_counts = instance.getArchitecture().getProcessorTypeCount();
163-
164-
bool found_compatible_processor = false;
165-
for (unsigned proc_type_idx = 0; proc_type_idx < proc_type_counts.size(); ++proc_type_idx) {
166-
if (instance.isCompatibleType(common_node_type, proc_type_idx)) {
167-
min_compatible_processors = std::min(min_compatible_processors, proc_type_counts[proc_type_idx]);
168-
found_compatible_processor = true;
169-
}
170-
}
171-
if (found_compatible_processor) {
172-
if constexpr (verbose) {
173-
std::cout << "Group " << group_idx_debug << " (size " << group_size << "): Single node type (" << common_node_type
174-
<< "). Min compatible processors: " << min_compatible_processors << "." << std::endl;
175-
}
176-
effective_min_proc_type_count = min_compatible_processors;
177-
} else {
178-
if constexpr (verbose) {
179-
std::cout << "Group " << group_idx_debug << " (size " << group_size << "): Single node type (" << common_node_type
180-
<< ") but no compatible processors found. Disabling trimming." << std::endl;
181-
}
182-
// If no compatible processors found for this type, effectively disable trimming for this group.
183-
effective_min_proc_type_count = 1;
184-
}
185-
} else {
186-
// Fallback to a default min_proc_type_count if not a single-type group or no typed vertices.
187-
effective_min_proc_type_count = instance.getArchitecture().getMinProcessorTypeCount();
188-
if constexpr (verbose) {
189-
std::cout << "Group " << group_idx_debug << " (size " << group_size << "): Multi-type or untyped group. Using default min_proc_type_count: " << effective_min_proc_type_count << "." << std::endl;
190-
}
191-
}
192-
}
193-
194-
// Ensure effective_min_proc_type_count is at least 1 for valid GCD calculation.
195-
if (effective_min_proc_type_count == 0) {
196-
effective_min_proc_type_count = 1;
197-
}
198-
199-
// If effective_min_proc_type_count is 1, no trimming is needed as gcd(X, 1) = 1.
200-
if (effective_min_proc_type_count <= 1) {
132+
for (auto& group : isomorphic_groups) {
133+
const unsigned group_size = static_cast<unsigned>(group.subgraphs.size());
134+
if (group_size == 0)
201135
continue;
202-
}
203-
204-
const unsigned gcd = std::gcd(group_size, effective_min_proc_type_count);
136+
const unsigned gcd = std::gcd(group_size, min_proc_type_count);
205137

206138
if (gcd < group_size) {
207-
if constexpr (verbose) {
208-
std::cout << " -> Trimming group " << group_idx_debug << ". GCD(" << group_size << ", " << effective_min_proc_type_count
209-
<< ") = " << gcd << ". Merging " << group_size / gcd << " subgraphs at a time." << std::endl;
210-
}
211-
212139
const unsigned merge_size = group_size / gcd;
213140
std::vector<std::vector<vertex_idx_t<Graph_t>>> new_subgraphs;
214141
new_subgraphs.reserve(gcd);
215142

216143
size_t original_sg_cursor = 0;
217144

218145
for (unsigned j = 0; j < gcd; ++j) {
219-
std::vector<vertex_idx_t<Graph_t>> merged_sg_vertices;
220-
// Estimate capacity for efficiency. Assuming subgraphs have similar sizes.
221-
if (!group.subgraphs.empty()) {
222-
merged_sg_vertices.reserve(group.subgraphs[0].size() * merge_size);
223-
}
146+
std::vector<vertex_idx_t<Graph_t>> merged_sg_vertices = group.subgraphs[original_sg_cursor];
147+
original_sg_cursor++;
224148

225-
for (unsigned k = 0; k < merge_size; ++k) {
149+
for (unsigned k = 1; k < merge_size; ++k) {
226150
const auto& sg_to_merge_vertices = group.subgraphs[original_sg_cursor];
227151
original_sg_cursor++;
228152
merged_sg_vertices.insert(merged_sg_vertices.end(), sg_to_merge_vertices.begin(), sg_to_merge_vertices.end());
229153
}
230154
new_subgraphs.push_back(std::move(merged_sg_vertices));
231155
}
232156
group.subgraphs = std::move(new_subgraphs);
233-
} else {
234-
if constexpr (verbose) {
235-
std::cout << " -> No trim needed for group " << group_idx_debug << "." << std::endl;
236-
}
237157
}
238-
group_idx_debug++;
239158
}
240159
}
241160

include/osp/dag_divider/isomorphism_divider/OrbitGraphProcessor.hpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -511,14 +511,6 @@ class OrbitGraphProcessor {
511511

512512
Constr_Graph_t induced_subgraph;
513513

514-
// create_induced_subgraph(original_dag, induced_subgraph, all_nodes);
515-
// std::vector<VertexType> components; // local -> component_id
516-
// size_t num_components = compute_weakly_connected_components(induced_subgraph, components);
517-
// out_new_subgraphs.assign(num_components, std::vector<VertexType>());
518-
// for (VertexType i = 0; i < induced_subgraph.num_vertices(); ++i) {
519-
// out_new_subgraphs[components[i]].push_back(all_nodes[i]);
520-
// }
521-
522514
auto map = create_induced_subgraph_map(original_dag, induced_subgraph, all_nodes);
523515
std::vector<VertexType> components; // local -> component_id
524516
size_t num_components = compute_weakly_connected_components(induced_subgraph, components);

tests/isomorphic_subgraph_scheduler.cpp

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ class IsomorphicSubgraphSchedulerTester : public IsomorphicSubgraphScheduler<Gra
4141
using IsomorphicSubgraphScheduler<Graph_t, Constr_Graph_t>::IsomorphicSubgraphScheduler;
4242

4343
void test_trim_subgraph_groups(std::vector<group_t>& isomorphic_groups,
44-
const BspInstance<Graph_t>& instance) {
45-
this->trim_subgraph_groups(isomorphic_groups, instance);
44+
const unsigned min_proc_type_count) {
45+
this->trim_subgraph_groups(isomorphic_groups, min_proc_type_count);
4646
}
4747

4848
void test_schedule_isomorphic_group(const BspInstance<Graph_t> &instance,
@@ -71,20 +71,11 @@ BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_NoTrim) {
7171
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
7272
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
7373

74-
BspInstance<graph_t> instance;
75-
auto& dag = instance.getComputationalDag();
76-
dag.add_vertex(1, 1, 1, 0); // 0
77-
dag.add_vertex(1, 1, 1, 0); // 1
78-
dag.add_vertex(1, 1, 1, 0); // 2
79-
dag.add_vertex(1, 1, 1, 0); // 3
80-
instance.getArchitecture().setProcessorsWithTypes({0,0,0,0,0,0,0,0}); // 8 processors of type 0
81-
instance.setDiagonalCompatibilityMatrix(1);
82-
8374
// A single group with 4 subgraphs, each with 1 node.
8475
std::vector<group_t> iso_groups = { group_t{ { {0}, {1}, {2}, {3} } } };
8576

86-
// Group size (4) is a divisor of processor count for type 0 (8), so no trim.
87-
tester.test_trim_subgraph_groups(iso_groups, instance);
77+
// Group size (4) is a divisor of min_proc_type_count (8), so no trim.
78+
tester.test_trim_subgraph_groups(iso_groups, 8);
8879

8980
BOOST_CHECK_EQUAL(iso_groups.size(), 1);
9081
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs.size(), 4); // Still 4 subgraphs in the group
@@ -94,25 +85,14 @@ BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_WithTrim) {
9485
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
9586
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
9687

97-
BspInstance<graph_t> instance;
98-
auto& dag = instance.getComputationalDag();
99-
dag.add_vertex(10, 1, 1, 0); // 0
100-
dag.add_vertex(10, 1, 1, 0); // 1
101-
dag.add_vertex(10, 1, 1, 0); // 2
102-
dag.add_vertex(10, 1, 1, 0); // 3
103-
dag.add_vertex(10, 1, 1, 0); // 4
104-
dag.add_vertex(10, 1, 1, 0); // 5
105-
instance.getArchitecture().setProcessorsWithTypes({0,0,0,0,0,0,0,0}); // 8 processors of type 0
106-
instance.setDiagonalCompatibilityMatrix(1);
107-
10888
// 6 subgraphs, each with 1 node and work weight 10.
10989
std::vector<group_t> iso_groups = { group_t{ { {0}, {1}, {2}, {3}, {4}, {5} } } };
11090

111-
// Group size (6) is not a divisor of processor count for type 0 (8).
91+
// Group size (6) is not a divisor of min_proc_type_count (8).
11292
// gcd(6, 8) = 2.
11393
// merge_size = 6 / 2 = 3.
11494
// The 6 subgraphs should be merged into 2 new subgraphs, each containing 3 old ones.
115-
tester.test_trim_subgraph_groups(iso_groups, instance);
95+
tester.test_trim_subgraph_groups(iso_groups, 8);
11696

11797
BOOST_CHECK_EQUAL(iso_groups.size(), 1);
11898
BOOST_REQUIRE_EQUAL(iso_groups[0].subgraphs.size(), 2); // Group now contains 2 merged subgraphs
@@ -134,20 +114,6 @@ BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_MultipleGroups) {
134114
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
135115
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
136116

137-
BspInstance<graph_t> instance;
138-
auto& dag = instance.getComputationalDag();
139-
for (int i = 0; i < 6; ++i) dag.add_vertex(1,1,1,0); // 0-5
140-
for (int i = 0; i < 3; ++i) dag.add_vertex(1,1,1,0); // 6-8, but we will use 10-12 in test
141-
for (int i = 0; i < 2; ++i) dag.add_vertex(1,1,1,0); // 9-10
142-
for (int i = 0; i < 2; ++i) dag.add_vertex(1,1,1,0); // 11-12
143-
for (int i = 0; i < 8; ++i) dag.add_vertex(1,1,1,0); // 13-20
144-
for (int i = 0; i < 5; ++i) dag.add_vertex(1,1,1,0); // 21-25
145-
// Make sure all vertices used in iso_groups exist.
146-
// All are type 0.
147-
148-
instance.getArchitecture().setProcessorsWithTypes({0,0,0,0,0,0,0,0,0}); // 9 processors of type 0
149-
instance.setDiagonalCompatibilityMatrix(1);
150-
151117
// Group 1: size 6. gcd(6, 9) = 3. merge_size = 6/3 = 2. -> 3 subgraphs of size 2.
152118
// Group 2: size 3. gcd(3, 9) = 3. merge_size = 3/3 = 1. -> no trim.
153119
// Group 3: size 5. gcd(5, 9) = 1. merge_size = 5/1 = 5. -> 1 subgraph of size 5.
@@ -157,7 +123,7 @@ BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_MultipleGroups) {
157123
group_t{ { {20}, {21}, {22}, {23}, {24} } } // Group 3
158124
};
159125

160-
tester.test_trim_subgraph_groups(iso_groups, instance);
126+
tester.test_trim_subgraph_groups(iso_groups, 9);
161127

162128
BOOST_REQUIRE_EQUAL(iso_groups.size(), 3);
163129

0 commit comments

Comments
 (0)