Skip to content

Commit 3fa3152

Browse files
committed
WIP, some changes to use an adjacency matrix to compute communication
1 parent abaee1a commit 3fa3152

10 files changed

Lines changed: 506 additions & 121 deletions

algorithms/partitioner/build_sb_graph.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ Set get_edge_domain(Set image_intersection_set, Set& edge_set, int& max_value)
365365
return edge_domain_set;
366366
}
367367

368-
tuple<Set, PWMap, PWMap, EdgeCost> create_graph_edges(const std::map<int, Node>& nodes, const map<int, int>& node_offsets, int& max_value)
368+
tuple<Set, PWMap, PWMap, EdgeCost> create_graph_edges(const std::map<int, Node>& nodes, const map<int, int>& node_offsets, int& max_value, bool compact_maps)
369369
{
370370
Set edge_set = SET_FACT.createSet(); // Our set of edges
371371
PWMap rhs_maps = PW_FACT.createPWMap(); // Map object of one of the sides
@@ -534,16 +534,18 @@ tuple<Set, PWMap, PWMap, EdgeCost> create_graph_edges(const std::map<int, Node>&
534534
}
535535
}
536536

537-
rhs_maps = rhs_maps.compact();
538-
lhs_maps = lhs_maps.compact();
537+
if (compact_maps) {
538+
rhs_maps = rhs_maps.compact();
539+
lhs_maps = lhs_maps.compact();
540+
}
539541

540542
return {edge_set, rhs_maps, lhs_maps, costs};
541543
}
542544

543545
/// @brief Add documentation
544546
/// @param nodes
545547
/// @return
546-
SBG::LIB::WeightedSBGraph create_sb_graph(const std::map<int, Node>& nodes)
548+
SBG::LIB::WeightedSBGraph create_sb_graph(const std::map<int, Node>& nodes, bool compact_maps)
547549
{
548550
int max_value = 0; // We track the max value, so we avoid domain collision between edges and nodes
549551
map<int, int> node_offsets;
@@ -553,7 +555,7 @@ SBG::LIB::WeightedSBGraph create_sb_graph(const std::map<int, Node>& nodes)
553555
logging::sbg_log << "node_set " << node_set << endl;
554556

555557
// Create edges and maps.
556-
auto [edge_set, left_maps, right_maps, costs] = create_graph_edges(nodes, node_offsets, max_value);
558+
auto [edge_set, left_maps, right_maps, costs] = create_graph_edges(nodes, node_offsets, max_value, compact_maps);
557559

558560
// Now, let's create a graph
559561
SBG::LIB::WeightedSBGraph graph(node_set, PW_FACT.createPWMap(), left_maps, right_maps, PW_FACT.createPWMap(),
@@ -610,7 +612,7 @@ size_t get_set_size(const Set& set)
610612
return size;
611613
}
612614

613-
SBG::LIB::WeightedSBGraph build_sb_graph(const string& filename)
615+
SBG::LIB::WeightedSBGraph build_sb_graph(const string& filename, bool compact_maps)
614616
{
615617
logging::sbg_log << "Reading " << filename << "..." << endl;
616618

@@ -624,7 +626,7 @@ SBG::LIB::WeightedSBGraph build_sb_graph(const string& filename)
624626
auto nodes = create_node_objects_from_json(document);
625627

626628
// Now, let's get our graph
627-
auto graph = create_sb_graph(nodes);
629+
auto graph = create_sb_graph(nodes, compact_maps);
628630

629631
SBG_LOG << graph;
630632

algorithms/partitioner/build_sb_graph.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace sbg_partitioner {
3030
/// a node for each access to a variable and an edge for each connection
3131
/// between variables.
3232
/// If a variable appears on the left and on the right side, an edge is created.
33-
SBG::LIB::WeightedSBGraph build_sb_graph(const std::string& filename);
33+
SBG::LIB::WeightedSBGraph build_sb_graph(const std::string& filename, bool compact_maps = true);
3434

3535

3636
/// Ad hoc function to get pre image of an expression from its image.

algorithms/partitioner/communication_cost.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "communication_cost.hpp"
2424
#include "partition_graph.hpp"
2525
#include "partition_graph_cc.hpp"
26+
#include "sbg_partitioner_log.hpp"
2627

2728

2829
using namespace std;
@@ -48,6 +49,17 @@ std::size_t SetPieceHash::operator()(const SetPiece& set_piece) const {
4849
return seed;
4950
}
5051

52+
53+
std::size_t SetHash::operator()(const SBG::LIB::Set& set) const
54+
{
55+
std::size_t seed = set.size();
56+
for (const auto& set_piece : set) {
57+
seed ^= SetPieceHash::set_piece_hash(set_piece) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
58+
}
59+
return seed;
60+
}
61+
62+
5163
unordered_map<SetPiece, Set, SetPieceHash> CommunicationCost::_communication_by_set_piece = {};
5264

5365
namespace internal {
@@ -70,7 +82,8 @@ Set set_piece_communication(const SetPiece& nodes, const WeightedSBGraph& graph)
7082
auto edges_map2 = graph.map2().preImage(node_set);
7183

7284
// Now compute the disjoint union to remove loop edges
73-
auto communication = edges_map1.cup(edges_map2).difference(edges_map1.intersection(edges_map2));
85+
auto common_edges = edges_map1.intersection(edges_map2);
86+
auto communication = edges_map1.cup(edges_map2).difference(common_edges);
7487

7588
return communication;
7689
}
@@ -272,7 +285,7 @@ CommunicationCostCC::CommunicationCostCC(const WeightedSBGraph& graph, const usi
272285

273286
void CommunicationCostCC::initialize()
274287
{
275-
_adjacency_matrix = vector<vector<uint8_t> >(_sorted_nodes.size(), vector<uint8_t>(_sorted_nodes.size(), 0));
288+
_adjacency_matrix = vector<vector<unsigned> >(_sorted_nodes.size(), vector<unsigned>(_sorted_nodes.size(), 0));
276289

277290
for (size_t i = 0; i < _sorted_nodes.size(); i++) {
278291
const auto& set_piece_pointer = _sorted_nodes.at(i);
@@ -283,6 +296,7 @@ void CommunicationCostCC::initialize()
283296
auto edges2 = get_set_piece_edges(set_piece_pointer_j.set_piece);
284297
auto shared_edges_cardinal = edges.intersection(edges2).cardinal();
285298
if (not edges.intersection(edges2).isEmpty()) {
299+
logging::sbg_log << set_piece_pointer.set_piece << ", " << set_piece_pointer_j.set_piece << ": " << shared_edges_cardinal << endl;
286300
_adjacency_matrix[set_piece_pointer.index][set_piece_pointer_j.index] = shared_edges_cardinal;
287301
_adjacency_matrix[set_piece_pointer_j.index][set_piece_pointer.index] = shared_edges_cardinal;
288302
}
@@ -292,7 +306,7 @@ void CommunicationCostCC::initialize()
292306
#ifdef SBG_PARTITIONER_LOGGING
293307
for (size_t i = 0; i < _sorted_nodes.size(); i++) {
294308
for (size_t j = 0; j < _sorted_nodes.size(); j++) {
295-
cout << int(_adjacency_matrix[_sorted_nodes.at(i).index][_sorted_nodes.at(j).index]) << " ";
309+
cout << unsigned(_adjacency_matrix[_sorted_nodes.at(i).index][_sorted_nodes.at(j).index]) << " ";
296310
}
297311
cout << endl;
298312
}

algorithms/partitioner/communication_cost.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,13 @@
3232
namespace sbg_partitioner {
3333

3434
struct SetPieceHash {
35-
static std::size_t set_piece_hash(const SBG::LIB::SetPiece& set_piece);
36-
std::size_t operator()(const SBG::LIB::SetPiece& set_piece) const;
35+
SetPieceHash() = default;
36+
static std::size_t set_piece_hash(const SBG::LIB::SetPiece& set_piece);
37+
std::size_t operator()(const SBG::LIB::SetPiece& set_piece) const;
38+
};
39+
40+
struct SetHash {
41+
std::size_t operator()(const SBG::LIB::Set& set_piece) const;
3742
};
3843

3944
class ICommunicationCost {
@@ -169,7 +174,7 @@ class CommunicationCostCC {
169174
private:
170175
void initialize();
171176

172-
using AdjacencyMatrix = std::vector<std::vector<uint8_t>>;
177+
using AdjacencyMatrix = std::vector<std::vector<unsigned>>;
173178

174179
const SBG::LIB::WeightedSBGraph& _graph; // read-only members
175180

algorithms/partitioner/main.cpp

Lines changed: 92 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
#include <getopt.h>
2424
#include <iostream>
2525
#include <optional>
26+
#include <set>
2627
#include <string>
2728

2829
#include <algorithms/cc/cc.hpp>
30+
#include <sbg/set_fact.hpp>
2931
#include <util/time_profiler.hpp>
3032

3133
#include "build_sb_graph.hpp"
@@ -151,7 +153,7 @@ void read_directory(const std::string& name, std::vector<std::string>& v)
151153
}
152154

153155

154-
tuple<unique_ptr<SBG::LIB::WeightedSBGraph>, PartitionMap, double, double> run_current_version(
156+
tuple<unique_ptr<SBG::LIB::WeightedSBGraph>, PartitionMap, double, double> partitionate_not_using_cc(
155157
const PartitionerParams& params)
156158
{
157159
auto start_build_graph = chrono::high_resolution_clock::now();
@@ -173,6 +175,93 @@ tuple<unique_ptr<SBG::LIB::WeightedSBGraph>, PartitionMap, double, double> run_c
173175
}
174176

175177

178+
tuple<unique_ptr<SBG::LIB::WeightedSBGraph>, PartitionMap, double, double> partitionate_using_cc(const PartitionerParams& params)
179+
{
180+
auto start_build_graph = chrono::high_resolution_clock::now();
181+
auto sb_graph = make_unique<SBG::LIB::WeightedSBGraph>(build_sb_graph(params.filename->c_str(), false));
182+
auto end_build_graph = chrono::high_resolution_clock::now();
183+
auto time_to_build_graph = chrono::duration<double, std::milli>(end_build_graph - start_build_graph).count();
184+
185+
cout << "sb_graph: " << *sb_graph << endl;
186+
187+
auto injective_conn = using_cc::split_nodes_into_injective_domains(*sb_graph);
188+
189+
logging::sbg_log << "injective connections " << injective_conn << endl;
190+
#if SBG_PARTITIONER_LOGGING
191+
logging::sbg_log << "remaining " << sb_graph->V().difference(injective_conn) << endl;
192+
#endif
193+
194+
auto start_partitionate = chrono::high_resolution_clock::now();
195+
using_cc::SetPointers sorted_nodes = {};
196+
unsigned index = 0;
197+
for (const auto& s : injective_conn) {
198+
sorted_nodes.push_back(using_cc::SetPointer(index++, s, 0, s.cardinal()));
199+
}
200+
201+
sbg_partitioner::CommunicationCostCC comm_cc(*sb_graph, sorted_nodes);
202+
203+
std::vector<sbg_partitioner::using_cc::SetPointers> sorted_partitions;
204+
auto new_graph = SBG::LIB::WeightedSBGraph(
205+
injective_conn,
206+
sb_graph->Vmap(),
207+
sb_graph->map1(),
208+
sb_graph->map2(),
209+
sb_graph->Emap(),
210+
sb_graph->subEmap()
211+
);
212+
213+
auto non_sorted_partitions = best_initial_partition(new_graph, *params.number_of_partitions, params.initial_partition_strategy, params.enable_multithreading);
214+
215+
// logging::sbg_log << "converting nodes into set pointers" << endl;
216+
auto start_conversion = chrono::high_resolution_clock::now();
217+
for (const auto& partition : non_sorted_partitions) {
218+
sorted_partitions.emplace_back();
219+
for (const auto& v : partition) {
220+
for (const auto& n : sorted_nodes) {
221+
if (not v.intersection(n.set_piece).isEmpty()) {
222+
size_t offset = v.begin()[0].begin() - n.set_piece.begin()[0].begin();
223+
sorted_partitions.back().emplace_back(n.index, n.set_piece, offset, v.cardinal());
224+
}
225+
}
226+
}
227+
}
228+
auto end_conversion = chrono::high_resolution_clock::now();
229+
auto conversion_time = chrono::duration<double, std::milli>(end_conversion - start_conversion).count();
230+
// auto sorted_partitions = using_cc::best_initial_partition(*sb_graph, sorted_nodes, comm_cc, *params.number_of_partitions, InitialPartitionStrategy::DFS_DISTRIBUTIVE_POSTORDER);
231+
for (const auto& sp : sorted_partitions){
232+
cout << sp << endl;
233+
}
234+
235+
for (size_t i = 0; i < sorted_nodes.size(); i++) {
236+
const auto& s1 = sorted_nodes.at(i);
237+
for (size_t j = i + 1; j < sorted_nodes.size(); j++) {
238+
const auto& s2 = sorted_nodes.at(j);
239+
240+
auto comm = comm_cc.get_communication(s1.index, s2.index);
241+
cout << s1.set_piece << " " << s1.set_piece.cardinal() << " - " << s2.set_piece << " " << s2.set_piece.cardinal() << ": " << comm << endl;
242+
if (comm > 0) {
243+
assert(s1.set_piece.cardinal() == s2.set_piece.cardinal());
244+
}
245+
}
246+
}
247+
248+
sanity_check(*sb_graph, sbg_partitioner::using_cc::rebuild_partitions(sorted_nodes, sorted_partitions), *params.number_of_partitions);
249+
250+
using_cc::kl_sbg_imbalance_partitioner(*sb_graph, sorted_nodes, sorted_partitions, comm_cc, 0.);
251+
252+
auto partitions = sbg_partitioner::using_cc::rebuild_partitions(sorted_nodes, sorted_partitions);
253+
auto end_partitionate = chrono::high_resolution_clock::now();
254+
auto time_to_partitionate = chrono::duration<double, std::milli>(end_partitionate - start_partitionate).count();
255+
time_to_partitionate -= conversion_time;
256+
257+
// if (sanity_check_enabled) {
258+
sanity_check(*sb_graph, partitions, *params.number_of_partitions);
259+
// }
260+
261+
return { move(sb_graph), partitions, time_to_build_graph, time_to_partitionate };
262+
}
263+
264+
176265
static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
177266
{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
178267
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
@@ -316,57 +405,9 @@ int main(int argc, char** argv)
316405
PartitionMap partitions;
317406
double time_to_build_graph, time_to_partitionate = 0.0;
318407
if (not params.use_connected_components) {
319-
tie(sb_graph, partitions, time_to_build_graph, time_to_partitionate) = run_current_version(params);
408+
tie(sb_graph, partitions, time_to_build_graph, time_to_partitionate) = partitionate_not_using_cc(params);
320409
} else {
321-
auto start_build_graph = chrono::high_resolution_clock::now();
322-
sb_graph = make_unique<SBG::LIB::WeightedSBGraph>(build_sb_graph(params.filename->c_str()));
323-
auto end_build_graph = chrono::high_resolution_clock::now();
324-
time_to_build_graph = chrono::duration<double, std::milli>(end_build_graph - start_build_graph).count();
325-
326-
auto cc_pw_map = SBG::LIB::connectedComponents(*sb_graph);
327-
328-
cout << "sb_graph: " << *sb_graph << endl;
329-
cout << cc_pw_map.dom() << endl;
330-
331-
using_cc::SetPointers sorted_nodes = {};
332-
unsigned index = 0;
333-
for (const auto& s : cc_pw_map.dom()) {
334-
sorted_nodes.push_back(using_cc::SetPointer(index++, s, s.cardinal()));
335-
}
336-
337-
sbg_partitioner::CommunicationCostCC comm_cc(*sb_graph, sorted_nodes);
338-
339-
auto new_graph = SBG::LIB::WeightedSBGraph(
340-
cc_pw_map.dom(),
341-
sb_graph->Vmap(),
342-
sb_graph->map1(),
343-
sb_graph->map2(),
344-
sb_graph->Emap(),
345-
sb_graph->subEmap()
346-
);
347-
348-
vector<using_cc::SetPointers> sorted_partitions;
349-
auto non_sorted_partitions = best_initial_partition(new_graph, *params.number_of_partitions, params.initial_partition_strategy, params.enable_multithreading);
350-
351-
for(const auto& partition : non_sorted_partitions) {
352-
sorted_partitions.emplace_back();
353-
for (const auto& s : partition) {
354-
for (const auto& ss : sorted_nodes) {
355-
if (not s.intersection(ss.set_piece).isEmpty()) {
356-
sorted_partitions.back().emplace_back(ss.index, ss.set_piece, s.cardinal());
357-
break;
358-
}
359-
}
360-
}
361-
}
362-
363-
partitions = sbg_partitioner::using_cc::rebuild_partitions(sorted_nodes, sorted_partitions);
364-
sanity_check(*sb_graph, partitions, *params.number_of_partitions);
365-
366-
sbg_partitioner::using_cc::kl_sbg_imbalance_partitioner(*sb_graph, sorted_nodes, sorted_partitions, comm_cc, 0.);
367-
368-
partitions = sbg_partitioner::using_cc::rebuild_partitions(sorted_nodes, sorted_partitions);
369-
sanity_check(*sb_graph, partitions, *params.number_of_partitions);
410+
tie(sb_graph, partitions, time_to_build_graph, time_to_partitionate) = partitionate_using_cc(params);
370411
}
371412

372413
if (not sb_graph) {

algorithms/partitioner/partition_graph.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,16 @@ Partition to_vector(const Set& partition_set)
155155

156156

157157
PartitionMap best_initial_partition(WeightedSBGraph& graph, unsigned number_of_partitions,
158-
const InitialPartitionStrategy strategy, bool multithreading_enabled)
158+
const InitialPartitionStrategy strategy, bool multithreading_enabled, bool create_comm_cost)
159159
{
160160
logging::sbg_log << "computing strategy number " << strategy << endl;
161161
std::vector<sbg_partitioner::PartitionMap> partition_maps = make_initial_partitions(graph, number_of_partitions, strategy);
162162

163163
auto& best_initial_partitions = partition_maps.front();
164-
CommunicationCostPtr comm_cost = create_communication_cost(graph, best_initial_partitions, multithreading_enabled);
164+
CommunicationCostPtr comm_cost;
165+
if (create_comm_cost) {
166+
comm_cost = create_communication_cost(graph, best_initial_partitions, multithreading_enabled);
167+
}
165168
if (strategy == InitialPartitionStrategy::ALL) {
166169

167170
auto best_communication_set = SET_FACT.createSet();
@@ -190,7 +193,9 @@ PartitionMap best_initial_partition(WeightedSBGraph& graph, unsigned number_of_p
190193
logging::sbg_log << "Best is " << best_initial_partitions << " with communication " << best_communication_set << endl;
191194
}
192195

193-
set_communication_cost(move(comm_cost));
196+
if (create_comm_cost) {
197+
set_communication_cost(move(comm_cost));
198+
}
194199

195200
return best_initial_partitions;
196201
}
@@ -209,21 +214,22 @@ Set get_connectivity_set(SBG::LIB::SBG& graph, const PartitionMap& partitions, s
209214
}
210215

211216

212-
void sanity_check(const WeightedSBGraph& graph, PartitionMap& partitions_set, unsigned number_of_partitions)
217+
void sanity_check(const WeightedSBGraph& graph, const PartitionMap& partitions_set, unsigned number_of_partitions)
213218
{
214-
cout << "\nsanity_check\n" << partitions_set << endl;
215219
// This is just a sanity check
216220
Set nodes_to_check = SET_FACT.createSet();
217221
for (unsigned i = 0; i < number_of_partitions; i++) {
218-
nodes_to_check = nodes_to_check.cup(from_vector(partitions_set[i]));
222+
auto s_i = from_vector(partitions_set[i]);
223+
assert(s_i.intersection(nodes_to_check).isEmpty());
224+
nodes_to_check = nodes_to_check.cup(s_i);
219225
}
220226

221227
Set diff = nodes_to_check.difference(graph.V());
222-
cout << "diff1 " << diff << endl;
228+
logging::sbg_log << "diff1 " << diff << endl;
223229
assert(get_node_size(diff, graph.get_node_weights()) == 0 and "The intial partition has more elements than the graph");
224230

225231
diff = graph.V().difference(nodes_to_check);
226-
cout << "diff2 " << diff << endl;
232+
logging::sbg_log << "diff2 " << diff << endl;
227233
assert(get_node_size(diff, graph.get_node_weights()) == 0 and "The intial partition has less elements than the graph");
228234

229235
for (unsigned i = 0; i < number_of_partitions; i++) {

0 commit comments

Comments
 (0)