Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions algorithms/partitioner/build_sb_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <cassert>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <optional>
#include <rapidjson/document.h>
Expand Down Expand Up @@ -50,7 +51,7 @@ namespace {
struct Var {
string id;
vector<pair<INT, INT>> exps;
vector<int> defs;
list<int> defs;
unsigned cost = 1;
};

Expand Down Expand Up @@ -115,7 +116,7 @@ struct Node {
vector<Var> read_var_object(const rapidjson::Value& var_array)
{
vector<Var> vars;
// vars.reserve(var_array.GetArray().Size());
vars.reserve(var_array.GetArray().Size());
for (const auto& value : var_array.GetArray()) {
assert(value.HasMember("id") and value["id"].IsString());
string id = value["id"].GetString();
Expand All @@ -134,12 +135,11 @@ vector<Var> read_var_object(const rapidjson::Value& var_array)
int exp_a = expression[0].GetInt();
int exp_b = expression[1].GetInt();

exps.push_back(make_pair(exp_a, exp_b));
exps.emplace_back(exp_a, exp_b);
}

auto def_object = value["defs"].GetArray();
vector<int> defs;
defs.reserve(def_object.Size());
list<int> defs;
for (const auto& def : def_object) {
defs.push_back(def.GetInt());
}
Expand Down Expand Up @@ -222,7 +222,7 @@ tuple<Set, NodeWeight> create_set_of_nodes(const map<int, Node>& nodes, map<int,
// own domain.
SetPiece array_of_nodes;
for (size_t i = 0; i < node.intervals.size(); i++) {
auto node_interval = node.intervals[i];
const auto& node_interval = node.intervals[i];

int interval_begin, interval_end;
if (i == 0) {
Expand Down
189 changes: 126 additions & 63 deletions algorithms/partitioner/communication_cost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with SBG Library. If not, see <http://www.gnu.org/licenses/>.

******************************************************************************/
******************************************************************************/

#include <unordered_map>

Expand All @@ -28,57 +28,41 @@ using namespace SBG::LIB;

namespace sbg_partitioner {

unordered_map<SetPiece, Set, SetPieceHash> CommunicationCost::_communication_by_set_piece = {};

namespace internal {


static CommunicationCost* cost_matrix = nullptr;
// the only real instance
CommunicationCostPtr cost_matrix = nullptr;


namespace {

ec_ic compute_EC_IC_from_map_1_to_map_2(
const Partition& partition,
const SetPiece& nodes,
const PWMap& map_1,
const PWMap& map_2,
const SetAF& set_fact)
Set set_piece_communication(const SetPiece& nodes, const WeightedSBGraph& graph)
{
auto nodes_set = set_fact.createSet(nodes);
auto d = map_1.preImage(nodes_set);
auto im = map_2.image(d);
auto partition_set = from_vector(partition, set_fact);
auto ic_nodes = partition_set.intersection(im);
ic_nodes = ic_nodes.difference(nodes_set);
auto ec_nodes = im.difference(ic_nodes);
auto ic = map_2.preImage(ic_nodes).intersection(d);
auto ec = map_2.preImage(ec_nodes).intersection(d);
// convert nodes into a set
auto node_set = graph.fact().createSet(nodes);

return make_pair(ec, ic);
}
// compute preImage of map1 and map2 to get the edges that connects `nodes`
auto edges_map1 = graph.map1().preImage(node_set);
auto edges_map2 = graph.map2().preImage(node_set);

// Now compute the disjoint union to remove loop edges
auto communication = edges_map1.cup(edges_map2).difference(edges_map1.intersection(edges_map2));

return communication;
}


ec_ic compute_EC_IC(
const Partition& partition,
const SetPiece& nodes,
const SBG::LIB::WeightedSBGraph& graph)
{
ec_ic cost1 = compute_EC_IC_from_map_1_to_map_2(partition, nodes, graph.map1(), graph.map2(), graph.fact());
ec_ic cost2 = compute_EC_IC_from_map_1_to_map_2(partition, nodes, graph.map2(), graph.map1(), graph.fact());

ec_ic cost = ec_ic(cost1.first.cup(cost2.first), cost1.second.cup(cost2.second));

return cost;
}

}


CommunicationCost::CommunicationCost(const WeightedSBGraph& graph, PartitionMap partitions)
: _graph(graph),
_partitions(partitions)
: ICommunicationCost(),
_graph(graph),
_partitions(partitions)
{
initialize();
}
Expand All @@ -91,40 +75,53 @@ void CommunicationCost::initialize()
_ec_cost_by_interval.reserve(_partitions.size());
_ic_cost_by_interval.reserve(_partitions.size());
for (size_t i = 0; i < _partitions.size(); i++) {
Set partition_i_communication = _graph.fact().createSet();
Set internal_communication_partition_i = _graph.fact().createSet();

_cost_by_partition.emplace_back(make_pair(_graph.fact().createSet(), _graph.fact().createSet()));
_ec_cost_by_interval.emplace_back();
_ic_cost_by_interval.emplace_back();
for (const auto& node : _partitions.at(i)) {
auto [ec, ic] = internal::compute_EC_IC(_partitions.at(i), node, _graph);
if (_communication_by_set_piece.find(node) == _communication_by_set_piece.end()) {
_communication_by_set_piece.insert({node, internal::set_piece_communication(node, _graph)});
}

_cost_by_partition.back() = { _cost_by_partition.back().first.cup(ec), _cost_by_partition.back().second.cup(ic) };
_ec_cost_by_interval.back().insert({node, ec});
_ic_cost_by_interval.back().insert({node, ic});
const auto& node_edges = _communication_by_set_piece.at(node);
internal_communication_partition_i = node_edges.intersection(partition_i_communication).cup(internal_communication_partition_i);
partition_i_communication = partition_i_communication.cup(node_edges);
}

auto ec_parition_i = partition_i_communication.difference(internal_communication_partition_i);
_cost_by_partition.emplace_back(make_pair(ec_parition_i, move(internal_communication_partition_i)));

_ic_cost_by_interval.emplace_back(); // save space for this, will be filled on demand
_ec_cost_by_interval.emplace_back();
}
}


void CommunicationCost::update_partitions(PartitionMap& partitions, optional<vector<size_t>> modified_partitions)
void CommunicationCost::update_partitions(PartitionMap& partitions, optional<reference_wrapper<const list<size_t>>> modified_partitions)
{
_partitions = partitions;
if (modified_partitions) {
Set update_nodes = _graph.fact().createSet();
// now, update communication for partitions that were updated
for (size_t i : *modified_partitions) {
_ec_cost_by_interval[i].clear();
_ic_cost_by_interval[i].clear();
update_nodes = update_nodes.cup(from_vector(_partitions.at(i), _graph.fact()));
_cost_by_partition[i] = make_pair(_graph.fact().createSet(), _graph.fact().createSet());
for (size_t i : modified_partitions->get()) {
Set partition_i_communication = _graph.fact().createSet();
Set internal_communication_partition_i = _graph.fact().createSet();

for (const auto& node : _partitions.at(i)) {
auto [ec, ic] = internal::compute_EC_IC(_partitions.at(i), node, _graph);
if (_communication_by_set_piece.find(node) == _communication_by_set_piece.end()) {
_communication_by_set_piece.insert({node, internal::set_piece_communication(node, _graph)});
}

_cost_by_partition[i] = { _cost_by_partition.at(i).first.cup(ec), _cost_by_partition.at(i).second.cup(ic) };
_ec_cost_by_interval[i].insert_or_assign(node, ec);
_ic_cost_by_interval[i].insert_or_assign(node, ic);
const auto& node_edges = _communication_by_set_piece.at(node);
internal_communication_partition_i = node_edges.intersection(partition_i_communication).cup(internal_communication_partition_i);
partition_i_communication = partition_i_communication.cup(node_edges);
}
}

auto ec_parition_i = partition_i_communication.difference(internal_communication_partition_i);
_cost_by_partition[i] = (make_pair(ec_parition_i, move(internal_communication_partition_i)));

_ic_cost_by_interval[i].clear();
_ec_cost_by_interval[i].clear();
}
} else {
// if modified partitions was not provided, update everything
_cost_by_partition.clear();
Expand All @@ -141,17 +138,36 @@ Set CommunicationCost::get_ec_by_partition_id(unsigned partition_id)
}


pair<Set, Set> CommunicationCost::compute_ec_ic(unsigned partition_id, const SetPiece& nodes)
{
if (_communication_by_set_piece.find(nodes) == _communication_by_set_piece.end()) {
_communication_by_set_piece.insert({nodes, internal::set_piece_communication(nodes, _graph)});
}

auto communication = _communication_by_set_piece.at(nodes);

auto ec = communication.intersection(_cost_by_partition[partition_id].first);
auto ic = communication.difference(ec);
_ec_cost_by_interval[partition_id].insert({nodes, ec});
_ic_cost_by_interval[partition_id].insert({nodes, ic});

return { ec, ic };
}


Set CommunicationCost::get_ec_by_interval(unsigned partition_id, const SetPiece& nodes)
{
if (_ec_cost_by_interval[partition_id].find(nodes) != _ec_cost_by_interval[partition_id].end()) {
return _ec_cost_by_interval[partition_id].at(nodes);
}

auto cost = internal::compute_EC_IC(_partitions.at(partition_id), nodes, _graph);
_ec_cost_by_interval[partition_id].insert({nodes, cost.first});
_ic_cost_by_interval[partition_id].insert({nodes, cost.second});
if (_communication_by_set_piece.find(nodes) == _communication_by_set_piece.end()) {
_communication_by_set_piece.insert({nodes, internal::set_piece_communication(nodes, _graph)});
}

auto [ec, _] = compute_ec_ic(partition_id, nodes);

return cost.first;
return ec;
}


Expand All @@ -161,20 +177,67 @@ Set CommunicationCost::get_ic_by_interval(unsigned partition_id, const SetPiece&
return _ic_cost_by_interval[partition_id].at(nodes);
}

auto cost = internal::compute_EC_IC(_partitions.at(partition_id), nodes, _graph);
_ec_cost_by_interval[partition_id].insert({nodes, cost.first});
_ic_cost_by_interval[partition_id].insert({nodes, cost.second});
if (_communication_by_set_piece.find(nodes) == _communication_by_set_piece.end()) {
_communication_by_set_piece.insert({nodes, internal::set_piece_communication(nodes, _graph)});
}

auto [_, ic] = compute_ec_ic(partition_id, nodes);

return ic;
}



CommunicationCostSync::CommunicationCostSync(const WeightedSBGraph& graph, PartitionMap partitions)
:ICommunicationCost(),
_comm_cost(graph, partitions)
{}


void CommunicationCostSync::update_partitions(PartitionMap& partitions, optional<reference_wrapper<const list<size_t>>> modified_partitions)
{
const lock_guard<mutex> lock(_mutex);
_comm_cost.update_partitions(partitions, modified_partitions);
}


Set CommunicationCostSync::get_ec_by_partition_id(unsigned partition_id)
{
const lock_guard<mutex> lock(_mutex);
return _comm_cost.get_ec_by_partition_id(partition_id);
}


Set CommunicationCostSync::get_ec_by_interval(unsigned partition_id, const SetPiece& nodes)
{
const lock_guard<mutex> lock(_mutex);
return _comm_cost.get_ec_by_interval(partition_id, nodes);
}


return cost.second;
Set CommunicationCostSync::get_ic_by_interval(unsigned partition_id, const SetPiece& nodes)
{
const lock_guard<mutex> lock(_mutex);
return _comm_cost.get_ic_by_interval(partition_id, nodes);
}


void set_communication_cost(CommunicationCost& cost_matrix)

CommunicationCostPtr create_communication_cost(const WeightedSBGraph& graph, PartitionMap partitions, bool multithreading_enabled)
{
if (multithreading_enabled) {
return make_unique<CommunicationCostSync>(graph, partitions);
} else {
return make_unique<CommunicationCost>(graph, partitions);
}
}

void set_communication_cost(CommunicationCostPtr&& cost_matrix)
{
internal::cost_matrix = new CommunicationCost(cost_matrix);
internal::cost_matrix = move(cost_matrix);
}

CommunicationCost& get_communication_cost()
ICommunicationCost& get_communication_cost()
{
assert(internal::cost_matrix);
return *internal::cost_matrix;
Expand Down
Loading