Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
New: s4u::create_fatTree_zone
[simgrid.git] / include / simgrid / kernel / routing / FatTreeZone.hpp
1 /* Copyright (c) 2014-2021. 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_ROUTING_CLUSTER_FAT_TREE_HPP_
7 #define SIMGRID_ROUTING_CLUSTER_FAT_TREE_HPP_
8
9 #include <simgrid/kernel/routing/ClusterZone.hpp>
10
11 namespace simgrid {
12 namespace kernel {
13 namespace routing {
14
15 class XBT_PRIVATE FatTreeLink;
16
17 /** @brief A node in a fat tree (@ref FatTreeZone).
18  * A FatTreeNode can either be a switch or a processing node. Switches are
19  * identified by a negative ID. This class is closely related to fat
20  */
21 class XBT_PRIVATE FatTreeNode {
22 public:
23   /** Unique ID which identifies every node. */
24   int id;
25   /* Level into the tree, with 0 being the leafs.
26    */
27   unsigned int level;
28   /* @brief Position into the level, starting from 0.
29    */
30   unsigned int position;
31   /** In order to link nodes between them, each one must be assigned a label,
32    * consisting of l integers, l being the levels number of the tree. Each label
33    * is unique in the level, and the way it is generated allows the construction
34    * of a fat tree which fits the desired topology.
35    */
36   std::vector<unsigned int> label;
37
38   /** Links to the lower level, where the position in the vector corresponds to
39    * a port number.
40    */
41   std::vector<FatTreeLink*> children;
42   /** Links to the upper level, where the position in the vector corresponds to
43    * a port number.
44    */
45   std::vector<FatTreeLink*> parents;
46
47   /** Virtual link standing for the node global capacity.
48    */
49   resource::LinkImpl* limiter_link_;
50   /** If present, communications from this node to this node will pass through it
51    * instead of passing by an upper level switch.
52    */
53   resource::LinkImpl* loopback_;
54   FatTreeNode(int id, int level, int position, resource::LinkImpl* limiter, resource::LinkImpl* loopback)
55       : id(id), level(level), position(position), limiter_link_(limiter), loopback_(loopback)
56   {
57   }
58 };
59
60 /** @brief Link in a fat tree (@ref FatTreeZone).
61  *
62  * Represents a single, duplex link in a fat tree. This is necessary to have a tree.
63  * It is equivalent to a physical link.
64  */
65 class FatTreeLink {
66 public:
67   FatTreeLink(FatTreeNode* src, FatTreeNode* dst, resource::LinkImpl* linkup, resource::LinkImpl* linkdown)
68       : up_node_(dst), down_node_(src), up_link_(linkup), down_link_(linkdown)
69   {
70   }
71   /** Upper end of the link */
72   FatTreeNode* up_node_;
73   /** Lower end of the link */
74   FatTreeNode* down_node_;
75   /** Link going up in the tree */
76   resource::LinkImpl* up_link_;
77   /** Link going down in the tree */
78   resource::LinkImpl* down_link_;
79 };
80
81 /** @ingroup ROUTING_API
82  * @brief NetZone using a Fat-Tree topology
83  *
84  * Generate fat trees according to the topology asked for, according to:
85  * Eitan Zahavi, D-Mod-K Routing Providing Non-Blocking Traffic for Shift
86  * Permutations on Real Life Fat Trees (2010).
87  *
88  * RLFT are PGFT with some restrictions to address real world constraints,
89  * which are not currently enforced.
90  *
91  * The exact topology is described in the mandatory topo_parameters
92  * field, and follow the "h ; m_1, ..., m_h ; w_1, ..., w_h ; p_1, ..., p_h" format.
93  * h stands for the switches levels number, i.e. the fat tree is of height h,
94  * without the processing nodes. m_i stands for the number of lower level nodes
95  * connected to a node in level i. w_i stands for the number of upper levels
96  * nodes connected to a node in level i-1. p_i stands for the number of
97  * parallel links connecting two nodes between level i and i - 1. Level h is
98  * the topmost switch level, level 1 is the lowest switch level, and level 0
99  * represents the processing nodes. The number of provided nodes must be exactly
100  * the number of processing nodes required to fit the topology, which is the
101  * product of the m_i's.
102  *
103  * Routing is made using a destination-mod-k scheme.
104  */
105 class XBT_PRIVATE FatTreeZone : public ClusterZone {
106   /** @brief Generate the fat tree
107    *
108    * Once all processing nodes have been added, this will make sure the fat
109    * tree is generated by calling generateLabels(), generateSwitches() and
110    * then connection all nodes between them, using their label.
111    */
112   // description of a PGFT (TODO : better doc)
113   unsigned long levels_ = 0;
114   std::vector<unsigned int> num_children_per_node_; // number of children by node
115   std::vector<unsigned int> num_parents_per_node_;  // number of parents by node
116   std::vector<unsigned int> num_port_lower_level_;  // ports between each level l and l-1
117
118   std::map<int, FatTreeNode*> compute_nodes_;
119   std::vector<FatTreeNode*> nodes_;
120   std::vector<FatTreeLink*> links_;
121   std::vector<unsigned int> nodes_by_level_;
122
123   s4u::Link::SharingPolicy link_sharing_policy_; //!< fat tree links: sharing policy
124   double link_bw_;                               //!< fat tree links: bandwidth
125   double link_lat_;                              //!< fat tree links: latency
126
127   void add_link(FatTreeNode* parent, unsigned int parent_port, FatTreeNode* child, unsigned int child_port);
128   int get_level_position(const unsigned int level);
129   void generate_labels();
130   void generate_switches();
131   int connect_node_to_parents(FatTreeNode* node);
132   bool are_related(FatTreeNode* parent, FatTreeNode* child) const;
133   bool is_in_sub_tree(FatTreeNode* root, FatTreeNode* node) const;
134
135   void do_seal() override;
136
137 public:
138   using ClusterZone::ClusterZone;
139   FatTreeZone(const FatTreeZone&) = delete;
140   FatTreeZone& operator=(const FatTreeZone&) = delete;
141   ~FatTreeZone() override;
142   void get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* into, double* latency) override;
143
144   /** @brief Read the parameters in topo_parameters field. */
145   void parse_specific_arguments(ClusterCreationArgs* cluster) override;
146   /** @brief Checks topology parameters */
147   static void check_topology(unsigned int n_levels, const std::vector<unsigned int>& down_links,
148                              const std::vector<unsigned int>& up_links, const std::vector<unsigned int>& link_count);
149   /** @brief Set FatTree topology */
150   void set_topology(unsigned int n_levels, const std::vector<unsigned int>& down_links,
151                     const std::vector<unsigned int>& up_links, const std::vector<unsigned int>& link_count);
152   /** @brief Set the characteristics of links inside the Fat Tree zone */
153   void set_link_characteristics(double bw, double lat, s4u::Link::SharingPolicy sharing_policy);
154   void add_processing_node(int id, resource::LinkImpl* limiter, resource::LinkImpl* loopback);
155   void generate_dot_file(const std::string& filename = "fat_tree.dot") const;
156 };
157 } // namespace routing
158 } // namespace kernel
159 } // namespace simgrid
160
161 #endif