1 /* Copyright (c) 2006-2018. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
8 #include <simgrid/plugins/load.h>
9 #include <simgrid/s4u.hpp>
10 #include <simgrid/smpi/loadbalancer/load_balancer.hpp>
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(plugin_load_balancer_impl, smpi, "Logging specific to the SMPI load balancing plugin");
16 namespace loadbalancer {
18 static std::map<simgrid::s4u::Host*, double> additional_load;
20 static bool compare_by_avg_load(simgrid::s4u::Host* a, simgrid::s4u::Host* b)
22 return sg_host_get_avg_load(a) + additional_load[a] > sg_host_get_avg_load(b) + additional_load[b];
25 LoadBalancer::LoadBalancer()
29 LoadBalancer::~LoadBalancer()
33 void LoadBalancer::run()
35 simgrid::s4u::Engine* engine = simgrid::s4u::Engine::get_instance();
36 std::vector<simgrid::s4u::Host*> available_hosts = engine->get_filtered_hosts([](simgrid::s4u::Host* host) {
37 return not host->is_off();
39 xbt_assert(available_hosts.size() > 0, "No hosts available; are they all switched off?");
40 for (auto& host : available_hosts) {
41 additional_load[host] = 0;
44 // TODO: Account for daemon background load (-> use especially the availability file)
46 std::vector<simgrid::s4u::ActorPtr> all_actors =
47 engine->get_filtered_actors([](simgrid::s4u::ActorPtr actor) { return not actor->is_daemon(); });
48 for (auto& actor : all_actors) {
49 new_mapping[actor] = actor->get_host();
51 // Sort the actors, from highest to lowest load; we then just iterate over these actors
52 std::sort(all_actors.begin(), all_actors.end(), [this](simgrid::s4u::ActorPtr a, simgrid::s4u::ActorPtr b) {
53 return actor_computation[a->get_pid()] < actor_computation[b->get_pid()];
55 for (auto& actor : all_actors) {
56 XBT_INFO("Order: %li", actor->get_pid());
58 // Sort the hosts. Use a heap datastructure, because we re-insert a host
59 // that got an actor assigned in a possibly different position
60 // This is equivalent to a std::greater<Host*> implementation that uses the load to compare the two objects.
61 // --> The least loaded host will be in the first position
62 std::priority_queue</*datatype*/ simgrid::s4u::Host*, /*container*/ std::vector<simgrid::s4u::Host*>,
63 /*comparison function*/ std::function<bool(simgrid::s4u::Host*, simgrid::s4u::Host*)>>
64 usable_hosts(compare_by_avg_load, std::move(available_hosts));
66 for (auto& actor : all_actors) {
67 simgrid::s4u::Host* target_host = usable_hosts.top(); // This is the host with the lowest load
69 if (target_host != actor->get_host() && actor->get_host()->get_actor_count() > 1) {
72 assign(actor, target_host); // This updates also the load
73 usable_hosts.push(target_host);
78 void LoadBalancer::assign(simgrid::s4u::ActorPtr actor, simgrid::s4u::Host* host)
80 // If an actor gets re-assigned twice, we don't want to subtract
81 // the load from the same host twice so we have to use the old value of new_mapping here
82 additional_load[new_mapping[actor]] -= 1; // actor->load();
83 additional_load[host] += 1; // actor->load();
84 new_mapping[actor] = host;
86 XBT_INFO("Assigning actor %li to host %s", actor->get_pid(), host->get_cname());
89 simgrid::s4u::Host* LoadBalancer::get_mapping()
91 return new_mapping[simgrid::s4u::Actor::self()];
94 void LoadBalancer::record_actor_computation(simgrid::s4u::ActorPtr actor, double load)
96 actor_computation[actor->get_pid()] += load;