Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
5057c98ba9a08e57b52a38ba19d65823aa6b68f8
[simgrid.git] / src / surf / surf_routing_cluster_fat_tree.cpp
1 #include "surf_routing_cluster_fat_tree.hpp"
2
3 #include <boost/algorithm/string/split.hpp>
4 #include <boost/algorithm/string/classification.hpp>
5
6 #include <iostream>
7 #include <fstream>
8
9
10 AsClusterFatTree::AsClusterFatTree() : levels(0) {}
11
12 AsClusterFatTree::~AsClusterFatTree() {
13   for (unsigned int i = 0 ; i < this->nodes.size() ; i++) {
14     delete this->nodes[i];
15   }
16 }
17
18 void AsClusterFatTree::getRouteAndLatency(RoutingEdgePtr src,
19                                           RoutingEdgePtr dst,
20                                           sg_platf_route_cbarg_t into,
21                                           double *latency) {
22   // TODO
23 }
24
25 /* This function makes the assumption that parse_specific_arguments() and
26  * addNodes() have already been called
27  */
28 void AsClusterFatTree::create_links(sg_platf_cluster_cbarg_t cluster) {
29
30   if(this->levels == 0) {
31     return;
32   }
33   this->nodesByLevel.resize(this->levels, 0);
34   unsigned int nodesRequired = 0;
35
36
37     for (unsigned int i = 0 ; i < this->levels ; i++) {
38       int nodesInThisLevel = 1;
39       
40       for (unsigned int j = 0 ;  j < i ; j++) {
41         nodesInThisLevel *= this->upperLevelNodesNumber[j];
42       }
43       
44       for (unsigned int j = i+1 ; j < this->levels ; j++) {
45         nodesInThisLevel *= this->lowerLevelNodesNumber[j];
46       }
47
48       this->nodesByLevel[i] = nodesInThisLevel;
49       nodesRequired += nodesInThisLevel;
50     }
51    
52     if(nodesRequired > this->nodes.size()) {
53       surf_parse_error("There is not enough nodes to fit to the described topology."
54                        " Please check your platform description (We need %d nodes, we only got %lu)",
55                        nodesRequired, this->nodes.size());
56       return;
57     }
58
59     // Nodes are totally ordered, by level and then by position, in this->nodes
60     int k = 0;
61     for (unsigned int i = 0 ; i < this->levels ; i++) {
62       for (unsigned int j = 0 ; j < this->nodesByLevel[i] ; j++) {
63         this->nodes[k]->level = i;
64         this->nodes[k]->position = j;
65       }
66     }
67     
68 }
69
70 void AsClusterFatTree::getLevelPosition(const unsigned  int level, int &position, int &size) {
71   if (level > this->levels - 1) {
72     position = -1;
73     size =  -1;
74     return;
75   }
76   int tempPosition = 0;
77
78   for (unsigned int i = 0 ; i < level ; i++) {
79     tempPosition += this->nodesByLevel[i];
80   }
81   position = tempPosition;
82   size = this->nodesByLevel[level];
83 }
84
85 void AsClusterFatTree::addNodes(std::vector<int> const& id) {
86   for (unsigned int  i = 0 ; i < id.size() ; i++) {
87     this->nodes.push_back(new FatTreeNode(id[i]));
88   }
89 }
90
91 void AsClusterFatTree::addLink(FatTreeNode *parent, FatTreeNode *child) {
92   using std::make_pair;
93   if (parent->children.size() == this->nodesByLevel[parent->level] ||
94       child->parents.size()   == this->nodesByLevel[child->level]) {
95     /* NB : This case should never happen, if this private function is not misused,
96      * so should we keep this test, keep it only for debug, throw an exception
97      * or get rid of it ? In all cases, anytime we get in there, code should be
98      * fixed
99      */
100     xbt_die("I've been asked to create a link that could not possibly exist");
101     return;
102   }
103
104   parent->children.push_back(child);
105   child->parents.push_back(parent);
106
107   // FatTreeLink *newLink;
108
109   // newLink = new FatTreeLink(parent, child, this->lowerLevelPortsNumber[parent->level]);
110   // this->links.insert(make_pair(make_pair(parent->id, child->id), newLink));
111
112   
113
114 }
115
116 void AsClusterFatTree::parse_specific_arguments(sg_platf_cluster_cbarg_t 
117                                                 cluster) {
118   std::vector<string> parameters;
119   std::vector<string> tmp;
120   boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";"));
121  
122
123   // TODO : we have to check for zeros and negative numbers, or it might crash
124   if (parameters.size() != 4){
125     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
126                      ", see the documentation for more informations");
127     // Well, there's no doc, yet
128   }
129
130   // The first parts of topo_parameters should be the levels number
131   this->levels = std::atoi(tmp[0].c_str()); // stoi() only in C++11...
132
133   // Then, a l-sized vector standing for the childs number by level
134   boost::split(tmp, parameters[1], boost::is_any_of(","));
135   if(tmp.size() != this->levels) {
136     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
137                      ", see the documentation for more informations"); 
138   }
139   for(unsigned int i = 0 ; i < tmp.size() ; i++){
140     this->lowerLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
141   }
142   
143   // Then, a l-sized vector standing for the parents number by level
144   boost::split(tmp, parameters[2], boost::is_any_of(","));
145   if(tmp.size() != this->levels) {
146     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
147                      ", see the documentation for more informations"); 
148   }
149   for(unsigned int i = 0 ; i < tmp.size() ; i++){
150     this->upperLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
151   }
152   
153   // Finally, a l-sized vector standing for the ports number with the lower level
154   boost::split(tmp, parameters[3], boost::is_any_of(","));
155   if(tmp.size() != this->levels) {
156     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
157                      ", see the documentation for more informations"); 
158     
159   }
160   for(unsigned int i = 0 ; i < tmp.size() ; i++){
161     this->lowerLevelPortsNumber.push_back(std::atoi(tmp[i].c_str())); 
162   }
163 }
164
165
166 void AsClusterFatTree::generateDotFile(const string& filename) const {
167   ofstream file;
168   /* Maybe should we get directly a char*, as open takes strings only beginning
169    * with C++11...
170    */
171   file.open(filename.c_str(), ios::out | ios::trunc); 
172   
173   if(file.is_open()) {
174     // That could also be greatly clarified with C++11
175     std::map<std::pair<int,int>,FatTreeLink*>::const_iterator iter;
176     file << "graph AsClusterFatTree {\n";
177     for (iter = this->links.begin() ; iter != this->links.end() ; iter++ ) {
178       for (unsigned int j = 0 ; j < iter->second->ports ; j++) {
179         file << iter->second->source->id
180              << " -- "
181              << iter->second->destination->id
182              << ";\n";
183       }
184     }
185     file << "}";
186     file.close();
187   }
188   else {
189     std::cerr << "Unable to open file " << filename << std::endl;
190     return;
191   }
192 }
193
194 FatTreeNode::FatTreeNode(int id, int level, int position) : id(id),
195                                                             level(level),
196                                                             position(position){}
197
198 // FatTreeLink::FatTreeLink(FatTreeNode *source, FatTreeNode *destination,
199 //                          int ports) : source(source), destination(destination),
200 //                                       ports(ports) {
201   
202 // }