Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into 'master'
[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   /**  Used to valuate the state. Corresponds to a maximum minus the number of in-fly communications.
23    *   Maximum should be set in order not to reach 0.*/
24   int value_of_state_ = _sg_mc_max_depth;
25     
26     // The two next values are used to save the operation we execute so the next strategy can update its field accordingly
27   Transition::Type last_transition_;
28   unsigned last_mailbox_ = 0;
29
30 public:
31   void copy_from(const Strategy* strategy) override
32   {
33       const MinMatchComm* cast_strategy = dynamic_cast<MinMatchComm const*>(strategy);
34       xbt_assert(cast_strategy != nullptr);
35       for (auto& [id, val] : cast_strategy->mailbox_)
36           mailbox_[id] = val;
37       if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_RECV)
38           mailbox_[cast_strategy->last_mailbox_]--;
39       if (cast_strategy->last_transition_ == Transition::Type::COMM_ASYNC_SEND)
40           mailbox_[cast_strategy->last_mailbox_]++;
41
42       for (auto const& [_, val] : mailbox_) 
43           value_of_state_ -= std::abs(val);
44       xbt_assert(value_of_state_ > 0, "MinMatchComm value shouldn't reach 0");
45   }
46     MinMatchComm()                     = default;
47   ~MinMatchComm() override           = default;
48
49  std::pair<aid_t, int> best_transition(bool must_be_todo) const override
50   {
51     std::pair<aid_t, int> min_found = std::make_pair(-1, value_of_state_+2);
52     for (auto const& [aid, actor] : actors_to_run_) {
53         if ((not actor.is_todo() && must_be_todo) || not actor.is_enabled() || actor.is_done())
54             continue;
55
56       int aid_value = value_of_state_;
57       const Transition* transition = actor.get_transition(actor.get_times_considered()).get();
58
59       const CommRecvTransition* cast_recv = dynamic_cast<CommRecvTransition const*>(transition);
60       if (cast_recv != nullptr) {
61           if ((mailbox_.count(cast_recv->get_mailbox()) > 0 and
62                mailbox_.at(cast_recv->get_mailbox()) <= 0) or mailbox_.count(cast_recv->get_mailbox()) == 0) 
63               aid_value--; // This means we don't have waiting recv corresponding to this recv
64           else 
65               aid_value++; 
66       }
67       const CommSendTransition* cast_send = dynamic_cast<CommSendTransition const*>(transition);
68       if (cast_send != nullptr) {
69           if ((mailbox_.count(cast_send->get_mailbox()) > 0 and
70                mailbox_.at(cast_send->get_mailbox()) >= 0) or mailbox_.count(cast_send->get_mailbox()) == 0)
71               aid_value--;
72           else
73               aid_value++;
74       }
75       
76       if (aid_value < min_found.second)
77           min_found = std::make_pair(aid, aid_value);
78     }
79     return min_found;
80   }
81
82     
83   void execute_next(aid_t aid, RemoteApp& app) override
84   {
85       const Transition* transition = actors_to_run_.at(aid).get_transition(actors_to_run_.at(aid).get_times_considered()).get();
86     last_transition_             = transition->type_;
87
88     const CommRecvTransition* cast_recv = dynamic_cast<CommRecvTransition const*>(transition);
89     if (cast_recv != nullptr)
90       last_mailbox_ = cast_recv->get_mailbox();
91
92     const CommSendTransition* cast_send = dynamic_cast<CommSendTransition const*>(transition);
93     if (cast_send != nullptr)
94       last_mailbox_ = cast_send->get_mailbox();
95   }
96
97 };
98
99 } // namespace simgrid::mc
100
101 #endif