1 /* Copyright (c) 2007-2023. 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. */
6 #ifndef SIMGRID_MC_MINWAITTAKEN_HPP
7 #define SIMGRID_MC_MINWAITTAKEN_HPP
9 #include "src/mc/transition/TransitionComm.hpp"
11 namespace simgrid::mc {
13 /** Wait MC guiding class that aims at maximizing the number of in-fly communication.
14 * When possible, it will try not to match communications. */
15 class MinMatchComm : public Strategy {
16 /** Stores for each mailbox what kind of transition is waiting on it.
17 * Negative number means that much recv are waiting on that mailbox, while
18 * a positiv number means that much send are waiting there. */
19 std::map<unsigned, int> mailbox_;
20 /** Used to valuate the state. Corresponds to a maximum minus the number of in-fly communications.
21 * Maximum should be set in order not to reach 0.*/
22 int value_of_state_ = _sg_mc_max_depth;
24 // The two next values are used to save the operation we execute so the next strategy can update its field accordingly
25 Transition::Type last_transition_;
26 unsigned last_mailbox_ = 0;
29 void copy_from(const Strategy* strategy) override
31 const auto* cast_strategy = dynamic_cast<MinMatchComm const*>(strategy);
32 xbt_assert(cast_strategy != nullptr);
33 for (auto& [id, val] : cast_strategy->mailbox_)
35 if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_RECV)
36 mailbox_[cast_strategy->last_mailbox_]--;
37 if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_SEND)
38 mailbox_[cast_strategy->last_mailbox_]++;
40 for (auto const& [_, val] : mailbox_)
41 value_of_state_ -= std::abs(val);
42 xbt_assert(value_of_state_ > 0, "MinMatchComm value shouldn't reach 0");
44 MinMatchComm() = default;
45 ~MinMatchComm() override = default;
47 std::pair<aid_t, int> best_transition(bool must_be_todo) const override
49 std::pair<aid_t, int> min_found = std::make_pair(-1, value_of_state_ + 2);
50 for (auto const& [aid, actor] : actors_to_run_) {
51 if ((not actor.is_todo() && must_be_todo) || not actor.is_enabled() || actor.is_done())
54 int aid_value = value_of_state_;
55 const Transition* transition = actor.get_transition(actor.get_times_considered()).get();
57 if (auto const* cast_recv = dynamic_cast<CommRecvTransition const*>(transition)) {
58 if ((mailbox_.count(cast_recv->get_mailbox()) > 0 && mailbox_.at(cast_recv->get_mailbox()) <= 0) ||
59 mailbox_.count(cast_recv->get_mailbox()) == 0)
60 aid_value--; // This means we don't have waiting recv corresponding to this recv
64 if (auto const* cast_send = dynamic_cast<CommSendTransition const*>(transition)) {
65 if ((mailbox_.count(cast_send->get_mailbox()) > 0 && mailbox_.at(cast_send->get_mailbox()) >= 0) ||
66 mailbox_.count(cast_send->get_mailbox()) == 0)
72 if (aid_value < min_found.second)
73 min_found = std::make_pair(aid, aid_value);
79 void execute_next(aid_t aid, RemoteApp& app) override
81 const Transition* transition = actors_to_run_.at(aid).get_transition(actors_to_run_.at(aid).get_times_considered()).get();
82 last_transition_ = transition->type_;
84 if (auto const* cast_recv = dynamic_cast<CommRecvTransition const*>(transition))
85 last_mailbox_ = cast_recv->get_mailbox();
87 if (auto const* cast_send = dynamic_cast<CommSendTransition const*>(transition))
88 last_mailbox_ = cast_send->get_mailbox();
92 } // namespace simgrid::mc