Skip to content

Commit a77b662

Browse files
committed
Merge branch 'sb-graph-dev' into sb-graph-tearing
2 parents a60493b + ee6f943 commit a77b662

23 files changed

Lines changed: 1476 additions & 1197 deletions

algorithms/partitioner/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ target_sources(
88
sbg-part-lib
99
PRIVATE
1010
build_sb_graph.cpp
11+
communication_cost.cpp
1112
dfs_on_sbg.cpp
1213
kernighan_lin_partitioner.cpp
1314
partition_graph.cpp

algorithms/partitioner/build_sb_graph.cpp

Lines changed: 83 additions & 91 deletions
Large diffs are not rendered by default.

algorithms/partitioner/build_sb_graph.hpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +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, SBG::LIB::SetAF& set_fact,
34-
SBG::LIB::MapAF& map_fact, SBG::LIB::PWMapAF& pw_map_fact);
33+
SBG::LIB::WeightedSBGraph build_sb_graph(const std::string& filename, SBG::LIB::PWMapAF& pw_map_fact);
3534

3635

3736
/// Ad hoc function to get pre image of an expression from its image.
@@ -47,31 +46,40 @@ SBG::LIB::Interval get_pre_image(const SBG::LIB::Interval& image_interval, const
4746
/// @param graph the graph where we are looking for connections.
4847
/// @param node set of nodes we want to know its connections.
4948
/// @return a set of nodes connected to the function parameter.
50-
SBG::LIB::Set get_adjacents(const SBG::LIB::SBG& graph, const SBG::LIB::Set& node, SBG::LIB::SetAF& set_fact, SBG::LIB::MapAF& map_fact);
49+
SBG::LIB::Set get_adjacents(const SBG::LIB::SBG& graph, const SBG::LIB::Set& node);
5150

5251

5352
/// Takes a set piece and calculate its size of the intervals. E.g [1:10] has 10 elements,
5453
/// {[1:10], [1:10]} has 100 elements.
5554
/// @param node input set we want to calculate the size.
5655
/// @return the number of elements
57-
unsigned get_node_size(const SBG::LIB::SetPiece& node, const SBG::LIB::NodeWeight& node_weight, SBG::LIB::SetAF& set_fact);
56+
unsigned get_node_size(const SBG::LIB::SetPiece& node, const SBG::LIB::NodeWeight& node_weight, const SBG::LIB::SetAF& set_fact);
5857

5958

6059
/// Takes each set piece and calculates its size, it returns the sum of them
61-
unsigned get_node_size(const SBG::LIB::Set& node, const SBG::LIB::NodeWeight& node_weight, SBG::LIB::SetAF& set_fact);
60+
unsigned get_node_size(const SBG::LIB::Set& node, const SBG::LIB::NodeWeight& node_weight, const SBG::LIB::SetAF& set_fact);
6261

6362

6463
/// Takes each set piece of the partition and calculates its size, it returns the sum of them
65-
unsigned get_partition_size(const std::vector<SBG::LIB::SetPiece>& node, const SBG::LIB::NodeWeight& node_weight, SBG::LIB::SetAF& set_fact);
64+
unsigned get_partition_size(const std::vector<SBG::LIB::SetPiece>& node, const SBG::LIB::NodeWeight& node_weight, const SBG::LIB::SetAF& set_fact);
6665

6766

68-
unsigned get_edge_set_cost(const SBG::LIB::Set& node, const SBG::LIB::EdgeCost& edge_cost);
67+
/// Takes a set of edges and compute its cost.
68+
/// @param edges - input set edges we want to calculate the size.
69+
/// @return the cost of edges (number of elements * communication cost).
70+
unsigned get_edge_set_cost(const SBG::LIB::Set& edges, const SBG::LIB::EdgeCost& edge_cost);
6971

7072

73+
/// Takes a set piece of edges and compute its cost.
74+
/// @param edges - input set piece edges we want to calculate the size.
75+
/// @return the cost of edges (number of elements * communication cost).
7176
unsigned get_edge_set_cost(const SBG::LIB::SetPiece& node, const SBG::LIB::EdgeCost& edge_cost);
7277

7378

74-
void flatten_set(SBG::LIB::Set &set, const SBG::LIB::WeightedSBGraph& graph, SBG::LIB::SetAF& set_fact);
79+
/// Flattens a set of nodes according to the graph nodes.
80+
/// @param edges - input set edges we want to calculate the size.
81+
/// @return the cost of edges (number of elements * communication cost).
82+
void flatten_set(SBG::LIB::Set &set, const SBG::LIB::WeightedSBGraph& graph);
7583

7684

7785
SBG::LIB::WeightedSBGraph create_air_conditioners_graph();
@@ -83,7 +91,7 @@ SBG::LIB::WeightedSBGraph create_air_conditioners_graph();
8391
/// @param costs hashtable with set/costs.
8492
/// @return the cost of set.
8593
template<typename T>
86-
int get_set_cost(const SBG::LIB::SetPiece& set_piece, const T& costs, SBG::LIB::SetAF& set_fact)
94+
int get_set_cost(const SBG::LIB::SetPiece& set_piece, const T& costs, const SBG::LIB::SetAF& set_fact)
8795
{
8896
int weight = 1;
8997
auto set = set_fact.createSet(set_piece);
@@ -100,5 +108,11 @@ int get_set_cost(const SBG::LIB::SetPiece& set_piece, const T& costs, SBG::LIB::
100108
size_t get_set_size(const SBG::LIB::Set& set);
101109

102110

103-
std::pair<SBG::LIB::Set, SBG::LIB::Set> cut_interval_by_dimension(SBG::LIB::Set& set_piece, const SBG::LIB::NodeWeight& node_weight, std::size_t size, SBG::LIB::SetAF& set_fact);
111+
std::pair<SBG::LIB::Set, SBG::LIB::Set> cut_interval_by_dimension(
112+
SBG::LIB::Set& set_piece,
113+
const SBG::LIB::NodeWeight& node_weight,
114+
std::size_t size,
115+
const SBG::LIB::SetAF& set_fact);
116+
117+
std::pair<SBG::LIB::SetPiece, SBG::LIB::SetPiece> cut_interval(const SBG::LIB::SetPiece& interval, int cut_value);
104118
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/**
2+
This file is part of Set--Based Graph Library.
3+
4+
SBG Library is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
SBG Library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with SBG Library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
******************************************************************************/
18+
19+
#include <unordered_map>
20+
21+
#include "communication_cost.hpp"
22+
#include "partition_graph.hpp"
23+
24+
25+
using namespace std;
26+
27+
using namespace SBG::LIB;
28+
29+
namespace sbg_partitioner {
30+
31+
namespace internal {
32+
33+
34+
static CommunicationCost* cost_matrix = nullptr;
35+
36+
37+
namespace {
38+
39+
ec_ic compute_EC_IC_from_map_1_to_map_2(
40+
const Partition& partition,
41+
const SetPiece& nodes,
42+
const PWMap& map_1,
43+
const PWMap& map_2,
44+
const SetAF& set_fact)
45+
{
46+
auto nodes_set = set_fact.createSet(nodes);
47+
auto d = map_1.preImage(nodes_set);
48+
auto im = map_2.image(d);
49+
auto partition_set = from_vector(partition, set_fact);
50+
auto ic_nodes = partition_set.intersection(im);
51+
ic_nodes = ic_nodes.difference(nodes_set);
52+
auto ec_nodes = im.difference(ic_nodes);
53+
auto ic = map_2.preImage(ic_nodes).intersection(d);
54+
auto ec = map_2.preImage(ec_nodes).intersection(d);
55+
56+
return make_pair(ec, ic);
57+
}
58+
59+
60+
}
61+
62+
63+
ec_ic compute_EC_IC(
64+
const Partition& partition,
65+
const SetPiece& nodes,
66+
const SBG::LIB::WeightedSBGraph& graph)
67+
{
68+
ec_ic cost1 = compute_EC_IC_from_map_1_to_map_2(partition, nodes, graph.map1(), graph.map2(), graph.fact());
69+
ec_ic cost2 = compute_EC_IC_from_map_1_to_map_2(partition, nodes, graph.map2(), graph.map1(), graph.fact());
70+
71+
ec_ic cost = ec_ic(cost1.first.cup(cost2.first), cost1.second.cup(cost2.second));
72+
73+
return cost;
74+
}
75+
76+
}
77+
78+
79+
CommunicationCost::CommunicationCost(const WeightedSBGraph& graph, PartitionMap partitions)
80+
: _graph(graph),
81+
_partitions(partitions)
82+
{
83+
initialize();
84+
}
85+
86+
87+
void CommunicationCost::initialize()
88+
{
89+
// compute cost by interval and partitions
90+
_cost_by_partition.reserve(_partitions.size());
91+
_ec_cost_by_interval.reserve(_partitions.size());
92+
_ic_cost_by_interval.reserve(_partitions.size());
93+
for (size_t i = 0; i < _partitions.size(); i++) {
94+
95+
_cost_by_partition.emplace_back(make_pair(_graph.fact().createSet(), _graph.fact().createSet()));
96+
_ec_cost_by_interval.emplace_back();
97+
_ic_cost_by_interval.emplace_back();
98+
for (const auto& node : _partitions.at(i)) {
99+
auto [ec, ic] = internal::compute_EC_IC(_partitions.at(i), node, _graph);
100+
101+
_cost_by_partition.back() = { _cost_by_partition.back().first.cup(ec), _cost_by_partition.back().second.cup(ic) };
102+
_ec_cost_by_interval.back().insert({node, ec});
103+
_ic_cost_by_interval.back().insert({node, ic});
104+
}
105+
}
106+
}
107+
108+
109+
void CommunicationCost::update_partitions(PartitionMap& partitions, optional<vector<size_t>> modified_partitions)
110+
{
111+
_partitions = partitions;
112+
if (modified_partitions) {
113+
Set update_nodes = _graph.fact().createSet();
114+
// now, update communication for partitions that were updated
115+
for (size_t i : *modified_partitions) {
116+
_ec_cost_by_interval[i].clear();
117+
_ic_cost_by_interval[i].clear();
118+
update_nodes = update_nodes.cup(from_vector(_partitions.at(i), _graph.fact()));
119+
_cost_by_partition[i] = make_pair(_graph.fact().createSet(), _graph.fact().createSet());
120+
for (const auto& node : _partitions.at(i)) {
121+
auto [ec, ic] = internal::compute_EC_IC(_partitions.at(i), node, _graph);
122+
123+
_cost_by_partition[i] = { _cost_by_partition.at(i).first.cup(ec), _cost_by_partition.at(i).second.cup(ic) };
124+
_ec_cost_by_interval[i].insert_or_assign(node, ec);
125+
_ic_cost_by_interval[i].insert_or_assign(node, ic);
126+
}
127+
}
128+
} else {
129+
// if modified partitions was not provided, update everything
130+
_cost_by_partition.clear();
131+
_ec_cost_by_interval.clear();
132+
_ic_cost_by_interval.clear();
133+
initialize();
134+
}
135+
}
136+
137+
138+
Set CommunicationCost::get_ec_by_partition_id(unsigned partition_id)
139+
{
140+
return _cost_by_partition[partition_id].first;
141+
}
142+
143+
144+
Set CommunicationCost::get_ec_by_interval(unsigned partition_id, const SetPiece& nodes)
145+
{
146+
if (_ec_cost_by_interval[partition_id].find(nodes) != _ec_cost_by_interval[partition_id].end()) {
147+
return _ec_cost_by_interval[partition_id].at(nodes);
148+
}
149+
150+
auto cost = internal::compute_EC_IC(_partitions.at(partition_id), nodes, _graph);
151+
_ec_cost_by_interval[partition_id].insert({nodes, cost.first});
152+
_ic_cost_by_interval[partition_id].insert({nodes, cost.second});
153+
154+
return cost.first;
155+
}
156+
157+
158+
Set CommunicationCost::get_ic_by_interval(unsigned partition_id, const SetPiece& nodes)
159+
{
160+
if (_ic_cost_by_interval[partition_id].find(nodes) != _ic_cost_by_interval[partition_id].end()) {
161+
return _ic_cost_by_interval[partition_id].at(nodes);
162+
}
163+
164+
auto cost = internal::compute_EC_IC(_partitions.at(partition_id), nodes, _graph);
165+
_ec_cost_by_interval[partition_id].insert({nodes, cost.first});
166+
_ic_cost_by_interval[partition_id].insert({nodes, cost.second});
167+
168+
return cost.second;
169+
}
170+
171+
172+
void set_communication_cost(CommunicationCost& cost_matrix)
173+
{
174+
internal::cost_matrix = new CommunicationCost(cost_matrix);
175+
}
176+
177+
CommunicationCost& get_communication_cost()
178+
{
179+
assert(internal::cost_matrix);
180+
return *internal::cost_matrix;
181+
}
182+
183+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
This file is part of Set--Based Graph Library.
3+
4+
SBG Library is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
SBG Library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with SBG Library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
******************************************************************************/
18+
19+
#pragma once
20+
21+
#include <unordered_map>
22+
#include <vector>
23+
24+
#include <sbg/sbg.hpp>
25+
26+
#include "sbg_partitioner_types.hpp"
27+
#include "weighted_sb_graph.hpp"
28+
29+
30+
namespace sbg_partitioner {
31+
32+
namespace internal {
33+
34+
using ec_ic = std::pair<SBG::LIB::Set , SBG::LIB::Set>;
35+
36+
/**
37+
* @brief This function computes external and internal communication
38+
* given a certain partition for a particular set piece.
39+
*
40+
* @param partition - partition of graph nodes.
41+
* @param nodes - set piece of the graph nodes.
42+
* @param graph - set based graph that is being partitioned. */
43+
ec_ic compute_EC_IC(
44+
const Partition& partition,
45+
const SBG::LIB::SetPiece& nodes,
46+
const SBG::LIB::WeightedSBGraph& graph);
47+
48+
}
49+
50+
class CommunicationCost {
51+
public:
52+
CommunicationCost(const SBG::LIB::WeightedSBGraph& graph, PartitionMap partitions);
53+
54+
/**
55+
* @brief After partitions are modified, external and internal cost must be updated and this function takes care of it.
56+
* If `modified_partitions` is provided, only modified partitions will be updated to speed up the process.
57+
*
58+
* @param partitions - new partition of the graph nodes.
59+
* @param modified_partitions - [optional] partitions that were updated.
60+
*/
61+
void update_partitions(PartitionMap& partitions, std::optional<std::vector<size_t>> modified_partitions = std::nullopt);
62+
63+
/**
64+
* It returns the edges that communicate nodes in partition `partition_id` with others.
65+
*
66+
* @param partition_id - id or index of a partition.
67+
*
68+
* @return External edges of the given partition.
69+
* @note These values are pre-computed when the object is created or partitions are updated.
70+
*/
71+
SBG::LIB::Set get_ec_by_partition_id(unsigned partition_id); // non-const since _cost_by_partition may be updated
72+
73+
/**
74+
* It returns the edges that communicate the set piece nodes in partition `partition_id` with other partitions.
75+
*
76+
* @param partition_id - id or index of a partition.
77+
* @param nodes - the set piece of `partition_id` that we want to compute external edges.
78+
*
79+
* @return External edges of the given set piece.
80+
* @note the member function is non-const since _ec_cost_by_interval and _ic_cost_by_interval may be updated to prevent to be recomputed.
81+
*/
82+
83+
SBG::LIB::Set get_ec_by_interval(unsigned partition_id, const SBG::LIB::SetPiece& nodes);
84+
85+
/**
86+
* It returns the edges that communicate the set piece nodes with other nodes in partition `partition_id`.
87+
*
88+
* @param partition_id - id or index of a partition.
89+
* @param nodes - the set piece of `partition_id` that we want to compute internal edges.
90+
*
91+
* @return Internal edges of the given set piece.
92+
* @note the member function is non-const since _ec_cost_by_interval and _ic_cost_by_interval may be updated to prevent to be recomputed.
93+
*/
94+
SBG::LIB::Set get_ic_by_interval(unsigned partition_id, const SBG::LIB::SetPiece& nodes);
95+
96+
private:
97+
const SBG::LIB::WeightedSBGraph& _graph; // read-only members
98+
PartitionMap _partitions;
99+
100+
std::vector<std::pair<SBG::LIB::Set, SBG::LIB::Set>> _cost_by_partition;
101+
std::vector<std::unordered_map<SBG::LIB::SetPiece, SBG::LIB::Set, SBG::LIB::SetPieceHash>> _ec_cost_by_interval;
102+
std::vector<std::unordered_map<SBG::LIB::SetPiece, SBG::LIB::Set, SBG::LIB::SetPieceHash>> _ic_cost_by_interval;
103+
104+
void initialize();
105+
106+
};
107+
108+
/**
109+
* @brief Once communication cost object is created, it can be saved by calling this function to be used in the future.
110+
*/
111+
void set_communication_cost(CommunicationCost& cost_matrix);
112+
113+
/**
114+
* @brief Global communication cost object, saved to prevent recomputing.
115+
*/
116+
CommunicationCost& get_communication_cost();
117+
118+
}

0 commit comments

Comments
 (0)