Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
New: Engine::run_until(date) to split the simulation
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Tue, 14 Dec 2021 16:17:08 +0000 (17:17 +0100)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Tue, 14 Dec 2021 16:18:51 +0000 (17:18 +0100)
ChangeLog
include/simgrid/s4u/Engine.hpp
src/bindings/python/simgrid_python.cpp
src/kernel/EngineImpl.cpp
src/kernel/EngineImpl.hpp
src/s4u/s4u_Engine.cpp
src/smpi/internals/smpi_global.cpp

index bba357b..c71fe26 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,9 @@
 
 SimGrid (3.29.1) NOT RELEASED YET (v3.30 expected December 21. 2021, 15:59 UTC)
 
+Engine:
+ - New function: run_until(date) allowing to split the simulation.
+
 SMPI:
  - Dynamic costs for MPI operations: New API to allow users to dynamically
  change injected costs for MPI_Recv, MPI_Send and MPI_Isend operations.
index 2a88c38..778bc84 100644 (file)
@@ -43,9 +43,12 @@ public:
   /** Finalize the default engine and all its dependencies */
   void shutdown();
 
-  /** Run the simulation after initialization */
+  /** Run the simulation until its end */
   void run() const;
 
+  /** Run the simulation until the specified date */
+  void run_until(double max_date) const;
+
   /** @brief Retrieve the simulation time (in seconds) */
   static double get_clock();
   /** @brief Retrieve the engine singleton */
index 7530f38..3c0eb07 100644 (file)
@@ -139,7 +139,10 @@ PYBIND11_MODULE(simgrid, m)
       .def("get_all_hosts", &Engine::get_all_hosts, "Returns the list of all hosts found in the platform")
       .def("load_platform", &Engine::load_platform, "Load a platform file describing the environment")
       .def("load_deployment", &Engine::load_deployment, "Load a deployment file and launch the actors that it contains")
-      .def("run", &Engine::run, py::call_guard<py::gil_scoped_release>(), "Run the simulation")
+      .def("run", &Engine::run, py::call_guard<py::gil_scoped_release>(), "Run the simulation until its end")
+      .def("run_until", py::overload_cast<double>(&Engine::run_until, py::const_),
+           py::call_guard<py::gil_scoped_release>(), "Run the simulation until the given date",
+           py::arg("max_date") = -1)
       .def(
           "register_actor",
           [](Engine* e, const std::string& name, py::object fun_or_class) {
index b6269d0..6b08aa1 100644 (file)
@@ -672,7 +672,7 @@ double EngineImpl::solve(double max_date) const
   return time_delta;
 }
 
-void EngineImpl::run()
+void EngineImpl::run(double max_date)
 {
   if (MC_record_replay_is_active()) {
     mc::replay(MC_record_path());
@@ -680,7 +680,7 @@ void EngineImpl::run()
     return;
   }
 
-  double time = 0;
+  double elapsed_time = -1;
 
   do {
     XBT_DEBUG("New Schedule Round; size(queue)=%zu", actors_to_run_.size());
@@ -784,11 +784,21 @@ void EngineImpl::run()
         }
     }
 
-    time = timer::Timer::next();
-    if (time > -1.0 || not actor_list_.empty()) {
-      XBT_DEBUG("Calling solve");
-      time = solve(time);
-      XBT_DEBUG("Moving time ahead : %g", time);
+    // Compute the max_date of the next solve.
+    // It's either when a timer occurs, or when user-specified deadline is reached, or -1 if none is given
+    double next_time = timer::Timer::next();
+    if (next_time < 0 && max_date > -1) {
+      next_time = max_date;
+    } else if (next_time > -1 && max_date > -1) { // either both <0, or both >0
+      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;
     }
 
     /* Notify all the hosts that have failed */
@@ -807,9 +817,9 @@ void EngineImpl::run()
     /* Clean actors to destroy */
     empty_trash();
 
-    XBT_DEBUG("### time %f, #actors %zu, #to_run %zu", time, actor_list_.size(), actors_to_run_.size());
+    XBT_DEBUG("### elapsed time %f, #actors %zu, #to_run %zu", elapsed_time, actor_list_.size(), actors_to_run_.size());
 
-    if (time < 0. && actors_to_run_.empty() && not actor_list_.empty()) {
+    if (elapsed_time < 0. && actors_to_run_.empty() && not actor_list_.empty()) {
       if (actor_list_.size() <= daemons_.size()) {
         XBT_CRITICAL("Oops! Daemon actors cannot do any blocking activity (communications, synchronization, etc) "
                      "once the simulation is over. Please fix your on_exit() functions.");
@@ -823,9 +833,9 @@ void EngineImpl::run()
         maestro_->kill(kv.second);
       }
     }
-  } while (time > -1.0 || has_actors_to_run());
+  } while ((elapsed_time > -1.0 && not double_equals(max_date, NOW, 0.00001)) || has_actors_to_run());
 
-  if (not actor_list_.empty())
+  if (not actor_list_.empty() && max_date < 0)
     THROW_IMPOSSIBLE;
 
   simgrid::s4u::Engine::on_simulation_end();
@@ -840,5 +850,5 @@ double EngineImpl::get_clock()
 
 void SIMIX_run() // XBT_ATTRIB_DEPRECATED_v332
 {
-  simgrid::kernel::EngineImpl::get_instance()->run();
+  simgrid::kernel::EngineImpl::get_instance()->run(-1);
 }
index 3d34761..ba9ad2c 100644 (file)
@@ -202,8 +202,8 @@ public:
    */
   double solve(double max_date) const;
 
-  /** @brief Run the main simulation loop. */
-  void run();
+  /** @brief Run the main simulation loop until the specified date (or infinitly if max_date is negative). */
+  void run(double max_date);
 
   /** @brief Return the current time in milliseconds. */
   static double get_clock();
index f4531df..e824425 100644 (file)
@@ -316,6 +316,10 @@ std::vector<ActorPtr> Engine::get_filtered_actors(const std::function<bool(Actor
 }
 
 void Engine::run() const
+{
+  run_until(-1);
+}
+void Engine::run_until(double max_date) const
 {
   /* sealing resources before run: links */
   for (auto* link : get_all_links())
@@ -330,7 +334,7 @@ void Engine::run() const
   if (MC_is_active()) {
     MC_run();
   } else {
-    pimpl->run();
+    pimpl->run(max_date);
   }
 }
 
index c26d0cb..2a8d188 100644 (file)
@@ -578,7 +578,7 @@ int smpi_main(const char* executable, int argc, char* argv[])
   if (MC_is_active()) {
     MC_run();
   } else {
-    engine.get_impl()->run();
+    engine.get_impl()->run(-1);
 
     xbt_os_walltimer_stop(global_timer);
     simgrid::smpi::utils::print_time_analysis(xbt_os_timer_elapsed(global_timer));