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

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