Skip to content

Commit 57657e5

Browse files
committed
added a configuration file
1 parent 3acb706 commit 57657e5

3 files changed

Lines changed: 216 additions & 102 deletions

File tree

algorithms/partitioner/main.cpp

Lines changed: 165 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
You should have received a copy of the GNU General Public License
1616
along with SBG Partitioner. If not, see <http://www.gnu.org/licenses/>.
1717
18-
******************************************************************************/
18+
******************************************************************************/
1919

2020
#include <chrono>
2121
#include <filesystem>
@@ -31,15 +31,65 @@
3131
#include "kernighan_lin_partitioner.hpp"
3232
#include "partition_graph.hpp"
3333
#include "partition_metrics_api.hpp"
34+
#include "sbg_partitioner_log.hpp"
3435

3536
using namespace std;
3637

3738
using namespace sbg_partitioner;
3839

40+
41+
static void read_configuration_file(const string& filename, PartitionerParams& params)
42+
{
43+
44+
// helper function
45+
auto to_bool = [](string& str) {
46+
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
47+
std::istringstream is(str);
48+
bool b;
49+
is >> std::boolalpha >> b;
50+
return b;
51+
};
52+
53+
ifstream ifs(filename);
54+
string line;
55+
while (std::getline(ifs, line)) {
56+
std::istringstream is_line(line);
57+
std::string key;
58+
if(std::getline(is_line, key, '=')) {
59+
std::string value;
60+
if(std::getline(is_line, value)) {
61+
if (key == "filename") {
62+
params.filename = value;
63+
} else if (key == "partitions") {
64+
params.number_of_partitions = stoi(value);
65+
} else if (key == "imbalance") {
66+
params.epsilon = stof(value);
67+
} else if (key == "multithreading") {
68+
params.enable_multithreading = to_bool(value);
69+
} else if (key == "initial_partition_strategy") {
70+
params.initial_partition_strategy = InitialPartitionStrategy(stoi(value));
71+
} else if (key == "metrics") {
72+
params.compute_metrics = to_bool(value);
73+
} else if (key == "partitions_directory") {
74+
params.directory = value;
75+
} else {
76+
cerr << "Key " << key << " not found, it will be ignored" << endl;
77+
}
78+
}
79+
}
80+
}
81+
}
82+
83+
3984
static void usage()
4085
{
4186
cout << "Usage sbg-partitioner" << endl;
4287
cout << endl;
88+
89+
cout << "-c, --config-filename Path to the configuration file, a file with key/values "
90+
"that represents the partitioner configuration. If a flag and value by configuration "
91+
"file are passed, the flag will be used."
92+
<< endl;
4393
cout << "-f, --filename Path to the input file, a json file that represents "
4494
"the model we want to partitionate."
4595
<< endl;
@@ -66,6 +116,7 @@ static void usage()
66116
cout << "SBG Partitioner home page: https://github.com/CIFASIS/sbg-partitioner " << endl;
67117
}
68118

119+
69120
static void version()
70121
{
71122
cout << "SBG Partitioner 1.0.0" << endl;
@@ -74,6 +125,7 @@ static void version()
74125
cout << "There is NO WARRANTY, to the extent permitted by law." << endl;
75126
}
76127

128+
77129
void sort_before_print(PartitionMap partitions, const SBG::LIB::WeightedSBGraph& sb_graph, SBG::LIB::SetAF& set_fact)
78130
{
79131
for (auto& p : partitions) {
@@ -82,6 +134,7 @@ void sort_before_print(PartitionMap partitions, const SBG::LIB::WeightedSBGraph&
82134
cout << "partitions: " << partitions << endl;
83135
}
84136

137+
85138
void read_directory(const std::string& name, std::vector<std::string>& v)
86139
{
87140
auto path_leaf_string = [](const std::filesystem::directory_entry& entry) { return entry.path().string(); };
@@ -92,119 +145,144 @@ void read_directory(const std::string& name, std::vector<std::string>& v)
92145
std::transform(start, end, std::back_inserter(v), path_leaf_string);
93146
}
94147

148+
95149
int main(int argc, char** argv)
96150
{
97151
int opt;
98-
optional<string> filename = nullopt;
99-
optional<string> directory = nullopt;
100-
optional<unsigned> number_of_partitions = nullopt;
101-
optional<string> output_file;
102-
optional<string> output_sb_graph = nullopt;
103-
optional<float> epsilon = nullopt;
104-
InitialPartitionStrategy initial_partition_strategy = InitialPartitionStrategy::ALL;
105-
bool enable_multithreading = false;
106-
bool compute_metrics = false;
107-
108-
while (true) {
109-
static struct option long_options[] = {{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
110-
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
111-
{"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
112-
{"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
113-
{"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
152+
PartitionerParams params;
114153

154+
// look for configuration file
155+
while (true)
156+
{
115157
int option_index = 0;
116-
opt = getopt_long(argc, argv, "f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
158+
static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
159+
{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
160+
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
161+
{"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
162+
{"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
163+
{"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
164+
165+
opt = getopt_long(argc, argv, "c:f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
117166
if (opt == EOF) break;
118167

119168
switch (opt) {
120-
case 'f':
121-
if (optarg) {
122-
filename = string(optarg);
123-
}
124-
break;
169+
case 'c':
170+
if (optarg) {
171+
params.config_filename = string(optarg);
172+
}
173+
break;
125174

126-
case 'p':
127-
if (optarg) {
128-
number_of_partitions = atoi(optarg);
175+
default:
176+
continue;
129177
}
130-
break;
178+
}
131179

132-
case 'o':
133-
if (optarg) {
134-
output_sb_graph = string(optarg);
135-
}
136-
break;
180+
// read configuration file if exists, before reading flags
181+
if (params.config_filename) {
182+
read_configuration_file(*params.config_filename, params);
183+
}
184+
185+
// reset it to read values again. We reed them again because flags overwrite values from configuration file
186+
optind = 0;
187+
while (true) {
188+
int option_index = 0;
189+
static struct option long_options[] = {{"config-filename", required_argument, 0, 'c'},
190+
{"filename", required_argument, 0, 'f'}, {"partitions", required_argument, 0, 'p'},
191+
{"output-file", required_argument, 0, 'g'}, {"output-graph", required_argument, 0, 'o'},
192+
{"compute-metrics", no_argument, 0, 'm'}, {"directory", required_argument, 0, 'd'},
193+
{"initial-partition-strategy", required_argument, 0, 'i'}, {"enable-multithreading", no_argument, 0, 't'},
194+
{"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}};
195+
196+
opt = getopt_long(argc, argv, "c:f:p:e:o:g:d:i:tmvh:", long_options, &option_index);
197+
if (opt == EOF) break;
137198

138-
case 'g':
139-
if (optarg) {
140-
output_file = string(optarg);
141-
}
142-
break;
199+
switch (opt) {
200+
case 'c': // already read
201+
break;
202+
203+
case 'f':
204+
if (optarg) {
205+
params.filename = string(optarg);
206+
}
207+
break;
143208

144-
case 'e':
145-
if (optarg) {
146-
epsilon = atof(optarg);
147-
}
148-
break;
209+
case 'p':
210+
if (optarg) {
211+
params.number_of_partitions = atoi(optarg);
212+
}
213+
break;
149214

150-
case 'm':
151-
compute_metrics = true;
152-
break;
215+
case 'o':
216+
if (optarg) {
217+
params.output_sb_graph = string(optarg);
218+
}
219+
break;
153220

154-
case 'd':
155-
if (optarg) {
156-
directory = string(optarg);
157-
}
158-
break;
221+
case 'g':
222+
if (optarg) {
223+
params.output_file = string(optarg);
224+
}
225+
break;
159226

160-
case 'i':
161-
if (optarg) {
162-
initial_partition_strategy = InitialPartitionStrategy(atoi(optarg));
163-
}
164-
break;
227+
case 'e':
228+
if (optarg) {
229+
params.epsilon = atof(optarg);
230+
}
231+
break;
165232

166-
case 't':
167-
enable_multithreading = true;
168-
break;
233+
case 'm':
234+
params.compute_metrics = true;
235+
break;
169236

170-
case 'v':
171-
version();
172-
exit(0);
237+
case 'd':
238+
if (optarg) {
239+
params.directory = string(optarg);
240+
}
241+
break;
173242

174-
case 'h':
175-
usage();
176-
exit(0);
243+
case 'i':
244+
if (optarg) {
245+
params.initial_partition_strategy = InitialPartitionStrategy(atoi(optarg));
246+
}
247+
break;
177248

178-
case '?':
179-
usage();
180-
exit(-1);
181-
break;
249+
case 't':
250+
params.enable_multithreading = true;
251+
break;
252+
253+
case 'v':
254+
version();
255+
exit(0);
256+
257+
case 'h':
258+
usage();
259+
exit(0);
182260

183-
default:
184-
cout << "opt " << opt << endl;
185-
abort();
261+
case '?':
262+
usage();
263+
exit(-1);
264+
break;
265+
266+
default:
267+
abort();
186268
}
187269
}
188270

189-
if (not filename or not number_of_partitions) {
271+
if (not params.filename or not params.number_of_partitions) {
190272
usage();
191273
exit(1);
192274
}
193275

194-
if (not epsilon) {
195-
epsilon = 0.0;
196-
}
197-
198-
if (*epsilon < 0 or *epsilon > 1) {
276+
if (params.epsilon < 0 or params.epsilon > 1) {
199277
usage();
200278
exit(1);
201279
}
202280

203-
cout << "filename is " << *filename << endl;
204-
cout << "number of partitions is " << *number_of_partitions << endl;
281+
cout << "filename is " << *params.filename << endl;
282+
cout << "number of partitions is " << *params.number_of_partitions << endl;
205283

206284
optional<string> s;
207-
if (output_sb_graph) {
285+
if (params.output_sb_graph) {
208286
s = "";
209287
}
210288

@@ -213,25 +291,22 @@ int main(int argc, char** argv)
213291
SBG::LIB::UnordPWMapAF pw_fact(map_fact);
214292

215293
auto start_build_graph = chrono::high_resolution_clock::now();
216-
auto sb_graph = build_sb_graph(filename->c_str(), pw_fact);
294+
auto sb_graph = build_sb_graph(params.filename->c_str(), pw_fact);
217295
auto end_build_graph = chrono::high_resolution_clock::now();
218296
auto time_to_build_graph = chrono::duration<double, std::milli>(end_build_graph - start_build_graph).count();
219297

220298
cout << "sb_graph: " << sb_graph << endl;
221299

222300
auto start_partitionate = chrono::high_resolution_clock::now();
223-
auto partitions = best_initial_partition(sb_graph, *number_of_partitions, initial_partition_strategy, enable_multithreading);
224-
kl_sbg_imbalance_partitioner(sb_graph, partitions, *epsilon, enable_multithreading);
301+
auto partitions = best_initial_partition(sb_graph, *params.number_of_partitions, params.initial_partition_strategy, params.enable_multithreading);
302+
kl_sbg_imbalance_partitioner(sb_graph, partitions, params.epsilon, params.enable_multithreading);
225303
auto end_partitionate = chrono::high_resolution_clock::now();
226304
auto time_to_partitionate = chrono::duration<double, std::milli>(end_partitionate - start_partitionate).count();
227305

228-
if (compute_metrics) {
306+
if (params.compute_metrics) {
229307
map<string, metrics::communication_metrics> metrics;
230-
231308
int edge_cut = metrics::edge_cut(partitions, sb_graph, set_fact);
232-
233309
auto [comm_volume, max_comm_volume] = metrics::communication_volume(partitions, sb_graph, set_fact, map_fact);
234-
235310
auto max_imb = metrics::maximum_imbalance(partitions, sb_graph, set_fact);
236311

237312
metrics::communication_metrics comm_metrics = metrics::communication_metrics{edge_cut, comm_volume, max_comm_volume, max_imb};
@@ -241,17 +316,14 @@ int main(int argc, char** argv)
241316
cout << f << ": " << m << endl;
242317
}
243318

244-
if (compute_metrics and directory) {
319+
if (params.compute_metrics and params.directory) {
245320
std::vector<std::string> dir_files;
246-
read_directory(*directory, dir_files);
321+
read_directory(*params.directory, dir_files);
247322

248323
for (const auto& f : dir_files) {
249324
auto partition_from_file = metrics::read_partition_from_file(f, sb_graph, set_fact);
250-
251325
int edge_cut = metrics::edge_cut(partition_from_file, sb_graph, set_fact);
252-
253326
auto [comm_volume, max_comm_volume] = metrics::communication_volume(partition_from_file, sb_graph, set_fact, map_fact);
254-
255327
auto max_imb = metrics::maximum_imbalance(partition_from_file, sb_graph, set_fact);
256328

257329
metrics::communication_metrics comm_metrics = metrics::communication_metrics{edge_cut, comm_volume, max_comm_volume, max_imb};
@@ -267,7 +339,7 @@ int main(int argc, char** argv)
267339
cout << "time_to_partitionate = " << time_to_partitionate << " ms" << endl;
268340

269341
if (sanity_check_enabled) {
270-
sanity_check(sb_graph, partitions, *number_of_partitions);
342+
sanity_check(sb_graph, partitions, *params.number_of_partitions);
271343
}
272344

273345
if (s) {

0 commit comments

Comments
 (0)