Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fat trees progress
[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         if(i != 0) {
66           int position, size;
67           this->getLevelPosition(i - 1, &position, &size); // TODO : check position and size ?
68           for (unsigned int l = this->upperLevelNodesNumber[i] * j ;
69                l < this->upperLevelNodesNumber[i] * (j + 1) ; l++)
70             this->addLink(this->nodes[position + l], this->nodes[k]);
71         }
72         k++;
73       }
74     }
75     
76 }
77
78 void AsClusterFatTree::getLevelPosition(const unsigned  int level, int *position, int *size) {
79   if (level > this->levels - 1) {
80     *position = -1;
81     *size =  -1;
82     return;
83   }
84   int tempPosition = 0;
85
86   for (unsigned int i = 0 ; i < level ; i++) {
87     tempPosition += this->nodesByLevel[i];
88   }
89   *position = tempPosition;
90   *size = this->nodesByLevel[level];
91 }
92
93 void AsClusterFatTree::addNodes(std::vector<int> const& id) {
94   for (unsigned int  i = 0 ; i < id.size() ; i++) {
95     this->nodes.push_back(new FatTreeNode(id[i]));
96   }
97 }
98
99 void AsClusterFatTree::addLink(FatTreeNode *parent, FatTreeNode *child) {
100   using std::make_pair;
101   if (parent->children.size() == this->nodesByLevel[parent->level] ||
102       child->parents.size()   == this->nodesByLevel[child->level]) {
103     /* NB : This case should never happen, if this private function is not misused,
104      * so should we keep this test, keep it only for debug, throw an exception
105      * or get rid of it ? In all cases, anytime we get in there, code should be
106      * fixed
107      */
108     xbt_die("I've been asked to create a link that could not possibly exist");
109     return;
110   }
111
112   parent->children.push_back(child);
113   child->parents.push_back(parent);
114
115   // FatTreeLink *newLink;
116
117   // newLink = new FatTreeLink(parent, child, this->lowerLevelPortsNumber[parent->level]);
118   // this->links.insert(make_pair(make_pair(parent->id, child->id), newLink));
119
120   
121
122 }
123
124 void AsClusterFatTree::parse_specific_arguments(sg_platf_cluster_cbarg_t 
125                                                 cluster) {
126   std::vector<string> parameters;
127   std::vector<string> tmp;
128   boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";"));
129  
130
131   // TODO : we have to check for zeros and negative numbers, or it might crash
132   if (parameters.size() != 4){
133     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
134                      ", see the documentation for more informations");
135     // Well, there's no doc, yet
136   }
137
138   // The first parts of topo_parameters should be the levels number
139   this->levels = std::atoi(tmp[0].c_str()); // stoi() only in C++11...
140
141   // Then, a l-sized vector standing for the childs number by level
142   boost::split(tmp, parameters[1], boost::is_any_of(","));
143   if(tmp.size() != this->levels) {
144     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
145                      ", see the documentation for more informations"); 
146   }
147   for(unsigned int i = 0 ; i < tmp.size() ; i++){
148     this->lowerLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
149   }
150   
151   // Then, a l-sized vector standing for the parents number by level
152   boost::split(tmp, parameters[2], boost::is_any_of(","));
153   if(tmp.size() != this->levels) {
154     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
155                      ", see the documentation for more informations"); 
156   }
157   for(unsigned int i = 0 ; i < tmp.size() ; i++){
158     this->upperLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
159   }
160   
161   // Finally, a l-sized vector standing for the ports number with the lower level
162   boost::split(tmp, parameters[3], boost::is_any_of(","));
163   if(tmp.size() != this->levels) {
164     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
165                      ", see the documentation for more informations"); 
166     
167   }
168   for(unsigned int i = 0 ; i < tmp.size() ; i++){
169     this->lowerLevelPortsNumber.push_back(std::atoi(tmp[i].c_str())); 
170   }
171 }
172
173
174 void AsClusterFatTree::generateDotFile(const string& filename) const {
175   ofstream file;
176   /* Maybe should we get directly a char*, as open takes strings only beginning
177    * with C++11...
178    */
179   file.open(filename.c_str(), ios::out | ios::trunc); 
180   
181   if(file.is_open()) {
182     // That could also be greatly clarified with C++11
183     std::map<std::pair<int,int>,FatTreeLink*>::const_iterator iter;
184     file << "graph AsClusterFatTree {\n";
185     for (iter = this->links.begin() ; iter != this->links.end() ; iter++ ) {
186       for (unsigned int j = 0 ; j < iter->second->ports ; j++) {
187         file << iter->second->source->id
188              << " -- "
189              << iter->second->destination->id
190              << ";\n";
191       }
192     }
193     file << "}";
194     file.close();
195   }
196   else {
197     std::cerr << "Unable to open file " << filename << std::endl;
198     return;
199   }
200 }
201
202 FatTreeNode::FatTreeNode(int id, int level, int position) : id(id),
203                                                             level(level),
204                                                             position(position){}
205
206 // FatTreeLink::FatTreeLink(FatTreeNode *source, FatTreeNode *destination,
207 //                          int ports) : source(source), destination(destination),
208 //                                       ports(ports) {
209   
210 // }