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 {
18 /** Stores for each mailbox what kind of transition is waiting on it.
19 * Negative number means that much recv are waiting on that mailbox, while
20 * a positiv number means that much send are waiting there. */
21 std::map<unsigned, int> mailbox_;
22 int value_of_state_ = 100000; // used to valuate the state. Corresponds to the number of in-fly communications
23 // The two next values are used to save the operation we execute so the next strategy can update its field accordingly
24 Transition::Type last_transition_;
25 unsigned last_mailbox_ = 0;
28 void copy_from(const Strategy* strategy) override
30 const MinMatchComm* cast_strategy = static_cast<MinMatchComm const*>(strategy);
31 xbt_assert(cast_strategy != nullptr);
32 for (auto& [id, val] : cast_strategy->mailbox_)
34 if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_RECV)
35 mailbox_[cast_strategy->last_mailbox_]--;
36 if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_SEND)
37 mailbox_[cast_strategy->last_mailbox_]++;
39 for (auto const& [_, val] : mailbox_)
40 value_of_state -= std::abs(val);
41 if (value_of_state_ < 0)
44 MinMatchComm() = default;
45 ~MinMatchComm() override = default;
47 std::pair<aid_t, int> next_transition() const override
49 std::pair<aid_t, int> if_no_match = std::make_pair(-1, 0);
50 for (auto const& [aid, actor] : actors_to_run_) {
51 if (not actor.is_todo() || not actor.is_enabled() || actor.is_done())
54 const Transition* transition = actor.get_transition(actor.get_times_considered());
56 const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
57 if (cast_recv != nullptr and mailbox_.count(cast_recv->get_mailbox()) > 0 and
58 mailbox_.at(cast_recv->get_mailbox()) <= 0)
59 return std::make_pair(aid, value_of_state_ - 1); // This means we don't have waiting recv corresponding to this recv
61 const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
62 if (cast_send != nullptr and mailbox_.count(cast_send->get_mailbox()) > 0 and
63 mailbox_.at(cast_send->get_mailbox()) >= 0)
64 return std::make_pair(aid, value_of_state_ - 1); // This means we don't have waiting recv corresponding to this send
66 if (if_no_match.first == -1)
67 if_no_match = std::make_pair(aid, value_of_state_);
72 void execute_next(aid_t aid, RemoteApp& app) override
74 const Transition* transition = actors_to_run_.at(aid).get_transition(actors_to_run_.at(aid).get_times_considered());
75 last_transition_ = transition->type_;
77 const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
78 if (cast_recv != nullptr)
79 last_mailbox_ = cast_recv->get_mailbox();
81 const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
82 if (cast_send != nullptr)
83 last_mailbox_ = cast_send->get_mailbox();
86 void consider_best() override
88 for (auto& [aid, actor] : actors_to_run_)
92 for (auto& [aid, actor] : actors_to_run_) {
93 if (not actor.is_enabled() || actor.is_done())
96 const Transition* transition = actor.get_transition(actor.get_times_considered());
98 const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
99 if (cast_recv != nullptr and mailbox_.count(cast_recv->get_mailbox()) > 0 and
100 mailbox_.at(cast_recv->get_mailbox()) <= 0) {
105 const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
106 if (cast_send != nullptr and mailbox_.count(cast_send->get_mailbox()) > 0 and
107 mailbox_.at(cast_send->get_mailbox()) >= 0) {
112 for (auto& [_, actor] : actors_to_run_) {
113 if (actor.is_enabled() and not actor.is_done()) {
121 } // namespace simgrid::mc