Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Added some work in the creation of links in the fat trees, basically the repartion...
authorStéphane Castelli <stephane.castelli@loria.fr>
Tue, 15 Apr 2014 15:51:18 +0000 (17:51 +0200)
committerStéphane Castelli <stephane.castelli@loria.fr>
Tue, 15 Apr 2014 15:51:18 +0000 (17:51 +0200)
Method to generate a .dot file, almost done

Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid

1  2 
src/surf/surf_routing_cluster_fat_tree.cpp
src/surf/surf_routing_cluster_fat_tree.hpp

index 5cb6728,0000000..f852c36
mode 100644,000000..100644
--- /dev/null
@@@ -1,77 -1,0 +1,165 @@@
- AsClusterFatTree::AsClusterFatTree() : levels(0) {}
 +#include "surf_routing_cluster_fat_tree.hpp"
 +
 +#include <boost/algorithm/string/split.hpp>
 +#include <boost/algorithm/string/classification.hpp>
 +
++#include <iostream>
++#include <fstream>
 +
-                                           double *latency) {
 +
++AsClusterFatTree::AsClusterFatTree() : levels(0) {}
 +
++AsClusterFatTree::~AsClusterFatTree() {
++  for (int i = 0 ; i < this->nodes.size() ; i++) {
++    delete this->nodes[i];
++  }
++}
 +
 +void AsClusterFatTree::getRouteAndLatency(RoutingEdgePtr src,
 +                                          RoutingEdgePtr dst,
 +                                          sg_platf_route_cbarg_t into,
- void AsClusterFatTree::create_links() {
++                                          double *latency) const{
 +  // TODO
 +}
 +
-   
-   for (unsigned int i = 0 ; i < this->levels) {
-     
-   }
++/* This function makes the assumption that parse_specific_arguments() and
++ * addNodes() have already been called
++ */
++void AsClusterFatTree::create_links(sg_platf_cluster_cbarg_t cluster) {
++
 +  if(this->levels == 0) {
 +    return;
 +  }
-   
++  std::vector<int> nodesByLevel(this->levels); 
++  int nodesRequired = 0;
++
++
++    for (int i = 0 ; i < this->levels ; i++) {
++      int nodesInThisLevel = 1;
++      
++      for (int j = 0 ;  j < i ; j++) {
++        nodesInThisLevel *= this->upperLevelNodesNumber[j];
++      }
++      
++      for (int j = i+1 ; j < this->levels ; j++) {
++        nodesInThisLevel *= this->lowerLevelNodesNumber[j];
++      }
++
++      nodesByLevel[i] = nodesInThisLevel;
++      nodesRequired += nodesInThisLevel;
++    }
++   
++    if(nodesRequired > this->nodes.size()) {
++      surf_parse_error("There is not enough nodes to fit to the described topology. Please check your platform description (We need %d nodes, we only got %lu)", nodesRequired, this->nodes.size());
++      return;
++    }
++
++    // Nodes are totally ordered, by level and then by position, in this->nodes
++    int k = 0;
++    for (int i = 0 ; i < this->levels ; i++) {
++      for (int j = 0 ; j < nodesByLevel[i] ; j++) {
++        this->nodes[k]->level = i;
++        this->nodes[k]->position = j;
 +
++        if (i == 0) {
++          
++        }
++        else if (i == this->levels - 1) {
++          
++        }
++        else {
++          
++        }
++      }
++    }
 +}
 +
 +
++void AsClusterFatTree::addNodes(std::vector<int> const& id) {
++  for (int i = 0 ; i < id.size() ; i++) {
++    this->nodes.push_back(new FatTreeNode(id[i]));
++  }
++}
 +
 +void AsClusterFatTree::parse_specific_arguments(sg_platf_cluster_cbarg_t 
 +                                                cluster) {
 +  std::vector<string> parameters;
 +  std::vector<string> tmp;
 +  boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";"));
-   this->levels = std::atoi(tmp[0].c_str());
++ 
++
++  // TODO : we have to check for zeros and negative numbers, or it might crash
 +  if (parameters.size() != 4){
 +    surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
 +                     ", see the documentation for more informations");
 +    // Well, there's no doc, yet
 +  }
 +
 +  // The first parts of topo_parameters should be the levels number
-    boost::split(tmp, parameters[2], boost::is_any_of(","));
++  this->levels = std::atoi(tmp[0].c_str()); // stoi() only in C++11...
 +
 +  // Then, a l-sized vector standing for the childs number by level
 +  boost::split(tmp, parameters[1], boost::is_any_of(","));
 +  if(tmp.size() != this->levels) {
 +    surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
 +                     ", see the documentation for more informations"); 
 +  }
 +  for(unsigned int i = 0 ; i < tmp.size() ; i++){
 +    this->lowerLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
 +  }
 +  
 +  // Then, a l-sized vector standing for the parents number by level
++  boost::split(tmp, parameters[2], boost::is_any_of(","));
 +  if(tmp.size() != this->levels) {
 +    surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
 +                     ", see the documentation for more informations"); 
 +  }
 +  for(unsigned int i = 0 ; i < tmp.size() ; i++){
 +    this->upperLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
 +  }
 +  
 +  // Finally, a l-sized vector standing for the ports number with the lower level
 +  boost::split(tmp, parameters[3], boost::is_any_of(","));
 +  if(tmp.size() != this->levels) {
 +    surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
 +                     ", see the documentation for more informations"); 
 +    
 +  }
 +  for(unsigned int i = 0 ; i < tmp.size() ; i++){
 +    this->lowerLevelPortsNumber.push_back(std::atoi(tmp[i].c_str())); 
 +  }
 +}
++
++
++void AsClusterFatTree::generateDotFile(string filename) {
++  ofstream file;
++  /* Maybe should we get directly a char*, as open takes strings only beginning
++   * with c++11...
++   */
++  file.open(filename.c_str(), ios::out | ios::trunc); 
 +  
++  if(file.is_open()) {
++    /* TODO : Iterate through a map takes 10 chars with c++11, 100 with c++98.
++     * All I have to do is write it down...
++     */
++
++    // file << "graph AsClusterFatTree {\n";
++    // for (std::map<std::pair<int,int>, FatTreeLink*>::iterator link = this->links.begin() ; link != this->links.end() ; link++ ) {
++    //   for (int j = 0 ; j < link->ports ; j++) {
++    //   file << this->links[i]->source.id 
++    //        << " -- " this->links[i]->destination.id
++    //        << ";\n";
++    //   }
++    // }
++    // file << "}";
++    // file.close();
++  }
++  else {
++    std::cerr << "Unable to open file " << filename << std::endl;
++    return;
++  }
++}
++
++FatTreeNode::FatTreeNode(int id, int level, int position) : id(id),
++                                                            level(level),
++                                                            position(position){}
index d45cdbf,0000000..96ba5c9
mode 100644,000000..100644
--- /dev/null
@@@ -1,42 -1,0 +1,72 @@@
- class FatTreeLink;
- class FatTreeNode;
 +/* Copyright (c) 2014. The SimGrid Team.
 + * All rights reserved.                                                     */
 +
 +/* This program is free software; you can redistribute it and/or modify it
 + * under the terms of the license (GNU LGPL) which comes with this package. */
 +
 +#include "surf_routing_cluster.hpp"
 +
 +#ifndef SURF_ROUTING_CLUSTER_FAT_TREE_HPP_
 +#define SURF_ROUTING_CLUSTER_FAT_TREE_HPP_
 +
 +
++/* The class AsClusterFatTree describes PGFT, as introduced by Eitan Zahavi
++ * in "D-Mod-K Routing Providing Non-Blocking Traffic for Shift Permutations
++ * on Real Life Fat Trees" (2010). RLFT are PGFT with some restrictions to 
++ * address real world constraints, which are not currently enforced (but it 
++ * should certainly be checked for)
++ */
 +
-   virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
-   virtual void create_links();
++class FatTreeNode {
++public:
++  int id; // ID as given by the user
++  int level; // The 0th level represents the leafs of the PGFT
++  int position; // Position in the level
++  
++  /* We can see the sizes sum of the two following vectors as the device 
++   * ports number. If we use the notations used in Zahavi's paper, 
++   * children.size() = m_level and parents.size() = w_(level+1)
++   * 
++   */
++  std::vector<FatTreeNode*> children;  // m, apply from lvl 0 to levels - 1 
++  std::vector<FatTreeNode*> parents; // w, apply from lvl 1 to levels
++  FatTreeNode(int id, int level=-1, int position=-1);
++};
++
++class FatTreeLink {
++private:
++  unsigned int ports;
++  std::vector<NetworkLink> linksUp; // From source to destination
++  std::vector<NetworkLink> linksDown; // From destination to source
++  FatTreeNode source;
++  FatTreeNode destination;
++public:
++  FatTreeLink(int source, int destination, unsigned int ports = 0);
++  NetworkLink getLink(int number = 0) const;
++};
 +
 +class AsClusterFatTree : public AsCluster {
 +public:
 +  AsClusterFatTree();
-   std::vector<FatTreeNode> nodes;
++  ~AsClusterFatTree();
++  virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency) const;
++  virtual void create_links(sg_platf_cluster_cbarg_t cluster);
 +  void parse_specific_arguments(sg_platf_cluster_cbarg_t cluster);
++  void addNodes(std::vector<int> const& id);
++  void generateDotFile(string filename = "fatTree.dot");
 +
 +protected:
 +  //description of a PGFT (TODO : better doc)
 +  unsigned int levels;
 +  std::vector<int> lowerLevelNodesNumber;
 +  std::vector<int> upperLevelNodesNumber;
 +  std::vector<int> lowerLevelPortsNumber;
 +  
- class FatTreeLink {
- public:
- };
- class FatTreeNode {
-   int id;
-   std::string name;
- };
++  std::vector<FatTreeNode*> nodes;
++  std::map<std::pair<int,int>, FatTreeLink*> links;
++  
 +};
 +
++
 +  
 +#endif