Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e62076d7bd192d104032b6929561fd0bf13bf7d4
[simgrid.git] / src / mc / api / strategy / MinMatchComm.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_MINWAITTAKEN_HPP
7 #define SIMGRID_MC_MINWAITTAKEN_HPP
8
9 #include "src/mc/transition/TransitionComm.hpp"
10
11 namespace simgrid::mc {
12
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
17     
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;
26
27 public:
28   void copy_from(const Strategy* strategy) override
29   {
30       const MinMatchComm* cast_strategy = static_cast<MinMatchComm const*>(strategy);
31       xbt_assert(cast_strategy != nullptr);
32       for (auto& [id, val] : cast_strategy->mailbox_)
33           mailbox_[id] = val;
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_]++;
38
39       for (auto const& [_, val] : mailbox_) 
40           value_of_state -= std::abs(val);
41       if (value_of_state_ < 0)
42           value_of_state_ = 0;
43   }
44     MinMatchComm()                     = default;
45   ~MinMatchComm() override           = default;
46
47   std::pair<aid_t, int> next_transition() const override
48   {
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())
52         continue;
53
54       const Transition* transition = actor.get_transition(actor.get_times_considered());
55
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
60
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
65
66       if (if_no_match.first == -1)
67         if_no_match = std::make_pair(aid, value_of_state_);
68     }
69     return if_no_match;
70   }
71
72   void execute_next(aid_t aid, RemoteApp& app) override
73   {
74     const Transition* transition = actors_to_run_.at(aid).get_transition(actors_to_run_.at(aid).get_times_considered());
75     last_transition_             = transition->type_;
76
77     const CommRecvTransition* cast_recv = static_cast<CommRecvTransition const*>(transition);
78     if (cast_recv != nullptr)
79       last_mailbox_ = cast_recv->get_mailbox();
80
81     const CommSendTransition* cast_send = static_cast<CommSendTransition const*>(transition);
82     if (cast_send != nullptr)
83       last_mailbox_ = cast_send->get_mailbox();
84   }
85
86   void consider_best() override
87   {
88       for (auto& [aid, actor] : actors_to_run_)
89       if (actor.is_todo())
90         return;
91
92     for (auto& [aid, actor] : actors_to_run_) {
93       if (not actor.is_enabled() || actor.is_done())
94         continue;
95
96       const Transition* transition = actor.get_transition(actor.get_times_considered());
97
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) {
101         actor.mark_todo();
102         return;
103       }
104
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) {
108         actor.mark_todo();
109         return;
110       }
111     }
112     for (auto& [_, actor] : actors_to_run_) {
113       if (actor.is_enabled() and not actor.is_done()) {
114         actor.mark_todo();
115         return;
116       }
117     }
118   }
119 };
120
121 } // namespace simgrid::mc
122
123 #endif