]> AND Private Git Repository - loba.git/blob - options.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
Named options may now be selected by prefix if there is no ambiguity.
[loba.git] / options.cpp
1 #include <iomanip>
2 #include <iostream>
3 #include <sstream>
4 #include <stack>
5 #include <unistd.h>             // getopt
6 #include <xbt/log.h>
7
8 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(main);
9
10 #include "loba_simple.h"
11 #include "loba_fairstrategy.h"
12
13 #include "options.h"
14
15 namespace opt {
16
17     // Constants
18
19     // A sum of loads if considered null if it is less than
20     // load_ratio_threshold percent of the sum of loads at init.
21     const double load_ratio_threshold = 1e-4;
22
23     // Global options
24     std::string program_name;
25     int help_requested = 0;
26     bool version_requested = false;
27
28     // Simulation parameters
29     unsigned log_rate = 1;
30
31     // Platform and deployment
32     std::string platform_file;
33     std::string deployment_file;
34
35     // Automatic deployment
36     namespace auto_depl {
37         bool        enabled = false;
38         std::string topology("clique");
39         unsigned    nhosts = 0;
40         double      load = 0.0;
41     }
42
43     // Load balancing algorithm
44     std::string loba_algo("simple");
45     bool bookkeeping = false;
46
47     // Application parameters
48     cost_func comp_cost("1e9, 0"); // fixme: find better defaults
49     cost_func comm_cost("1, 0"); // fixme: find better defaults
50     unsigned maxiter = 10;       // fixme: find better defaults
51     bool exit_on_close = false;
52
53     // Named parameters lists
54     loba_algorithms_type loba_algorithms;
55     loba_algorithms_type::loba_algorithms_type()
56     {
57         NOL_INSERT("fairstrategy", "balance with fair strategy", loba_fairstrategy);
58         NOL_INSERT("none", "no load-balancing (for testing only)", process);
59         NOL_INSERT("simple", "balance with least loaded neighbor", loba_simple);
60     }
61
62     topologies_type topologies;
63     topologies_type::topologies_type()
64     {
65         NOL_INSERT("btree", "binary tree topology, initial load at root",
66                    deployment_btree);
67         NOL_INSERT("clique", "all connected topology", deployment_clique);
68         NOL_INSERT("hcube", "hypercube topology", deployment_hcube);
69         NOL_INSERT("line", "line topology, initial load at one end",
70                    deployment_line);
71         NOL_INSERT("ring", "ring topology", deployment_ring);
72         NOL_INSERT("star", "star topology, initial load at center",
73                    deployment_star);
74         NOL_INSERT("torus", "torus topology", deployment_torus);
75     }
76
77 } // namespace opt
78
79 namespace {
80
81     template <typename T>
82     bool nol_find_prefix(const T& nol, const char* descr, std::string& name)
83     {
84         bool result = nol.exists(name);
85         if (!result) {
86             std::stack<std::string> candidates;
87             for (typename T::iterator it = nol.begin() ; it != nol.end() ; ++it) {
88                 const std::string& fullname = nol.get_name(it);
89                 if (fullname.compare(0, name.length(), name) == 0)
90                     candidates.push(fullname);
91             }
92             switch (candidates.size()) {
93             case 0:
94                 ERROR2("unknownw %s -- %s", descr, name.c_str());
95                 break;
96             case 1:
97                 name = candidates.top();
98                 candidates.pop();
99                 result = true;
100                 DEBUG2("infered %s -- %s", descr, name.c_str());
101                 break;
102             default:
103                 ERROR2("ambiguous %s -- %s", descr, name.c_str());
104                 while (!candidates.empty()) {
105                     ERROR1("  candidates are -- %s", candidates.top().c_str());
106                     candidates.pop();
107                 }
108                 break;
109             }
110         }
111         return result;
112     }
113
114 } // namespace
115
116 bool opt::parse_args(int* argc, char* argv[])
117 {
118     bool result = true;
119
120     opt::program_name = argv[0];
121     opt::program_name.erase(0, 1 + opt::program_name.find_last_of('/'));
122     
123     int c;
124     opterr = 0;
125     while ((c = getopt(*argc, argv, "a:bc:C:ehi:l:L:N:T:vV")) != -1) {
126         switch (c) {
127         case 'a':
128             opt::loba_algo = optarg;
129             result = nol_find_prefix(opt::loba_algorithms,
130                                      "load balancing algorithm",
131                                      opt::loba_algo);
132             break;
133         case 'b':
134             opt::bookkeeping = true;
135             break;
136         case 'e':
137             opt::exit_on_close = true;
138             break;
139         case 'h':
140             opt::help_requested++;
141             break;
142         case 'c':
143             opt::comp_cost = cost_func(optarg);
144             break;
145         case 'C':
146             opt::comm_cost = cost_func(optarg);
147             break;
148         case 'i':
149             std::istringstream(optarg) >> opt::maxiter;
150             break;
151         case 'l':
152             std::istringstream(optarg) >> opt::log_rate;
153             break;
154         case 'L':
155             std::istringstream(optarg) >> opt::auto_depl::load;
156             break;
157         case 'N':
158             std::istringstream(optarg) >> opt::auto_depl::nhosts;
159             break;
160         case 'T':
161             opt::auto_depl::topology = optarg;
162             result = nol_find_prefix(opt::topologies, "topology",
163                                      opt::auto_depl::topology);
164             break;
165         case 'v':
166             // nothing to do: this option is checked at the very
167             // beginning of main()
168             break;
169         case 'V':
170             opt::version_requested = true;
171             break;
172         case '?':
173             ERROR1("invalid option -- '%c'", optopt);
174             result = false;
175             break;
176         }
177     }
178
179     if (opt::version_requested || opt::help_requested)
180         return 1;
181
182     if (optind < *argc) {
183         opt::platform_file = argv[optind++];
184     } else {
185         ERROR0("missing parameter -- <plaform_file>");
186         result = false;
187     }
188     if (optind < *argc) {
189         opt::deployment_file = argv[optind++];
190     }
191     opt::auto_depl::enabled = opt::deployment_file.empty();
192
193     while (optind < *argc) {
194         ERROR1("unused parameter -- \"%s\"", argv[optind++]);
195         result = false;
196     }
197
198     return result;
199 }
200
201 namespace {
202
203     // some helper functions for opt::print()
204
205     const char* on_off(bool b)
206     {
207         return b ? "on" : "off";
208     }
209
210     template <typename T>
211     const char* val_or_string(const T& val, const char* str, const T& deflt = 0)
212     {
213         static std::string res;
214         if (val != deflt) {
215             std::ostringstream oss;
216             oss << val;
217             res = oss.str();
218         } else {
219             res = str;
220         }
221         return res.c_str();
222     }
223
224 } // namespace
225
226 void opt::print()
227 {
228     INFO0(",----[ Simulation parameters ]");
229     INFO1("| log rate.....................: %s",
230           val_or_string(opt::log_rate, "disabled"));
231     INFO1("| platform file................: \"%s\"", opt::platform_file.c_str());
232     if (opt::auto_depl::enabled) {
233         INFO0("| automatic deployment enabled");
234         INFO1("| - topology...................: %s", opt::auto_depl::topology.c_str());
235         INFO1("| - number of hosts............: %s",
236               val_or_string(opt::auto_depl::nhosts, "auto"));
237         INFO1("| - initial load...............: %s",
238               val_or_string(opt::auto_depl::load, "auto"));
239     } else {
240         INFO1("| deployment file..............: \"%s\"", opt::deployment_file.c_str());
241     }
242     INFO1("| load balancing algorithm.....: %s",   opt::loba_algo.c_str());
243     INFO1("| bookkeeping..................: %s",   on_off(opt::bookkeeping));
244     INFO1("| computation cost factors.....: [%s]", opt::comp_cost.to_string().c_str());
245     INFO1("| communication cost factors...: [%s]", opt::comm_cost.to_string().c_str());
246     INFO1("| maximum number of iterations.: %s",
247           val_or_string(opt::maxiter, "infinity"));
248     INFO1("| exit on close................: %s",   on_off(opt::exit_on_close));
249     INFO0("`----");
250 }
251
252 void opt::usage()
253 {
254     // option(...)
255 #define o(opt) "    " << std::setw(14) \
256                       << std::left << (opt) << std::right << " "
257     // sub-option(...)
258 #define so(subopt) std::setw(18) << (subopt) << " : "
259     // sub-option list
260 #define so_list(name) do {                                      \
261         name ## _type::iterator it;                             \
262         for (it = name.begin() ; it != name.end() ; ++it)       \
263             std::clog << so(name.get_name(it))                  \
264                       << name.get_descr(it) << "\n";            \
265     } while (0)
266
267
268     std::clog << "Usage: " << opt::program_name
269               << " [options] <platform_file> [<deployment_file>]\n";
270
271     std::clog << "\nGlobal options\n";
272     std::clog << o("-h")
273               << "print help and exit (use -hh or -hhh for extended help)\n";
274     if (opt::help_requested < 1)
275         return;
276
277     std::clog << o("--help") << "print help from SimGrid framework and exit\n";
278     std::clog << o("-V") << "print version and exit\n";
279
280     std::clog << "\nSimulation parameters\n";
281     std::clog << o("-l value")
282               << "print current load every n-th iterations, 0 to disable"
283               << " (" << opt::log_rate << ")\n";
284     std::clog << o("-v")
285               << "verbose: do not override the default logging parameters\n";
286
287     std::clog << "\nAutomatic deployment options\n";
288     std::clog << o("-T name")
289               << "enable automatic deployment with selected topology"
290               << " (" << opt::auto_depl::topology << ")\n";
291     if (opt::help_requested > 1)
292         so_list(opt::topologies);
293     std::clog << o("-L value")
294               << "total load with auto deployment, 0 for number of hosts"
295               << " (" << opt::auto_depl::load << ")\n";
296     std::clog << o("-N value")
297               << "number of hosts to use with auto deployment,"
298               << " 0 for max. (" << opt::auto_depl::nhosts << ")\n";
299
300     std::clog << "\nLoad balancing algorithm\n";
301     std::clog << o("-a name") << "load balancing algorithm"
302               << " (" << opt::loba_algo << ")\n";
303     if (opt::help_requested > 1)
304         so_list(opt::loba_algorithms);
305     std::clog << o("-b") << "enable bookkeeping\n";
306
307     std::clog << "\nApplication parameters\n";
308     std::clog << o("-c [fn,...]f0")
309               << "polynomial factors for computation cost"
310               << " (" << opt::comp_cost.to_string() << ")\n";
311     std::clog << o("-C [fn,...]f0")
312               << "polynomial factors for communication cost"
313               << " (" << opt::comm_cost.to_string() << ")\n";
314     std::clog << o("-e") << "exit on reception of \"close\" message\n";
315     std::clog << o("-i value")
316               << "maximum number of iterations, 0 for infinity"
317               << " (" << opt::maxiter << ")\n";
318
319     if (opt::help_requested < 3)
320         return;
321
322     std::clog << "\nLogging support\n"
323               << "    See SimGrid documentation on:\n"
324               << "        http://simgrid.gforge.inria.fr/doc/group__XBT__log.html#log_user\n"
325               << "    Existing categories are:\n"
326               << "        simu : root of following categories\n"
327               << "        main : messages from global infrastructure\n"
328               << "        depl : messages from auto deployment (inherited from main)\n"
329               << "        comm : messages from asynchronous pipes\n"
330               << "        proc : messages from base process class\n"
331               << "        loba : messages from load-balancer\n";
332
333 #undef so_list
334 #undef so
335 #undef o
336 }
337
338 // Local variables:
339 // mode: c++
340 // End: