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
251 changes: 164 additions & 87 deletions algorithms/partitioner/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License
along with SBG Partitioner. If not, see <http://www.gnu.org/licenses/>.

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

#include <chrono>
#include <filesystem>
Expand All @@ -31,15 +31,65 @@
#include "kernighan_lin_partitioner.hpp"
#include "partition_graph.hpp"
#include "partition_metrics_api.hpp"
#include "sbg_partitioner_log.hpp"

using namespace std;

using namespace sbg_partitioner;


static void read_configuration_file(const string& filename, PartitionerParams& params)
{

// helper function
auto to_bool = [](string& str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
std::istringstream is(str);
bool b;
is >> std::boolalpha >> b;
return b;
};

ifstream ifs(filename);
string line;
while (std::getline(ifs, line)) {
std::istringstream is_line(line);
std::string key;
if(std::getline(is_line, key, '=')) {
std::string value;
if(std::getline(is_line, value)) {
if (key == "filename") {
params.filename = value;
} else if (key == "partitions") {
params.number_of_partitions = stoi(value);
} else if (key == "imbalance") {
params.epsilon = stof(value);
} else if (key == "multithreading") {
params.enable_multithreading = to_bool(value);
} else if (key == "initial_partition_strategy") {
params.initial_partition_strategy = InitialPartitionStrategy(stoi(value));
} else if (key == "metrics") {
params.compute_metrics = to_bool(value);
} else if (key == "partitions_directory") {
params.directory = value;
} else {
cerr << "Key " << key << " not found, it will be ignored" << endl;
}
}
}
}
}


static void usage()
{
cout << "Usage sbg-partitioner" << endl;
cout << endl;

cout << "-c, --config-filename Path to the configuration file, a file with key/values "
"that represents the partitioner configuration. If a flag and value by configuration "
"file are passed, the flag will be used."
<< endl;
cout << "-f, --filename Path to the input file, a json file that represents "
"the model we want to partitionate."
<< endl;
Expand All @@ -66,6 +116,7 @@ static void usage()
cout << "SBG Partitioner home page: https://github.com/CIFASIS/sbg-partitioner " << endl;
}


static void version()
{
cout << "SBG Partitioner 1.0.0" << endl;
Expand All @@ -82,6 +133,7 @@ void sort_before_print(PartitionMap partitions, const SBG::LIB::WeightedSBGraph&
cout << "partitions: " << partitions << endl;
}


void read_directory(const std::string& name, std::vector<std::string>& v)
{
auto path_leaf_string = [](const std::filesystem::directory_entry& entry) { return entry.path().string(); };
Expand All @@ -92,136 +144,161 @@ void read_directory(const std::string& name, std::vector<std::string>& v)
std::transform(start, end, std::back_inserter(v), path_leaf_string);
}


int main(int argc, char** argv)
{
int opt;
optional<string> filename = nullopt;
optional<string> directory = nullopt;
optional<unsigned> number_of_partitions = nullopt;
optional<string> output_file;
optional<string> output_sb_graph = nullopt;
optional<float> epsilon = nullopt;
InitialPartitionStrategy initial_partition_strategy = InitialPartitionStrategy::ALL;
bool enable_multithreading = false;
bool compute_metrics = false;

while (true) {
static struct option long_options[] = {{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
{"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
{"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
{"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
PartitionerParams params;

// look for configuration file
while (true)
{
int option_index = 0;
opt = getopt_long(argc, argv, "f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
{"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
{"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
{"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};

opt = getopt_long(argc, argv, "c:f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
if (opt == EOF) break;

switch (opt) {
case 'f':
if (optarg) {
filename = string(optarg);
}
break;
case 'c':
if (optarg) {
params.config_filename = string(optarg);
}
break;

case 'p':
if (optarg) {
number_of_partitions = atoi(optarg);
default:
continue;
}
break;
}

case 'o':
if (optarg) {
output_sb_graph = string(optarg);
}
break;
// read configuration file if exists, before reading flags
if (params.config_filename) {
read_configuration_file(*params.config_filename, params);
}

// reset it to read values again. We reed them again because flags overwrite values from configuration file
optind = 0;
while (true) {
int option_index = 0;
static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
{"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
{"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
{"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};

opt = getopt_long(argc, argv, "c:f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
if (opt == EOF) break;

case 'g':
if (optarg) {
output_file = string(optarg);
}
break;
switch (opt) {
case 'c': // already read
break;

case 'f':
if (optarg) {
params.filename = string(optarg);
}
break;

case 'e':
if (optarg) {
epsilon = atof(optarg);
}
break;
case 'p':
if (optarg) {
params.number_of_partitions = atoi(optarg);
}
break;

case 'm':
compute_metrics = true;
break;
case 'o':
if (optarg) {
params.output_sb_graph = string(optarg);
}
break;

case 'd':
if (optarg) {
directory = string(optarg);
}
break;
case 'g':
if (optarg) {
params.output_file = string(optarg);
}
break;

case 'i':
if (optarg) {
initial_partition_strategy = InitialPartitionStrategy(atoi(optarg));
}
break;
case 'e':
if (optarg) {
params.epsilon = atof(optarg);
}
break;

case 't':
enable_multithreading = true;
break;
case 'm':
params.compute_metrics = true;
break;

case 'v':
version();
exit(0);
case 'd':
if (optarg) {
params.directory = string(optarg);
}
break;

case 'h':
usage();
exit(0);
case 'i':
if (optarg) {
params.initial_partition_strategy = InitialPartitionStrategy(atoi(optarg));
}
break;

case '?':
usage();
exit(-1);
break;
case 't':
params.enable_multithreading = true;
break;

default:
cout << "opt " << opt << endl;
abort();
case 'v':
version();
exit(0);

case 'h':
usage();
exit(0);

case '?':
usage();
exit(-1);
break;

default:
abort();
}
}

if (not filename or not number_of_partitions) {
if (not params.filename or not params.number_of_partitions) {
usage();
exit(1);
}

if (not epsilon) {
epsilon = 0.0;
}

if (*epsilon < 0 or *epsilon > 1) {
if (params.epsilon < 0 or params.epsilon > 1) {
usage();
exit(1);
}

cout << "filename is " << *filename << endl;
cout << "number of partitions is " << *number_of_partitions << endl;
cout << "filename is " << *params.filename << endl;
cout << "number of partitions is " << *params.number_of_partitions << endl;

optional<string> s;
if (output_sb_graph) {
if (params.output_sb_graph) {
s = "";
}

auto start_build_graph = chrono::high_resolution_clock::now();
auto sb_graph = build_sb_graph(filename->c_str());
auto sb_graph = build_sb_graph(params.filename->c_str());
auto end_build_graph = chrono::high_resolution_clock::now();
auto time_to_build_graph = chrono::duration<double, std::milli>(end_build_graph - start_build_graph).count();

cout << "sb_graph: " << sb_graph << endl;

auto start_partitionate = chrono::high_resolution_clock::now();
auto partitions = best_initial_partition(sb_graph, *number_of_partitions, initial_partition_strategy, enable_multithreading);
kl_sbg_imbalance_partitioner(sb_graph, partitions, *epsilon, enable_multithreading);
auto partitions = best_initial_partition(sb_graph, *params.number_of_partitions, params.initial_partition_strategy, params.enable_multithreading);
kl_sbg_imbalance_partitioner(sb_graph, partitions, params.epsilon, params.enable_multithreading);
auto end_partitionate = chrono::high_resolution_clock::now();
auto time_to_partitionate = chrono::duration<double, std::milli>(end_partitionate - start_partitionate).count();

if (compute_metrics) {
if (params.compute_metrics) {
map<string, metrics::communication_metrics> metrics;

int edge_cut = metrics::edge_cut(partitions, sb_graph);
Expand All @@ -237,9 +314,9 @@ int main(int argc, char** argv)
cout << f << ": " << m << endl;
}

if (compute_metrics and directory) {
if (params.compute_metrics and params.directory) {
std::vector<std::string> dir_files;
read_directory(*directory, dir_files);
read_directory(*params.directory, dir_files);

for (const auto& f : dir_files) {
auto partition_from_file = metrics::read_partition_from_file(f, sb_graph);
Expand All @@ -263,7 +340,7 @@ int main(int argc, char** argv)
cout << "time_to_partitionate = " << time_to_partitionate << " ms" << endl;

if (sanity_check_enabled) {
sanity_check(sb_graph, partitions, *number_of_partitions);
sanity_check(sb_graph, partitions, *params.number_of_partitions);
}

if (s) {
Expand Down
10 changes: 1 addition & 9 deletions algorithms/partitioner/partition_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <sbg/interval.hpp>
#include <sbg/sbg.hpp>

#include "partitioner_params.hpp"
#include "sbg_partitioner_types.hpp"
#include "weighted_sb_graph.hpp"

Expand All @@ -34,15 +35,6 @@ namespace sbg_partitioner {
constexpr bool sanity_check_enabled = false;


enum InitialPartitionStrategy {
ALL = 0,
DFS_DISTRIBUTIVE_PREORDER = 1,
DFS_DISTRIBUTIVE_POSTORDER = 2,
DFS_GREEDY_PREORDER = 3,
DFS_GREEDY_POSTORDER =4
};


/// @brief Converts a Partition element into a Set.
/// @param partition - A list of SetPiece elements.
/// @return A SBG::LIB::Set representation of the Partition element.
Expand Down
Loading