Skip to content

Commit 3c73e80

Browse files
added a configuration file (#103)
1 parent 0b9a099 commit 3c73e80

3 files changed

Lines changed: 215 additions & 96 deletions

File tree

algorithms/partitioner/main.cpp

Lines changed: 164 additions & 87 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;
@@ -82,6 +133,7 @@ void sort_before_print(PartitionMap partitions, const SBG::LIB::WeightedSBGraph&
82133
cout << "partitions: " << partitions << endl;
83134
}
84135

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

147+
95148
int main(int argc, char** argv)
96149
{
97150
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'}};
151+
PartitionerParams params;
114152

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

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

126-
case 'p':
127-
if (optarg) {
128-
number_of_partitions = atoi(optarg);
174+
default:
175+
continue;
129176
}
130-
break;
177+
}
131178

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

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

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

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

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

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

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

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

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

178-
case '?':
179-
usage();
180-
exit(-1);
181-
break;
248+
case 't':
249+
params.enable_multithreading = true;
250+
break;
182251

183-
default:
184-
cout << "opt " << opt << endl;
185-
abort();
252+
case 'v':
253+
version();
254+
exit(0);
255+
256+
case 'h':
257+
usage();
258+
exit(0);
259+
260+
case '?':
261+
usage();
262+
exit(-1);
263+
break;
264+
265+
default:
266+
abort();
186267
}
187268
}
188269

189-
if (not filename or not number_of_partitions) {
270+
if (not params.filename or not params.number_of_partitions) {
190271
usage();
191272
exit(1);
192273
}
193274

194-
if (not epsilon) {
195-
epsilon = 0.0;
196-
}
197-
198-
if (*epsilon < 0 or *epsilon > 1) {
275+
if (params.epsilon < 0 or params.epsilon > 1) {
199276
usage();
200277
exit(1);
201278
}
202279

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

206283
optional<string> s;
207-
if (output_sb_graph) {
284+
if (params.output_sb_graph) {
208285
s = "";
209286
}
210287

211288
auto start_build_graph = chrono::high_resolution_clock::now();
212-
auto sb_graph = build_sb_graph(filename->c_str());
289+
auto sb_graph = build_sb_graph(params.filename->c_str());
213290
auto end_build_graph = chrono::high_resolution_clock::now();
214291
auto time_to_build_graph = chrono::duration<double, std::milli>(end_build_graph - start_build_graph).count();
215292

216293
cout << "sb_graph: " << sb_graph << endl;
217294

218295
auto start_partitionate = chrono::high_resolution_clock::now();
219-
auto partitions = best_initial_partition(sb_graph, *number_of_partitions, initial_partition_strategy, enable_multithreading);
220-
kl_sbg_imbalance_partitioner(sb_graph, partitions, *epsilon, enable_multithreading);
296+
auto partitions = best_initial_partition(sb_graph, *params.number_of_partitions, params.initial_partition_strategy, params.enable_multithreading);
297+
kl_sbg_imbalance_partitioner(sb_graph, partitions, params.epsilon, params.enable_multithreading);
221298
auto end_partitionate = chrono::high_resolution_clock::now();
222299
auto time_to_partitionate = chrono::duration<double, std::milli>(end_partitionate - start_partitionate).count();
223300

224-
if (compute_metrics) {
301+
if (params.compute_metrics) {
225302
map<string, metrics::communication_metrics> metrics;
226303

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

240-
if (compute_metrics and directory) {
317+
if (params.compute_metrics and params.directory) {
241318
std::vector<std::string> dir_files;
242-
read_directory(*directory, dir_files);
319+
read_directory(*params.directory, dir_files);
243320

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

265342
if (sanity_check_enabled) {
266-
sanity_check(sb_graph, partitions, *number_of_partitions);
343+
sanity_check(sb_graph, partitions, *params.number_of_partitions);
267344
}
268345

269346
if (s) {

algorithms/partitioner/partition_graph.hpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <sbg/interval.hpp>
2626
#include <sbg/sbg.hpp>
2727

28+
#include "partitioner_params.hpp"
2829
#include "sbg_partitioner_types.hpp"
2930
#include "weighted_sb_graph.hpp"
3031

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

3637

37-
enum InitialPartitionStrategy {
38-
ALL = 0,
39-
DFS_DISTRIBUTIVE_PREORDER = 1,
40-
DFS_DISTRIBUTIVE_POSTORDER = 2,
41-
DFS_GREEDY_PREORDER = 3,
42-
DFS_GREEDY_POSTORDER =4
43-
};
44-
45-
4638
/// @brief Converts a Partition element into a Set.
4739
/// @param partition - A list of SetPiece elements.
4840
/// @return A SBG::LIB::Set representation of the Partition element.

0 commit comments

Comments
 (0)