Skip to content

Commit 46d3205

Browse files
committed
update etf scheduler
etf fix update something is broken update update update update update update removed stuff update update update etf update update update etf update
1 parent 215a85b commit 46d3205

File tree

9 files changed

+450
-3095
lines changed

9 files changed

+450
-3095
lines changed

include/osp/dag_divider/isomorphism_divider/EftSubgraphScheduler.hpp

Lines changed: 92 additions & 142 deletions
Large diffs are not rendered by default.

include/osp/dag_divider/isomorphism_divider/IsomorphicComponentDivider.hpp

Lines changed: 0 additions & 833 deletions
This file was deleted.

include/osp/dag_divider/isomorphism_divider/IsomorphicSubgraphScheduler.hpp

Lines changed: 102 additions & 94 deletions
Large diffs are not rendered by default.

include/osp/dag_divider/isomorphism_divider/WavefrontOrbitProcessor.hpp

Lines changed: 0 additions & 1712 deletions
This file was deleted.

tests/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ _add_test( heaps )
6262

6363
#_add_test( kl_mem_constr )
6464

65+
_add_test( isomorphic_subgraph_scheduler )
66+
6567
_add_test( merkle_hash_computer )
6668

6769
#_add_test( merkle_hash_divider )
@@ -70,8 +72,6 @@ _add_test( orbit_graph_processor )
7072

7173
_add_test( eft_subgraph_scheduler )
7274

73-
_add_test( wavefront_orbit_processor )
74-
7575
_add_test( wavefront_component_divider )
7676

7777
_add_test( hill_climbing )

tests/eft_subgraph_scheduler.cpp

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_SimpleChain)
7171

7272
// Job 1 should use 2 workers of type 0 and 2 of type 1
7373
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type[1].size(), 2);
74-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 1);
75-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][1], 1);
74+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 2);
75+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][1], 2);
7676

7777
// Job 2 should use 2 workers of type 1
7878
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type[2].size(), 2);
@@ -117,6 +117,18 @@ BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_ForkJoin)
117117
SubgraphSchedule schedule = scheduler.run(instance, multiplicities, required_proc_types);
118118

119119
// 4. Assertions
120+
// Manual calculation:
121+
// Ranks: 0:500, 1:300, 2:400, 3:100. Prio order: 0,2,1,3
122+
// T=0: Start 0 (4w). Finishes at 100/4=25.
123+
// T=25: ReadyQ {1,2}. Avail=4. Prio order {2,1}.
124+
// Phase 1: Job 2 (mult 1) gets 1w. Avail=3. Job 1 (mult 2) gets 2w. Avail=1.
125+
// Phase 2 (proportional on 1w): Job 2 (prio 400) gets floor(1*400/700)=0. Job 1 (prio 300) gets floor(1*300/700)=0.
126+
// Phase 2.5 (greedy on 1w): Job 2 (higher prio) gets the remaining 1 worker.
127+
// Final allocation: Job 2 gets 1+1=2 workers. Job 1 gets 2 workers.
128+
// Job 2 (work 300, 2w) duration 150. Finishes at 25 + 150 = 175.
129+
// Job 1 (work 200, 2w) duration 100. Finishes at 25 + 100 = 125.
130+
// T=125: Job 1 finishes.
131+
// T=175: Job 2 finishes. Job 3 becomes ready. Starts with 4w. Duration 100/4=25. Ends 200.
120132
BOOST_CHECK_CLOSE(schedule.makespan, 200.0, 1e-9);
121133

122134
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type.size(), 4);
@@ -127,15 +139,15 @@ BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_ForkJoin)
127139

128140
// Job 1 should use 2 workers
129141
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type[1].size(), 1);
130-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 1);
142+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 2);
131143

132144
// Job 2 should use 2 workers
133145
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type[2].size(), 1);
134146
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][0], 2);
135147

136148
// Job 3 should use 4 workers
137149
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type[3].size(), 1);
138-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][0], 1);
150+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][0], 4);
139151
}
140152

141153
BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_Deadlock)
@@ -208,28 +220,15 @@ BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_ComplexDAG)
208220
EftSubgraphScheduler<graph_t> scheduler;
209221
SubgraphSchedule schedule = scheduler.run(instance, multiplicities, required_proc_types);
210222

211-
// 4. Assertions
212-
// Manual calculation:
213-
// Ranks: 0:380, 1:240, 2:330, 3:140, 4:180, 5:60. Prio order: 0,2,1,4,3,5
214-
// T=0: Start 0 (4xT0). Finishes at 50/4 = 12.5
215-
// T=12.5: ReadyQ {1,2}. Avail {4,4}. Prio sum=570.
216-
// Job 2 (prio 330, T1, mult 1) gets floor(4*330/570)=2 workers. Dur: 150/2=75. Ends 87.5.
217-
// Job 1 (prio 240, T0, mult 2) gets floor(4*240/570)=1 chunk=2 workers. Dur: 100/2=50. Ends 62.5.
218-
// T=62.5: Job 1 finishes.
219-
// T=87.5: Job 2 finishes. ReadyQ {3,4}. Avail {4,4}. Prio order {4,3}.
220-
// Runnable check: Job 4 (mult 2, T1) can run. Temp Avail {4,2}. Job 3 (mult 4, T0&T1) cannot run.
221-
// So only Job 4 runs. It gets all available T1 workers = 4. Dur: 120/4=30. Ends 117.5.
222-
// T=117.5: Job 4 finishes. ReadyQ {3}. Avail {4,4}. Job 3 starts (4xT0, 4xT1). Dur: max(40/4, 40/4)=10. Ends 127.5.
223-
// T=127.5: Job 3 finishes. ReadyQ {5}. Avail {4,4}. Job 5 starts (4xT0). Dur: 60/4=15. Ends 142.5.
224-
BOOST_CHECK_CLOSE(schedule.makespan, 142.5, 1e-9);
223+
BOOST_CHECK_CLOSE(schedule.makespan, 105.0, 1e-9);
225224

226225
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type.size(), 6);
227226
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[0][0], 4);
228-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 1);
229-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][1], 2);
230-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][0], 1);
231-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][1], 1);
232-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[4][1], 2);
227+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 4);
228+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][1], 4);
229+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][0], 4);
230+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][1], 4);
231+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[4][1], 4);
233232
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[5][0], 4);
234233
}
235234

@@ -275,24 +274,24 @@ BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_ResourceContention)
275274
// Manual calculation:
276275
// Ranks: 0:120, 1:110, 2:60, 3:30, 4:10. Prio order: 0,1,2,3,4
277276
// T=0: Start 0 (4w). Finishes at 10/4=2.5.
278-
// T=2.5: ReadyQ {1,2,3}. Avail=4. Runnable check: {1,2} can run.
279-
// Job 1 (prio 110) and 2 (prio 60) start, both get 2 workers.
280-
// Job 2 duration 50/2=25 (ends 27.5).
281-
// Job 1 (work 100, 2w) should have duration 50, but a bug causes it to be 60, so it ends at 2.5+60=62.5.
277+
// T=2.5: ReadyQ {1,2,3}. Avail=4. Runnable check: {1,2} can run (each needs mult=2).
278+
// Guarantee phase: Job 1 gets 2w, Job 2 gets 2w. Remaining=0.
279+
// Job 1 (work 100, 2w) duration 50. Finishes at 2.5 + 50 = 52.5.
280+
// Job 2 (work 50, 2w) duration 25. Finishes at 2.5 + 25 = 27.5.
282281
// T=27.5: Job 2 finishes. 2 workers free. Job 3 starts. Duration 20/2=10 (ends 37.5).
283282
// T=37.5: Job 3 finishes.
284-
// T=62.5: Job 1 finishes. Job 4 becomes ready. Starts with 4 workers. Duration 10/4=2.5 (ends 65.0).
285-
BOOST_CHECK_CLOSE(schedule.makespan, 65.0, 1e-9);
283+
// T=52.5: Job 1 finishes. Job 4 becomes ready. Starts with 4 workers. Duration 10/4=2.5 (ends 55.0).
284+
BOOST_CHECK_CLOSE(schedule.makespan, 55.0, 1e-9);
286285

287286
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type.size(), 5);
288287
// Job 0: 4 workers
289288
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[0][0], 4);
290289
// Job 1 (high rank): gets 2 workers
291-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 1);
290+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 2);
292291
// Job 2 (mid rank): gets 2 workers
293-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][0], 1);
292+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][0], 2);
294293
// Job 3 (low rank): has to wait, then gets 2 workers
295-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][0], 1);
294+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[3][0], 2);
296295
// Job 4: gets 4 workers
297296
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[4][0], 4);
298297
}
@@ -331,20 +330,21 @@ BOOST_AUTO_TEST_CASE(EftSubgraphScheduler_ProportionalAllocation)
331330
// Manual calculation:
332331
// Ranks: 0:310, 1:300, 2:100. Prio: 0,1,2
333332
// T=0: Start 0 (10 workers). Finishes at 10/10=1.0
334-
// T=1.0: ReadyQ: {1,2}. Available: 10.
335-
// Total prio = 300+100=400.
336-
// Job 1 (prio 300) gets floor(10 * 300/400) = floor(7.5) = 7 workers.
337-
// Job 2 (prio 100) gets floor(10 * 100/400) = floor(2.5) = 2 workers.
338-
// Job 1 finishes at 1 + 300/7 = 43.857...
339-
// Job 2 finishes at 1 + 100/2 = 51.0
340-
// Makespan is 51.0
341-
BOOST_CHECK_CLOSE(schedule.makespan, 51.0, 1e-9);
333+
// T=1.0: ReadyQ: {1,2}. Available: 10. All mult=1.
334+
// Guarantee phase: Job 1 gets 1w, Job 2 gets 1w. Remaining=8.
335+
// Proportional phase (on remaining 8): Total prio = 300+100=400.
336+
// Job 1 gets floor(8 * 300/400) = 6 additional workers. Total = 1+6=7.
337+
// Job 2 gets floor(8 * 100/400) = 2 additional workers. Total = 1+2=3.
338+
// Job 1 finishes at 1 + 300/7 = 1 + 42.857... = 43.857...
339+
// Job 2 finishes at 1 + 100/3 = 1 + 33.333... = 34.333...
340+
// Makespan is 43.857...
341+
BOOST_CHECK_CLOSE(schedule.makespan, 1.0 + 300.0/7.0, 1e-9);
342342

343343
BOOST_REQUIRE_EQUAL(schedule.node_assigned_worker_per_type.size(), 3);
344344
// Job 0: 10 workers
345345
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[0][0], 10);
346346
// Job 1 (high rank): gets 7 workers (75% of 10, floored)
347347
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[1][0], 7);
348-
// Job 2 (low rank): gets 2 workers (25% of 10, floored)
349-
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][0], 2);
348+
// Job 2 (low rank): gets 3 workers
349+
BOOST_CHECK_EQUAL(schedule.node_assigned_worker_per_type[2][0], 3);
350350
}
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
Copyright 2024 Huawei Technologies Co., Ltd.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
16+
@author Toni Boehnlein, Benjamin Lozes, Pal Andras Papp, Raphael S. Steiner
17+
*/
18+
19+
#define BOOST_TEST_MODULE IsomorphicSubgraphScheduler
20+
#include <boost/test/unit_test.hpp>
21+
22+
#include "test_graphs.hpp"
23+
#include "osp/bsp/scheduler/GreedySchedulers/GreedyBspScheduler.hpp"
24+
#include "osp/dag_divider/isomorphism_divider/IsomorphicSubgraphScheduler.hpp"
25+
#include "osp/graph_implementations/adj_list_impl/computational_dag_vector_impl.hpp"
26+
27+
#include <numeric>
28+
#include <set>
29+
30+
using namespace osp;
31+
32+
using graph_t = computational_dag_vector_impl_def_t;
33+
using constr_graph_t = computational_dag_vector_impl_def_t;
34+
35+
using group_t = typename OrbitGraphProcessor<graph_t, constr_graph_t>::Group;
36+
37+
// A test class to expose private methods of IsomorphicSubgraphScheduler
38+
template <typename Graph_t, typename Constr_Graph_t>
39+
class IsomorphicSubgraphSchedulerTester : public IsomorphicSubgraphScheduler<Graph_t, Constr_Graph_t> {
40+
public:
41+
using IsomorphicSubgraphScheduler<Graph_t, Constr_Graph_t>::IsomorphicSubgraphScheduler;
42+
43+
void test_trim_subgraph_groups(std::vector<group_t>& isomorphic_groups,
44+
const unsigned min_proc_type_count) {
45+
this->trim_subgraph_groups(isomorphic_groups, min_proc_type_count);
46+
}
47+
48+
void test_schedule_isomorphic_group(const BspInstance<Graph_t> &instance,
49+
const std::vector<group_t>& isomorphic_groups,
50+
const SubgraphSchedule &sub_sched,
51+
std::vector<vertex_idx_t<Graph_t>> &partition) {
52+
this->schedule_isomorphic_group(instance, isomorphic_groups, sub_sched, partition);
53+
}
54+
};
55+
56+
BOOST_AUTO_TEST_SUITE(IsomorphicSubgraphSchedulerTestSuite)
57+
58+
BOOST_AUTO_TEST_CASE(EmptyGraphTest) {
59+
60+
BspInstance<graph_t> instance;
61+
instance.getArchitecture().setNumberOfProcessors(4);
62+
63+
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
64+
IsomorphicSubgraphScheduler<graph_t, constr_graph_t> iso_scheduler(greedy_scheduler);
65+
66+
auto partition = iso_scheduler.compute_partition(instance);
67+
BOOST_CHECK(partition.empty());
68+
}
69+
70+
BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_NoTrim) {
71+
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
72+
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
73+
74+
// A single group with 4 subgraphs, each with 1 node.
75+
std::vector<group_t> iso_groups = { group_t{ { {0}, {1}, {2}, {3} } } };
76+
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);
79+
80+
BOOST_CHECK_EQUAL(iso_groups.size(), 1);
81+
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs.size(), 4); // Still 4 subgraphs in the group
82+
}
83+
84+
BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_WithTrim) {
85+
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
86+
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
87+
88+
// 6 subgraphs, each with 1 node and work weight 10.
89+
std::vector<group_t> iso_groups = { group_t{ { {0}, {1}, {2}, {3}, {4}, {5} } } };
90+
91+
// Group size (6) is not a divisor of min_proc_type_count (8).
92+
// gcd(6, 8) = 2.
93+
// merge_size = 6 / 2 = 3.
94+
// The 6 subgraphs should be merged into 2 new subgraphs, each containing 3 old ones.
95+
tester.test_trim_subgraph_groups(iso_groups, 8);
96+
97+
BOOST_CHECK_EQUAL(iso_groups.size(), 1);
98+
BOOST_REQUIRE_EQUAL(iso_groups[0].subgraphs.size(), 2); // Group now contains 2 merged subgraphs
99+
100+
// Check that the new subgraphs are correctly merged.
101+
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs[0].size(), 3);
102+
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs[1].size(), 3);
103+
104+
const auto& final_sgs = iso_groups[0].subgraphs;
105+
std::set<unsigned> vertices_sg0(final_sgs[0].begin(), final_sgs[0].end());
106+
std::set<unsigned> vertices_sg1(final_sgs[1].begin(), final_sgs[1].end());
107+
std::set<unsigned> expected_sg0 = {0, 1, 2};
108+
std::set<unsigned> expected_sg1 = {3, 4, 5};
109+
BOOST_CHECK(vertices_sg0 == expected_sg0);
110+
BOOST_CHECK(vertices_sg1 == expected_sg1);
111+
}
112+
113+
BOOST_AUTO_TEST_CASE(TrimSubgraphGroupsTest_MultipleGroups) {
114+
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
115+
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
116+
117+
// Group 1: size 6. gcd(6, 9) = 3. merge_size = 6/3 = 2. -> 3 subgraphs of size 2.
118+
// Group 2: size 3. gcd(3, 9) = 3. merge_size = 3/3 = 1. -> no trim.
119+
// Group 3: size 5. gcd(5, 9) = 1. merge_size = 5/1 = 5. -> 1 subgraph of size 5.
120+
std::vector<group_t> iso_groups = {
121+
group_t{ { {0}, {1}, {2}, {3}, {4}, {5} } }, // Group 1
122+
group_t{ { {10}, {11}, {12} } }, // Group 2
123+
group_t{ { {20}, {21}, {22}, {23}, {24} } } // Group 3
124+
};
125+
126+
tester.test_trim_subgraph_groups(iso_groups, 9);
127+
128+
BOOST_REQUIRE_EQUAL(iso_groups.size(), 3);
129+
130+
// Check Group 1
131+
BOOST_REQUIRE_EQUAL(iso_groups[0].subgraphs.size(), 3);
132+
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs[0].size(), 2);
133+
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs[1].size(), 2);
134+
BOOST_CHECK_EQUAL(iso_groups[0].subgraphs[2].size(), 2);
135+
136+
// Check Group 2
137+
BOOST_REQUIRE_EQUAL(iso_groups[1].subgraphs.size(), 3);
138+
BOOST_CHECK_EQUAL(iso_groups[1].subgraphs[0].size(), 1);
139+
140+
// Check Group 3
141+
BOOST_REQUIRE_EQUAL(iso_groups[2].subgraphs.size(), 1);
142+
BOOST_CHECK_EQUAL(iso_groups[2].subgraphs[0].size(), 5);
143+
}
144+
145+
BOOST_AUTO_TEST_CASE(ScheduleIsomorphicGroup_HeterogeneousArch) {
146+
// --- Setup ---
147+
BspInstance<graph_t> instance;
148+
auto& dag = instance.getComputationalDag();
149+
// Two isomorphic groups:
150+
// Group 0: {0,1}, {2,3} (type 0)
151+
// Group 1: {4}, {5} (type 1)
152+
dag.add_vertex(10, 1, 1, 0); dag.add_vertex(10, 1, 1, 0); // 0, 1
153+
dag.add_vertex(10, 1, 1, 0); dag.add_vertex(10, 1, 1, 0); // 2, 3
154+
dag.add_vertex(20, 1, 1, 1); // 4
155+
dag.add_vertex(20, 1, 1, 1); // 5
156+
dag.add_edge(0, 1); dag.add_edge(2, 3);
157+
dag.add_edge(1, 4); dag.add_edge(3, 5);
158+
159+
// 2 procs of type 0, 2 procs of type 1
160+
instance.getArchitecture().setProcessorsWithTypes({0, 0, 1, 1});
161+
instance.setDiagonalCompatibilityMatrix(2);
162+
163+
std::vector<group_t> iso_groups = {
164+
group_t{ { {0, 1}, {2, 3} } },
165+
group_t{ { {4}, {5} } }
166+
};
167+
168+
// Mock SubgraphSchedule from EFT scheduler
169+
// Group 0 (2 subgraphs) gets 2 workers of type 0
170+
// Group 1 (2 subgraphs) gets 2 workers of type 1
171+
SubgraphSchedule sub_sched;
172+
sub_sched.node_assigned_worker_per_type.resize(2);
173+
sub_sched.node_assigned_worker_per_type[0] = {2, 0}; // 2xT0 for group 0
174+
sub_sched.node_assigned_worker_per_type[1] = {0, 2}; // 2xT1 for group 1
175+
176+
std::vector<vertex_idx_t<graph_t>> partition(dag.num_vertices());
177+
178+
GreedyBspScheduler<constr_graph_t> greedy_scheduler;
179+
IsomorphicSubgraphSchedulerTester<graph_t, constr_graph_t> tester(greedy_scheduler);
180+
181+
// --- Execute ---
182+
tester.test_schedule_isomorphic_group(instance, iso_groups, sub_sched, partition);
183+
184+
// --- Assert ---
185+
// Group 0 has 2 subgraphs, scheduled on 2 processors.
186+
// The internal scheduler for the representative {0,1} will likely put both on one processor.
187+
// So, {0,1} will be in one partition, and {2,3} will be in another.
188+
BOOST_CHECK_EQUAL(partition[0], partition[1]);
189+
BOOST_CHECK_EQUAL(partition[2], partition[3]);
190+
BOOST_CHECK_NE(partition[0], partition[2]);
191+
192+
// Group 1 has 2 subgraphs, scheduled on 2 processors.
193+
// Each subgraph {4} and {5} gets its own partition.
194+
BOOST_CHECK_NE(partition[4], partition[5]);
195+
196+
// Check that partitions for different groups are distinct
197+
BOOST_CHECK_NE(partition[0], partition[4]);
198+
BOOST_CHECK_NE(partition[0], partition[5]);
199+
BOOST_CHECK_NE(partition[2], partition[4]);
200+
BOOST_CHECK_NE(partition[2], partition[5]);
201+
202+
// Verify all partitions are unique as expected
203+
std::set<vertex_idx_t<graph_t>> partition_ids;
204+
for(const auto& p_id : partition) partition_ids.insert(p_id);
205+
BOOST_CHECK_EQUAL(partition_ids.size(), 4);
206+
}
207+
208+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)