From: Frederic Suter Date: Thu, 30 Jan 2020 10:06:01 +0000 (+0100) Subject: Merge branch 'master' into depencencies X-Git-Tag: v3.25~33^2^2~7 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/e87e7a6959f53286092e5c160dd865579601ba0e?hp=10b2c45a66b840a7a20b17071e476e1b9381a584 Merge branch 'master' into depencencies --- diff --git a/MANIFEST.in b/MANIFEST.in index fa9a8e1a37..0e36cdd94e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -370,6 +370,8 @@ include examples/s4u/exec-async/s4u-exec-async.cpp include examples/s4u/exec-async/s4u-exec-async.tesh include examples/s4u/exec-basic/s4u-exec-basic.cpp include examples/s4u/exec-basic/s4u-exec-basic.tesh +include examples/s4u/exec-dependent/s4u-exec-dependent.cpp +include examples/s4u/exec-dependent/s4u-exec-dependent.tesh include examples/s4u/exec-dvfs/s4u-exec-dvfs.cpp include examples/s4u/exec-dvfs/s4u-exec-dvfs.tesh include examples/s4u/exec-ptask/s4u-exec-ptask.cpp @@ -382,6 +384,8 @@ include examples/s4u/exec-waitfor/s4u-exec-waitfor.cpp include examples/s4u/exec-waitfor/s4u-exec-waitfor.tesh include examples/s4u/io-async/s4u-io-async.cpp include examples/s4u/io-async/s4u-io-async.tesh +include examples/s4u/io-dependent/s4u-io-dependent.cpp +include examples/s4u/io-dependent/s4u-io-dependent.tesh include examples/s4u/io-disk-raw/s4u-io-disk-raw.cpp include examples/s4u/io-disk-raw/s4u-io-disk-raw.tesh include examples/s4u/io-file-remote/s4u-io-file-remote.cpp diff --git a/examples/s4u/CMakeLists.txt b/examples/s4u/CMakeLists.txt index e3d0199380..0fb122df1d 100644 --- a/examples/s4u/CMakeLists.txt +++ b/examples/s4u/CMakeLists.txt @@ -9,8 +9,8 @@ foreach (example actor-create actor-daemon actor-exiting actor-join actor-kill cloud-capping cloud-migration cloud-simple energy-exec energy-boot energy-link energy-vm energy-exec-ptask engine-filtering - exec-async exec-basic exec-dvfs exec-ptask exec-remote exec-waitany exec-waitfor - io-async io-file-system io-file-remote io-disk-raw + exec-async exec-basic exec-dvfs exec-ptask exec-remote exec-waitany exec-waitfor exec-dependent + io-async io-file-system io-file-remote io-disk-raw io-dependent platform-failures platform-profile platform-properties plugin-hostload replay-comm replay-io diff --git a/examples/s4u/exec-dependent/s4u-exec-dependent.cpp b/examples/s4u/exec-dependent/s4u-exec-dependent.cpp new file mode 100644 index 0000000000..67b32b986f --- /dev/null +++ b/examples/s4u/exec-dependent/s4u-exec-dependent.cpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2007-2019. 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 + +XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "Messages specific for this s4u example"); + +static void worker() +{ + // Define an amount of work that should take 1 second to execute. + double computation_amount = simgrid::s4u::this_actor::get_host()->get_speed(); + + std::vector pending_execs; + // Create a small DAG + // + Two parents and a child + // + First parent ends after 1 second and the Second parent after 2 seconds. + simgrid::s4u::ExecPtr first_parent = simgrid::s4u::this_actor::exec_init(computation_amount); + pending_execs.push_back(first_parent); + simgrid::s4u::ExecPtr second_parent = simgrid::s4u::this_actor::exec_init(2 * computation_amount); + pending_execs.push_back(second_parent); + simgrid::s4u::ExecPtr child = simgrid::s4u::this_actor::exec_init(computation_amount); + pending_execs.push_back(child); + + // Name the activities (for logging purposes only) + first_parent->set_name("parent 1"); + second_parent->set_name("parent 2"); + child->set_name("child"); + + // Create the dependencies by declaring 'child' as a successor of first_parent and second_parent + first_parent->add_successor(child.get()); + second_parent->add_successor(child.get()); + + // Start the activities. + first_parent->start(); + second_parent->start(); + // child uses a vetoable start to force it to wait for the completion of its predecessors + child->vetoable_start(); + + // wait for the completion of all activities + while (not pending_execs.empty()) { + int changed_pos = simgrid::s4u::Exec::wait_any_for(&pending_execs, -1); + XBT_INFO("Exec '%s' is complete", pending_execs[changed_pos]->get_cname()); + pending_execs.erase(pending_execs.begin() + changed_pos); + } +} + +int main(int argc, char* argv[]) +{ + simgrid::s4u::Engine e(&argc, argv); + e.load_platform(argv[1]); + + simgrid::s4u::Actor::create("worker", simgrid::s4u::Host::by_name("Fafard"), worker); + + e.run(); + + XBT_INFO("Simulation time %g", e.get_clock()); + + return 0; +} diff --git a/examples/s4u/exec-dependent/s4u-exec-dependent.tesh b/examples/s4u/exec-dependent/s4u-exec-dependent.tesh new file mode 100644 index 0000000000..dab01ae3df --- /dev/null +++ b/examples/s4u/exec-dependent/s4u-exec-dependent.tesh @@ -0,0 +1,11 @@ +#!/usr/bin/env tesh + +! output sort +$ ${bindir:=.}/s4u-exec-dependent ${platfdir}/small_platform.xml --log=s4u_activity.t:debug "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" +> [ 2.000000] (1:worker@Fafard) Remove a dependency from 'parent 1' on 'child' +> [ 2.000000] (1:worker@Fafard) Exec 'parent 1' is complete +> [ 3.000000] (1:worker@Fafard) Remove a dependency from 'parent 2' on 'child' +> [ 3.000000] (1:worker@Fafard) All dependencies are solved, let's start 'child' +> [ 3.000000] (1:worker@Fafard) Exec 'parent 2' is complete +> [ 4.000000] (1:worker@Fafard) Exec 'child' is complete +> [ 4.000000] (0:maestro@) Simulation time 4 diff --git a/examples/s4u/io-dependent/s4u-io-dependent.cpp b/examples/s4u/io-dependent/s4u-io-dependent.cpp new file mode 100644 index 0000000000..ba182261b4 --- /dev/null +++ b/examples/s4u/io-dependent/s4u-io-dependent.cpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2007-2019. 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 +#include + +XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "Messages specific for this s4u example"); + +static void test() +{ + simgrid::s4u::ExecPtr bob_compute = simgrid::s4u::this_actor::exec_init(1e9); + simgrid::s4u::IoPtr bob_write = + simgrid::s4u::Host::current()->get_disks().front()->io_init(4000000, simgrid::s4u::Io::OpType::WRITE); + simgrid::s4u::IoPtr carl_read = + simgrid::s4u::Host::by_name("carl")->get_disks().front()->io_init(4000000, simgrid::s4u::Io::OpType::READ); + simgrid::s4u::ExecPtr carl_compute = simgrid::s4u::Host::by_name("carl")->exec_async(1e9); + + // Name the activities (for logging purposes only) + bob_compute->set_name("bob compute"); + bob_write->set_name("bob write"); + carl_read->set_name("carl read"); + carl_compute->set_name("carl compute"); + + // Create the dependencies: + // 'bob_write' is a successor of 'bob_compute' + // 'carl_read' is a successor of 'bob_write' + // 'carl_compute' is a successor of 'carl_read' + bob_compute->add_successor(bob_write.get()); + bob_write->add_successor(carl_read.get()); + carl_read->add_successor(carl_compute.get()); + + // Start the activities. + bob_compute->start(); + bob_write->vetoable_start(); + carl_read->vetoable_start(); + carl_compute->vetoable_start(); + + // Wait for their completion (should be replaced by a wait_any_for at some point) + bob_compute->wait(); + bob_write->wait(); + carl_read->wait(); + carl_compute->wait(); +} + +int main(int argc, char* argv[]) +{ + simgrid::s4u::Engine e(&argc, argv); + sg_storage_file_system_init(); + e.load_platform(argv[1]); + + simgrid::s4u::Actor::create("bob", simgrid::s4u::Host::by_name("bob"), test); + + e.run(); + + XBT_INFO("Simulation time %g", e.get_clock()); + + return 0; +} diff --git a/examples/s4u/io-dependent/s4u-io-dependent.tesh b/examples/s4u/io-dependent/s4u-io-dependent.tesh new file mode 100644 index 0000000000..26fb3b3c52 --- /dev/null +++ b/examples/s4u/io-dependent/s4u-io-dependent.tesh @@ -0,0 +1,11 @@ +#!/usr/bin/env tesh + +! output sort +$ ${bindir:=.}/s4u-io-dependent ${platfdir}/hosts_with_disks.xml --log=s4u_activity.t:debug "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" +> [ 1.000000] (1:bob@bob) All dependencies are solved, let's start 'bob write' +> [ 1.000000] (1:bob@bob) Remove a dependency from 'bob compute' on 'bob write' +> [ 1.100000] (1:bob@bob) All dependencies are solved, let's start 'carl read' +> [ 1.100000] (1:bob@bob) Remove a dependency from 'bob write' on 'carl read' +> [ 1.166667] (1:bob@bob) All dependencies are solved, let's start 'carl compute' +> [ 1.166667] (1:bob@bob) Remove a dependency from 'carl read' on 'carl compute' +> [ 2.166667] (0:maestro@) Simulation time 2.16667 diff --git a/include/simgrid/s4u/Activity.hpp b/include/simgrid/s4u/Activity.hpp index fb07a248ba..67fe59beeb 100644 --- a/include/simgrid/s4u/Activity.hpp +++ b/include/simgrid/s4u/Activity.hpp @@ -8,10 +8,14 @@ #include "xbt/asserts.h" #include +#include #include #include +#include #include +XBT_LOG_EXTERNAL_CATEGORY(s4u_activity); + namespace simgrid { namespace s4u { @@ -30,14 +34,13 @@ class XBT_PUBLIC Activity { protected: Activity() = default; virtual ~Activity() = default; - public: #ifndef DOXYGEN Activity(Activity const&) = delete; Activity& operator=(Activity const&) = delete; #endif - enum class State { INITED = 0, STARTED, CANCELED, ERRORED, FINISHED }; + enum class State { INITED = 0, STARTING, STARTED, CANCELED, ERRORED, FINISHED }; /** Starts a previously created activity. * @@ -57,6 +60,7 @@ public: virtual Activity* cancel() = 0; /** Retrieve the current state of the activity */ Activity::State get_state() { return state_; } + void set_state(Activity::State state) { state_ = state; } /** Tests whether the given activity is terminated yet. This is a pure function. */ virtual bool test() = 0; @@ -90,11 +94,52 @@ private: template class Activity_T : public Activity { private: - std::string name_ = ""; + std::string name_ = "unnamed"; std::string tracing_category_ = ""; void* user_data_ = nullptr; + std::vector successors_; + std::set dependencies_; public: + + void add_successor(Activity* a) + { + successors_.push_back(a); + static_cast(a)->add_dependency_on(static_cast(this)); + } + void remove_successor() { successors_.pop_back(); } + Activity* get_successor() { return successors_.back(); } + bool has_successors() { return not successors_.empty(); } + + void add_dependency_on(Activity* a) { dependencies_.insert({a}); } + void remove_dependency_on(Activity* a) { dependencies_.erase(a); } + bool has_dependencies() { return not dependencies_.empty(); } + void release_dependencies() + { + while (has_successors()) { + AnyActivity* b = static_cast(get_successor()); + XBT_CDEBUG(s4u_activity, "Remove a dependency from '%s' on '%s'", static_cast(this)->get_cname(), + b->get_cname()); + b->remove_dependency_on(static_cast(this)); + if (not b->has_dependencies()) { + b->vetoable_start(); + } + remove_successor(); + } + } + + AnyActivity* vetoable_start() + { + set_state(State::STARTING); + if (has_dependencies()) + return static_cast(this); + set_state(State::STARTED); + XBT_CDEBUG(s4u_activity, "All dependencies are solved, let's start '%s'", + static_cast(this)->get_cname()); + static_cast(this)->start(); + return static_cast(this); + } + AnyActivity* set_name(const std::string& name) { xbt_assert(get_state() == State::INITED, "Cannot change the name of an activity after its start"); diff --git a/src/kernel/activity/IoImpl.cpp b/src/kernel/activity/IoImpl.cpp index ce4254f7f8..8125e0e595 100644 --- a/src/kernel/activity/IoImpl.cpp +++ b/src/kernel/activity/IoImpl.cpp @@ -34,6 +34,7 @@ void simcall_HANDLER_io_wait(smx_simcall_t simcall, simgrid::kernel::activity::I synchro->state_ = simgrid::kernel::activity::State::TIMEOUT; } synchro->finish(); + return; } /* If the synchro is already finished then perform the error handling */ diff --git a/src/s4u/s4u_Exec.cpp b/src/s4u/s4u_Exec.cpp index 0aca559de4..a0d3cc5302 100644 --- a/src/s4u/s4u_Exec.cpp +++ b/src/s4u/s4u_Exec.cpp @@ -22,16 +22,18 @@ Exec::Exec() bool Exec::test() { - xbt_assert(state_ == State::INITED || state_ == State::STARTED || state_ == State::FINISHED); + xbt_assert(state_ == State::INITED || state_ == State::STARTED || state_ == State::STARTING || + state_ == State::FINISHED); if (state_ == State::FINISHED) return true; - if (state_ == State::INITED) - this->start(); + if (state_ == State::INITED || state_ == State::STARTING) + this->vetoable_start(); if (simcall_execution_test(pimpl_)) { state_ = State::FINISHED; + this->release_dependencies(); return true; } @@ -46,10 +48,11 @@ Exec* Exec::wait() Exec* Exec::wait_for(double timeout) { if (state_ == State::INITED) - start(); + vetoable_start(); simcall_execution_wait(pimpl_, timeout); state_ = State::FINISHED; on_completion(*Actor::self(), *this); + this->release_dependencies(); return this; } @@ -58,7 +61,11 @@ int Exec::wait_any_for(std::vector* execs, double timeout) std::unique_ptr rexecs(new kernel::activity::ExecImpl*[execs->size()]); std::transform(begin(*execs), end(*execs), rexecs.get(), [](const ExecPtr& exec) { return static_cast(exec->pimpl_.get()); }); - return simcall_execution_waitany_for(rexecs.get(), execs->size(), timeout); + + int changed_pos = simcall_execution_waitany_for(rexecs.get(), execs->size(), timeout); + if (changed_pos != -1) + execs->at(changed_pos)->release_dependencies(); + return changed_pos; } Exec* Exec::cancel() diff --git a/src/s4u/s4u_Io.cpp b/src/s4u/s4u_Io.cpp index 9b363ce0d1..73149eb614 100644 --- a/src/s4u/s4u_Io.cpp +++ b/src/s4u/s4u_Io.cpp @@ -61,23 +61,28 @@ Io* Io::wait() Io* Io::wait_for(double timeout) { + if (state_ == State::INITED) + vetoable_start(); simcall_io_wait(pimpl_, timeout); state_ = State::FINISHED; + this->release_dependencies(); return this; } bool Io::test() { - xbt_assert(state_ == State::INITED || state_ == State::STARTED || state_ == State::FINISHED); + xbt_assert(state_ == State::INITED || state_ == State::STARTED || state_ == State::STARTING || + state_ == State::FINISHED); if (state_ == State::FINISHED) return true; - if (state_ == State::INITED) - this->start(); + if (state_ == State::INITED || state_ == State::STARTING) + this->vetoable_start(); if (simcall_io_test(pimpl_)) { state_ = State::FINISHED; + this->release_dependencies(); return true; }