Plus...
* add named_object_list templates
* first tests with MSG_set_function in MY_launch_application
* some preliminary work for topology selection
* rename loba_least_loaded -> loba_simple
* some minor cleanups
CPPFLAGS += $(CHECK_FLAGS)
CFLAGS += -std=c99
-CFLAGS += -fgnu89-inline # workaround simgrid bug
+#CFLAGS += -fgnu89-inline # workaround simgrid bug
CFLAGS += $(OPTIM_FLAGS) $(DEBUG_FLAGS)
+#CXXFLAGS += -std=c++0x
CXXFLAGS += $(OPTIM_FLAGS) $(DEBUG_FLAGS)
LDFLAGS += -L $(SIMGRID_INSTALL_DIR)/lib
$(shell $(SETLOCALVERSION))
-.PHONY: all depend clean
+.PHONY: all clean realclean
all: $(TARGETS)
version.o: $(patsubst %.cpp,%.o,$(filter-out version.cpp, $(SRC.loba)))
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),realclean)
-include $(DEP)
+endif
+endif
.SECONDEXPANSION:
$(TARGETS): $$(patsubst %.cpp,%.o,$$(SRC.$$@))
* implement loba_* algorithms (start with some trivial one)
-* add loba algorithm selection (-a number ?)
* fix process::run when load is 0
-> wait for a message...
* implement automatic process topology
(line, ring, star, btree, clique, hypercube, etc..)
- use MSG_process_create_with_arguments
- name function name (is duped...)
- code use MSG_get_registered_function
- data NULL
- argc
- argv argv[0] = process_name
+* add synchronized mode
#include "deployment.h"
-namespace {
+#include <vector>
+#include <msg/msg.h>
+#include <xbt/dynar.h>
+#include <xbt/sysdep.h>
+#include "hostdata.h"
-}
void MY_launch_application()
{
+ xbt_assert(hostdata::size() >= 2);
+
+ const char* func = "simulation_main";
+ xbt_dynar_t p0_args = xbt_dynar_new(sizeof(const char*), NULL);
+ xbt_dynar_t p1_args = xbt_dynar_new(sizeof(const char*), NULL);
+
+ xbt_dynar_push_as(p0_args, const char*, "33");
+ xbt_dynar_push_as(p0_args, const char*, hostdata::at(1).get_name());
+
+ xbt_dynar_push_as(p1_args, const char*, "42");
+ xbt_dynar_push_as(p1_args, const char*, hostdata::at(0).get_name());
+
+ MSG_set_function(hostdata::at(0).get_name(), func, p0_args);
+ MSG_set_function(hostdata::at(1).get_name(), func, p1_args);
+
+ xbt_dynar_free(&p0_args);
+ xbt_dynar_free(&p1_args);
}
#include <algorithm>
#include <stdexcept>
#include <xbt/log.h>
+#include <xbt/sysdep.h>
#include "misc.h"
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(main);
+++ /dev/null
-#ifndef LOBA_LEAST_LOADED
-#define LOBA_LEAST_LOADED
-
-#include "process.h"
-
-class loba_least_loaded: public process {
-public:
- loba_least_loaded(int argc, char* argv[]): process(argc, argv) { }
- ~loba_least_loaded() { }
-
-private:
- double load_balance(double my_load);
-};
-
-#endif //!LOBA_LEAST_LOADED
-
-// Local variables:
-// mode: c++
-// End:
-#include "loba_least_loaded.h"
+#include "loba_simple.h"
#include <xbt/log.h>
* load balance with a least-loaded neighbor,
* without breaking the ping-pong condition
*/
-double loba_least_loaded::load_balance(double my_load)
+double loba_simple::load_balance(double my_load)
{
int imin = -1;
int imax = -1;
--- /dev/null
+#ifndef LOBA_SIMPLE
+#define LOBA_SIMPLE
+
+#include "process.h"
+
+class loba_simple: public process {
+public:
+ loba_simple(int argc, char* argv[]): process(argc, argv) { }
+ ~loba_simple() { }
+
+private:
+ double load_balance(double my_load);
+};
+
+#endif //!LOBA_SIMPLE
+
+// Local variables:
+// mode: c++
+// End:
EXIT_FAILURE_CLEAN = 0x08, // error at cleanup
};
-#include "loba_least_loaded.h"
+#include "loba_simple.h"
int simulation_main(int argc, char* argv[])
{
int result;
process* proc;
try {
- proc = new loba_least_loaded(argc, argv);
+ proc = opt::loba_algorithms.new_instance(opt::loba_algo, argc, argv);
result = proc->run();
delete proc;
}
TRY {
exit_status = EXIT_FAILURE_INIT; // =====
- // Register the main function of an agent in a global table.
- MSG_function_register("simulation_main", simulation_main);
+ // Register the default function of an agent
+ // MSG_function_register("simulation_main", simulation_main);
+ MSG_function_register_default(simulation_main);
// Create the platform and the application.
MSG_create_environment(opt::platform_file.c_str());
--- /dev/null
+#ifndef NAMED_OBJECT_LIST_H
+#define NAMED_OBJECT_LIST_H
+
+#include <map>
+#include <string>
+
+//===== arity 0 =====
+
+template <typename Base>
+class named_object_list {
+protected:
+ struct creator_base {
+ std::string description;
+ creator_base(const std::string& descr): description(descr) { }
+ creator_base(const char* descr): description(descr) { }
+ virtual Base* operator()() const = 0;
+ };
+
+ template <typename Derived>
+ struct creator: public creator_base {
+ creator(const std::string& descr): creator_base(descr) { }
+ creator(const char* descr): creator_base(descr) { }
+ Base* operator()() const { return new Derived(); }
+ };
+
+ typedef std::map<std::string, const creator_base*> map_type;
+
+ map_type assoc;
+
+ void insert(const std::string& name, const creator_base* creat)
+ {
+ assoc.insert(std::make_pair(name, creat));
+ }
+
+ void insert(const char* name, const creator_base* creat)
+ {
+ assoc.insert(std::make_pair(std::string(name), creat));
+ }
+
+public:
+ typedef typename map_type::const_iterator iterator;
+
+ named_object_list() { };
+ ~named_object_list()
+ {
+ for (iterator it = begin(); it != end(); ++it)
+ delete it->second;
+ }
+
+ Base* new_instance(const std::string& name) const
+ {
+ iterator it = assoc.find(name);
+ if (it != assoc.end())
+ return (*it->second)();
+ else
+ return NULL;
+ }
+
+ Base* new_instance(const char* name) const
+ {
+ return new_instance(std::string(name));
+ }
+
+ const std::string& get_name(iterator& it) const { return it->first; }
+ const std::string& get_descr(iterator& it) const
+ { return it->second->description; }
+
+ size_t size() const { return assoc.size(); }
+ iterator begin() const { return assoc.begin(); }
+ iterator end() const { return assoc.end(); }
+
+};
+
+//===== arity 2 =====
+
+#include <map>
+#include <string>
+
+template <typename Base, typename Arg1, typename Arg2>
+class named_object_list2 {
+protected:
+ struct creator_base {
+ std::string description;
+ creator_base(const std::string& descr): description(descr) { }
+ creator_base(const char* descr): description(descr) { }
+ virtual Base* operator()(Arg1, Arg2) const = 0;
+ };
+
+ template <typename Derived>
+ struct creator: public creator_base {
+ creator(const std::string& descr): creator_base(descr) { }
+ creator(const char* descr): creator_base(descr) { }
+ Base* operator()(Arg1 arg1, Arg2 arg2) const
+ { return new Derived(arg1, arg2); }
+ };
+
+ typedef std::map<std::string, const creator_base*> map_type;
+
+ map_type assoc;
+
+ void insert(const std::string& name, const creator_base* creat)
+ {
+ assoc.insert(std::make_pair(name, creat));
+ }
+
+ void insert(const char* name, const creator_base* creat)
+ {
+ assoc.insert(std::make_pair(std::string(name), creat));
+ }
+
+public:
+ typedef typename map_type::const_iterator iterator;
+
+ named_object_list2() { };
+ ~named_object_list2()
+ {
+ for (iterator it = begin(); it != end(); ++it)
+ delete it->second;
+ }
+
+ Base* new_instance(const std::string& name, Arg1 arg1, Arg2 arg2) const
+ {
+ iterator it = assoc.find(name);
+ if (it != assoc.end())
+ return (*it->second)(arg1, arg2);
+ else
+ return NULL;
+ }
+
+ Base* new_instance(const char* name, Arg1 arg1, Arg2 arg2) const
+ {
+ return new_instance(std::string(name), arg1, arg2);
+ }
+
+ const std::string& get_name(iterator& it) const { return it->first; }
+ const std::string& get_descr(iterator& it) const
+ { return it->second->description; }
+
+ bool exists(const std::string& name) const
+ { return assoc.find(name) != assoc.end(); }
+ iterator begin() const { return assoc.begin(); }
+ iterator end() const { return assoc.end(); }
+
+};
+
+//===================
+
+#define THIS_INSERT(name, descr, class) insert(name, new creator<class>(descr))
+
+#endif // !NAMED_OBJECT_LIST_H
+
+// Local variables:
+// mode: c++
+// End:
#include <sstream>
#include <unistd.h> // getopt
#include <xbt/log.h>
-#include "misc.h"
+#include "loba_simple.h"
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(main);
namespace opt {
+ // Global options
std::string program_name;
-
- std::string platform_file;
- std::string deployment_file;
-
int help_requested = 0;
bool version_requested = false;
+ // Simulation parameters
unsigned log_rate = 1;
+ // Platform and deployment
+ std::string platform_file;
+ std::string deployment_file;
+
+ // Automatic deployment
namespace auto_depl {
bool enabled = false;
std::string topology;
double load = 0.0;
}
- unsigned maxiter = 4; // fixme
- bool exit_on_close = false;
-
+ // Load balancing algorithm
+ std::string loba_algo("none");
bool bookkeeping = false;
+ // Application parameters
cost_func comp_cost("1e9, 0"); // fixme: find better defaults
cost_func comm_cost("1, 0"); // fixme: find better defaults
+ unsigned maxiter = 4; // fixme
+ bool exit_on_close = false;
+
+ // Named parameters lists
+ loba_algorithms_type loba_algorithms;
+ loba_algorithms_type::loba_algorithms_type()
+ {
+ THIS_INSERT("none", "no load-balancing", process);
+ THIS_INSERT("simple", "balance with least loaded neighbor",
+ loba_simple);
+ }
+
+#if 0
+ topologies_type topologies;
+ topologies_type::topologies_type()
+ {
+ THIS_INSERT("none", "no load-balancing", process);
+ THIS_INSERT("simple", "balance with least loaded neighbor",
+ loba_simple);
+ }
+#endif
} // namespace opt
int c;
opterr = 0;
- while ((c = getopt(*argc, argv, "bc:C:ehi:l:L:N:T:V")) != -1) {
+ while ((c = getopt(*argc, argv, "a:bc:C:ehi:l:L:N:T:V")) != -1) {
switch (c) {
+ case 'a':
+ opt::loba_algo = optarg;
+ break;
case 'b':
opt::bookkeeping = true;
break;
void opt::usage()
{
+ // option(...)
#define o(opt) " " << std::setw(14) \
<< std::left << (opt) << std::right << " "
-#define so(subopt) std::setw(10) << (subopt) << ": "
+ // sub-option(...)
+#define so(subopt) std::setw(18) << (subopt) << " : "
+ // sub-option list
+#define so_list(name) do { \
+ name ## _type::iterator it; \
+ for (it = name.begin() ; it != name.end() ; ++it) \
+ std::clog << so(name.get_name(it)) \
+ << name.get_descr(it) << "\n"; \
+ } while (0)
+
std::clog << "Usage: " << opt::program_name
<< " [options] <platform_file> <deployment_file>\n";
<< "print current load every n-th iterations, 0 to disable"
<< " (" << opt::log_rate << ")\n";
+ std::clog << "\nAutomatic deployment options\n";
+ std::clog << o("-T name")
+ << "enable automatic deployment with selected topology\n";
+ if (opt::help_requested > 1)
+#if 0
+ so_list(opt::topologies);
+#else
+ std::clog << so("name") << "FIXME\n"; // fixme
+#endif
+ std::clog << o("-L value")
+ << "total load with auto deployment, 0 for number of hosts"
+ << " (" << opt::auto_depl::load << ")\n";
+ std::clog << o("-N value")
+ << "number of hosts to use with auto deployment,"
+ << " 0 for max. (" << opt::auto_depl::nhosts << ")\n";
+
+ std::clog << "\nLoad balancing algorithm\n";
+ std::clog << o("-a name") << "load balancing algorithm"
+ << " (" << opt::loba_algo << ")\n";
+ if (opt::help_requested > 1)
+ so_list(opt::loba_algorithms);
+ std::clog << o("-b") << "enable bookkeeping\n";
+
std::clog << "\nApplication parameters\n";
std::clog << o("-c [fn,...]f0")
<< "polynomial factors for computation cost"
<< "maximum number of iterations, 0 for infinity"
<< " (" << opt::maxiter << ")\n";
- std::clog << "\nLoad balancing algorithm\n";
- std::clog << o("-b") << "enable bookkeeping\n";
-
- std::clog << "\nAutomatic deployment options\n";
- std::clog << o("-T type")
- << "enable automatic deployment with selected topology\n";
- if (opt::help_requested > 1) {
- std::clog << so(1) << "pipo\n";
- std::clog << so(42) << "atchoum\n";
- }
- std::clog << o("-L value")
- << "total load with auto deployment, 0 for number of hosts"
- << " (" << opt::auto_depl::load << ")\n";
- std::clog << o("-N value")
- << "number of hosts to use with auto deployment,"
- << " 0 for max. (" << opt::auto_depl::nhosts << ")\n";
-
+#undef so_list
#undef so
#undef o
}
#include <string>
#include "cost_func.h"
+#include "named_object_list.h"
+#include "process.h"
// Global parameters, shared by all the processes
namespace opt {
+ // Global options
extern std::string program_name;
-
- extern std::string platform_file;
- extern std::string deployment_file;
-
extern int help_requested;
extern bool version_requested;
+ // Simulation parameters
extern unsigned log_rate;
+ // Platform and deployment
+ extern std::string platform_file;
+ extern std::string deployment_file;
+
+ // Automatic deployment
namespace auto_depl {
extern bool enabled;
extern std::string topology;
extern double load;
}
- extern std::string topology;
- extern double init_load;
+ // Load balancing algorithm
+ extern std::string loba_algo;
+ extern bool bookkeeping;
+ // Application parameters
+ extern cost_func comp_cost;
+ extern cost_func comm_cost;
extern unsigned maxiter;
extern bool exit_on_close;
- extern bool bookkeeping;
+ // Named parameters lists
+ extern struct loba_algorithms_type:
+ public named_object_list2<process, int, char** > {
+ loba_algorithms_type();
+ } loba_algorithms;
- extern cost_func comp_cost;
- extern cost_func comm_cost;
+#if 0
+ extern struct topologies_type:
+ public named_object_list<xxx> {
+ topologies_type();
+ } topologies;
+#endif
+ // Utility functions
int parse_args(int* argc, char* argv[]);
void print();
void usage();
double process::load_balance(double /*my_load*/)
{
+ if (iter == 1)
+ WARN0("process::load_balance is a no-op!");
return 0.0;
}