Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fd3b68a08ee400b9eb5e7af956c618ca4cf614c9
[simgrid.git] / src / mc / api / strategy / MaxMatchComm.hpp
1 /* Copyright (c) 2007-2023. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #ifndef SIMGRID_MC_WAITSTRATEGY_HPP
7 #define SIMGRID_MC_WAITSTRATEGY_HPP
8
9 #include "src/mc/transition/TransitionComm.hpp"
10
11 namespace simgrid::mc {
12
13 /** Wait MC guiding class that aims at minimizing the number of in-fly communication.
14  *  When possible, it will try to match corresponding in-fly communications. */
15 class MaxMatchComm : public Strategy {
16
17   /** Stores for each mailbox what kind of transition is waiting on it.
18    *  Negative number means that much recv are waiting on that mailbox, while
19    *  a positiv number means that much send are waiting there. */
20   std::map<unsigned, int> mailbox_;
21     int value_of_state_ = 0; // used to valuate the state. Corresponds to the number of in-fly communications
22     // The two next values are used to save the operation we execute so the next strategy can update its field accordingly
23   Transition::Type last_transition_; 
24   unsigned last_mailbox_ = 0;
25
26 public:
27   void copy_from(const Strategy* strategy) override
28   {
29     const MaxMatchComm* cast_strategy = static_cast<MaxMatchComm const*>(strategy);
30     xbt_assert(cast_strategy != nullptr);
31     for (auto& [id, val] : cast_strategy->mailbox_)
32       mailbox_[id] = val;
33     if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_RECV)
34       mailbox_[cast_strategy->last_mailbox_]--;
35     if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_SEND)
36       mailbox_[cast_strategy->last_mailbox_]++;
37
38     for (auto const& [_, val] : mailbox_)
39         value_of_state += std::abs(val);
40   }
41   MaxMatchComm()                     = default;
42   ~MaxMatchComm() override           = default;
43
44   std::pair<aid_t, int> next_transition() const override
45   {
46     std::pair<aid_t, int> if_no_match = std::make_pair(-1, 0);
47     for (auto const& [aid, actor] : actors_to_run_) {
48       if (not actor.is_todo() || not actor.is_enabled() || actor.is_done())
49         continue;
50
51       const Transition* transition = actor.get_transition(actor.get_times_considered());
52
53       const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
54       if (cast_recv != nullptr and mailbox_.count(cast_recv->get_mailbox()) > 0 and
55           mailbox_.at(cast_recv->get_mailbox()) > 0)
56         return std::make_pair(aid, value_of_state_ - 1); // This means we have waiting send corresponding to this recv
57
58       const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
59       if (cast_send != nullptr and mailbox_.count(cast_send->get_mailbox()) > 0 and
60           mailbox_.at(cast_send->get_mailbox()) < 0)
61         return std::make_pair(aid, value_of_state_ - 1); // This means we have waiting recv corresponding to this send
62
63       if (if_no_match.first == -1)
64         if_no_match = std::make_pair(aid, value_of_state_);
65     }
66     return if_no_match;
67   }
68
69   void execute_next(aid_t aid, RemoteApp& app) override
70   {
71     const Transition* transition = actors_to_run_.at(aid).get_transition(actors_to_run_.at(aid).get_times_considered());
72     last_transition_             = transition->type_;
73
74     const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
75     if (cast_recv != nullptr)
76       last_mailbox_ = cast_recv->get_mailbox();
77
78     const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
79     if (cast_send != nullptr)
80       last_mailbox_ = cast_send->get_mailbox();
81   }
82
83   void consider_best() override
84   {
85     for (auto& [aid, actor] : actors_to_run_)
86       if (actor.is_todo())
87         return;
88
89     for (auto& [aid, actor] : actors_to_run_) {
90       if (not actor.is_enabled() || actor.is_done())
91         continue;
92
93       const Transition* transition = actor.get_transition(actor.get_times_considered());
94
95       const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
96       if (cast_recv != nullptr and mailbox_.count(cast_recv->get_mailbox()) > 0 and
97           mailbox_.at(cast_recv->get_mailbox()) > 0) {
98         actor.mark_todo();
99         return;
100       }
101
102       const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
103       if (cast_send != nullptr and mailbox_.count(cast_send->get_mailbox()) > 0 and
104           mailbox_.at(cast_send->get_mailbox()) < 0) {
105         actor.mark_todo();
106         return;
107       }
108     }
109     for (auto& [_, actor] : actors_to_run_) {
110       if (actor.is_enabled() and not actor.is_done()) {
111         actor.mark_todo();
112         return;
113       }
114     }
115   }
116 };
117
118 } // namespace simgrid::mc
119
120 #endif