S4U:
- New function: Engine::run_until(date), to split the simulation.
- New signal: Activity::on_veto, to detect when an activity fails to start.
+ - New function: Engine::track_vetoed_activities() to interrupt run()
+ when an activity fails to start, and to keep track of such activities.
+ Please see the corresponding example for more info.
SMPI:
- Dynamic costs for MPI operations: New API to allow users to dynamically
comm-pingpong comm-ready comm-serialize comm-suspend comm-wait comm-waitany comm-waitall comm-waituntil
comm-dependent comm-host2host comm-failure
cloud-capping cloud-migration cloud-simple
+ dag-simple
dht-chord dht-kademlia
energy-exec energy-boot energy-link energy-vm energy-exec-ptask energy-wifi
engine-filtering engine-run-partial
--- /dev/null
+/* Copyright (c) 2007-2021. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "simgrid/s4u.hpp"
+#include <vector>
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "Messages specific for this s4u example");
+
+int main(int argc, char* argv[])
+{
+ simgrid::s4u::Engine e(&argc, argv);
+ e.load_platform(argv[1]);
+ std::set<simgrid::s4u::Activity*> vetoed;
+ e.track_vetoed_activities(&vetoed);
+
+ auto fafard = e.host_by_name("Fafard");
+
+ // Display the details on vetoed activities
+ simgrid::s4u::Activity::on_veto.connect([&e](simgrid::s4u::Activity& a) {
+ auto& exec = static_cast<simgrid::s4u::Exec&>(a); // all activities are execs in this example
+
+ XBT_INFO("Activity '%s' vetoed. Dependencies: %s; Ressources: %s", exec.get_cname(),
+ (exec.dependencies_solved() ? "solved" : "NOT solved"),
+ (exec.is_assigned() ? "assigned" : "NOT assigned"));
+ });
+
+ // Define an amount of work that should take 1 second to execute.
+ double computation_amount = fafard->get_speed();
+
+ // Create a small DAG: Two parents and a child
+ simgrid::s4u::ExecPtr first_parent = simgrid::s4u::Exec::init();
+ simgrid::s4u::ExecPtr second_parent = simgrid::s4u::Exec::init();
+ simgrid::s4u::ExecPtr child = simgrid::s4u::Exec::init();
+ first_parent->add_successor(child);
+ second_parent->add_successor(child);
+
+ /*
+ std::vector<simgrid::s4u::ExecPtr> pending_execs;
+ pending_execs.push_back(first_parent);
+ pending_execs.push_back(second_parent);
+ pending_execs.push_back(child);
+ */
+
+ // Set the parameters (the name is for logging purposes only)
+ // + First parent ends after 1 second and the Second parent after 2 seconds.
+ first_parent->set_name("parent 1")->set_flops_amount(computation_amount);
+ second_parent->set_name("parent 2")->set_flops_amount(2 * computation_amount);
+ child->set_name("child")->set_flops_amount(computation_amount);
+
+ // Only the parents are scheduled so far
+ first_parent->set_host(fafard);
+ second_parent->set_host(fafard);
+
+ // Start all activities that can actually start.
+ first_parent->vetoable_start();
+ second_parent->vetoable_start();
+ child->vetoable_start();
+
+ while (child->get_state() != simgrid::s4u::Activity::State::FINISHED) {
+ e.run();
+ for (auto* a : vetoed) {
+ auto* exec = static_cast<simgrid::s4u::Exec*>(a);
+
+ // In this simple case, we just assign the child task to a resource when its dependencies are solved
+ if (exec->dependencies_solved() && not exec->is_assigned()) {
+ XBT_INFO("Activity %s's dependencies are resolved. Let's assign it to Fafard.", exec->get_cname());
+ exec->set_host(fafard);
+ } else {
+ XBT_INFO("Activity %s not ready.", exec->get_cname());
+ }
+ }
+ vetoed.clear(); // DON'T FORGET TO CLEAR this set between two calls to run
+ }
+
+ XBT_INFO("Simulation time %g", simgrid::s4u::Engine::get_clock());
+
+ return 0;
+}
--- /dev/null
+#!/usr/bin/env tesh
+
+$ ${bindir:=.}/s4u-dag-simple ${platfdir}/small_platform.xml --log=s4u_activity.t:verbose "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
+> [ 0.000000] (0:maestro@) 'parent 1' is assigned to a resource and all dependencies are solved. Let's start
+> [ 0.000000] (0:maestro@) 'parent 2' is assigned to a resource and all dependencies are solved. Let's start
+> [ 0.000000] (0:maestro@) Activity 'child' vetoed. Dependencies: NOT solved; Ressources: NOT assigned
+> [ 2.000000] (0:maestro@) Remove a dependency from 'parent 1' on 'child'
+> [ 2.000000] (0:maestro@) Activity child not ready.
+> [ 3.000000] (0:maestro@) Remove a dependency from 'parent 2' on 'child'
+> [ 3.000000] (0:maestro@) Activity 'child' vetoed. Dependencies: solved; Ressources: NOT assigned
+> [ 3.000000] (0:maestro@) Activity child's dependencies are resolved. Let's assign it to Fafard.
+> [ 3.000000] (0:maestro@) 'child' is assigned to a resource and all dependencies are solved. Let's start
+> [ 4.000000] (0:maestro@) Simulation time 4
throw std::invalid_argument("Dependency does not exist. Can not be removed.");
}
+ static std::set<Activity*>* vetoed_activities_;
+
public:
/*! Signal fired each time that the activity fails to start because of a veto (e.g., unsolved dependency or no
* resource assigned) */
XBT_CVERB(s4u_activity, "'%s' is assigned to a resource and all dependencies are solved. Let's start", get_cname());
start();
} else {
+ if (vetoed_activities_ != nullptr)
+ vetoed_activities_->insert(this);
on_veto(*this);
}
}
+ static std::set<Activity*>* get_vetoed_activities() { return vetoed_activities_; }
+ static void set_vetoed_activities(std::set<Activity*>* whereto) { vetoed_activities_ = whereto; }
+
#ifndef DOXYGEN
Activity(Activity const&) = delete;
Activity& operator=(Activity const&) = delete;
#include <simgrid/kernel/resource/Model.hpp>
#include <simgrid/s4u/NetZone.hpp>
+#include <set>
#include <string>
#include <utility>
#include <vector>
register_function(name, code_factory);
}
+ /** If non-null, the provided set will be filled with all activities that fail to start because of a veto */
+ void track_vetoed_activities(std::set<Activity*>* vetoed_activities);
+
void load_deployment(const std::string& deploy) const;
protected:
class XBT_PUBLIC Exec : public Activity_T<Exec> {
#ifndef DOXYGEN
friend kernel::activity::ExecImpl;
+ friend kernel::EngineImpl; // Auto-completes the execs of maestro (in simDAG)
#endif
bool parallel_ = false;
XBT_DEBUG("Handling the failed actions (if any)");
while (auto* action = model->extract_failed_action()) {
XBT_DEBUG(" Handling Action %p", action);
- if (action->get_activity() != nullptr)
+ if (action->get_activity() != nullptr) {
+ // If nobody told the interface that the activity has failed, that's because no actor waits on it (maestro
+ // started it). SimDAG I see you!
+ auto* exec = dynamic_cast<activity::ExecImpl*>(action->get_activity());
+ if (exec != nullptr && exec->get_actor() == maestro_)
+ exec->get_iface()->complete(s4u::Activity::State::FAILED);
+
activity::ActivityImplPtr(action->get_activity())->post();
+ }
}
XBT_DEBUG("Handling the terminated actions (if any)");
while (auto* action = model->extract_done_action()) {
XBT_DEBUG(" Handling Action %p", action);
if (action->get_activity() == nullptr)
XBT_DEBUG("probably vcpu's action %p, skip", action);
- else
+ else {
+ // If nobody told the interface that the activity is finished, that's because no actor waits on it (maestro
+ // started it). SimDAG I see you!
+ // TODO: do the same for other activity kinds once comms are cleaned up
+ auto* exec = dynamic_cast<activity::ExecImpl*>(action->get_activity());
+ if (exec != nullptr && exec->get_actor() == maestro_)
+ exec->get_iface()->complete(s4u::Activity::State::FINISHED);
+
activity::ActivityImplPtr(action->get_activity())->post();
+ }
}
}
}
}
double elapsed_time = -1;
+ std::set<s4u::Activity*>* vetoed_activities = s4u::Activity::get_vetoed_activities();
do {
XBT_DEBUG("New Schedule Round; size(queue)=%zu", actors_to_run_.size());
next_time = std::min(next_time, max_date);
}
- if (next_time > -1.0 || not actor_list_.empty()) {
- XBT_DEBUG("Calling solve(%g) %g", next_time, NOW);
- elapsed_time = solve(next_time);
- XBT_DEBUG("Moving time ahead. NOW=%g; elapsed: %g", NOW, elapsed_time);
- } else {
- elapsed_time = -1;
- }
+ XBT_DEBUG("Calling solve(%g) %g", next_time, NOW);
+ elapsed_time = solve(next_time);
+ XBT_DEBUG("Moving time ahead. NOW=%g; elapsed: %g", NOW, elapsed_time);
/* Notify all the hosts that have failed */
/* FIXME: iterate through the list of failed host and mark each of them */
/* Clean actors to destroy */
empty_trash();
- XBT_DEBUG("### elapsed time %f, #actors %zu, #to_run %zu", elapsed_time, actor_list_.size(), actors_to_run_.size());
+ XBT_DEBUG("### elapsed time %f, #actors %zu, #to_run %zu, #vetoed %d", elapsed_time, actor_list_.size(),
+ actors_to_run_.size(), (vetoed_activities == nullptr ? -1 : static_cast<int>(vetoed_activities->size())));
if (elapsed_time < 0. && actors_to_run_.empty() && not actor_list_.empty()) {
if (actor_list_.size() <= daemons_.size()) {
maestro_->kill(kv.second);
}
}
- } while ((elapsed_time > -1.0 && not double_equals(max_date, NOW, 0.00001)) || has_actors_to_run());
- if (not actor_list_.empty() && max_date < 0)
+ } while ((vetoed_activities == nullptr || vetoed_activities->empty()) &&
+ ((elapsed_time > -1.0 && not double_equals(max_date, NOW, 0.00001)) || has_actors_to_run()));
+
+ if (not actor_list_.empty() && max_date < 0 && not(vetoed_activities == nullptr || vetoed_activities->empty()))
THROW_IMPOSSIBLE;
simgrid::s4u::Engine::on_simulation_end();
public:
ExecImpl();
s4u::Exec* get_iface() { return piface_; }
+ actor::ActorImpl* get_actor() { return actor_; }
ExecImpl& set_timeout(double timeout) override;
ExecImpl& set_bound(double bound);
xbt::signal<void(Activity&)> Activity::on_veto;
+std::set<Activity*>* Activity::vetoed_activities_ = nullptr;
+
void Activity::wait_until(double time_limit)
{
double now = Engine::get_clock();
}
}
+void Engine::track_vetoed_activities(std::set<Activity*>* vetoed_activities)
+{
+ Activity::set_vetoed_activities(vetoed_activities);
+}
+
/** @brief Retrieve the root netzone, containing all others */
s4u::NetZone* Engine::get_netzone_root() const
{