Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[simgrid.git] / src / smpi / smpi_topo.cpp
index fc77a2e..432174e 100644 (file)
-/* Copyright (c) 2014, 2017. The SimGrid Team.
- * All rights reserved.                                                     */
+/* Copyright (c) 2014-2017. 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 "xbt/sysdep.h"
 #include "smpi/smpi.h"
-#include "src/smpi/smpi_group.hpp"
 #include "private.h"
 #include <vector>
 #include <math.h>
+#include "src/smpi/smpi_comm.hpp"
+#include "src/smpi/smpi_topo.hpp"
 
-typedef struct s_smpi_mpi_cart_topology {
-  int nnodes;
-  int ndims;
-  int *dims;
-  int *periodic;
-  int *position;
-} s_smpi_mpi_cart_topology_t;
-
-typedef struct s_smpi_mpi_graph_topology {
-  int nnodes;
-  int nedges;
-  int *index;
-  int *edges;
-} s_smpi_mpi_graph_topology_t;
-
-typedef struct s_smpi_dist_graph_topology {
-  int indegree;
-  int *in;
-  int *in_weights;
-  int outdegree;
-  int *out;
-  int *out_weights;
-  int is_weighted;
-} s_smpi_mpi_dist_graph_topology_t;
-
-typedef struct s_smpi_mpi_topology { 
-  MPIR_Topo_type kind;
-  union topo {
-    MPIR_Graph_Topology graph;
-    MPIR_Cart_Topology  cart;
-    MPIR_Dist_Graph_Topology dist_graph;
-  } topo;
-} s_smpi_mpi_topology_t;
-
-void smpi_topo_destroy(MPI_Topology topo) {
-  if(topo == nullptr) {
-    return;
-  }
-  switch (topo->kind) {
-  case MPI_CART:
-    smpi_cart_topo_destroy(topo->topo.cart);
-    break;
-  case MPI_GRAPH:
-    // This topology is not supported by SMPI yet
-    smpi_graph_topo_destroy(topo->topo.graph);
-    break;
-  case MPI_DIST_GRAPH:
-    // This topology is not supported by SMPI yet
-     smpi_dist_graph_topo_destroy(topo->topo.dist_graph);
-    break;
-  default:
-    return;
-  }
-  xbt_free(topo);
-}
+/* static functions */
+static int assignnodes(int ndim, int nfactor, int *pfacts,int **pdims);
+static int getfactors(int num, int *nfators, int **factors);
 
-MPI_Topology smpi_topo_create(MPIR_Topo_type kind) {
-  MPI_Topology newTopo = static_cast<MPI_Topology>(xbt_malloc(sizeof(*newTopo)));
-  newTopo->kind = kind;
-  // Allocate and initialize the right topo should be done by the caller
-  return newTopo;
-}
 
-void smpi_graph_topo_destroy(MPIR_Graph_Topology graph) {
-  if (graph) {
-    delete[] graph->index;
-    delete[] graph->edges;
-    xbt_free(graph);
-  }
+namespace simgrid{
+namespace smpi{
+
+Topo_Graph::~Topo_Graph()
+{
+  delete[] index_;
+  delete[] edges_;
 }
 
-void smpi_dist_graph_topo_destroy(MPIR_Dist_Graph_Topology dist_graph) {
-  if (dist_graph) {
-    delete[] dist_graph->in;
-    delete[] dist_graph->in_weights;
-    delete[] dist_graph->out;
-    delete[] dist_graph->out_weights;
-    xbt_free(dist_graph);
-  }
+Topo_Dist_Graph::~Topo_Dist_Graph()
+{
+  delete[] in_;
+  delete[] in_weights_;
+  delete[] out_;
+  delete[] out_weights_;
 }
 
 /*******************************************************************************
  * Cartesian topologies
  ******************************************************************************/
-void smpi_cart_topo_destroy(MPIR_Cart_Topology cart) {
-  if (cart) {
-    delete[] cart->dims;
-    delete[] cart->periodic;
-    delete[] cart->position;
-    xbt_free(cart);
-  }
+Topo_Cart::~Topo_Cart()
+{
+  delete[] dims_;
+  delete[] periodic_;
+  delete[] position_;
 }
 
-MPI_Topology smpi_cart_topo_create(int ndims) {
-    MPI_Topology newTopo = smpi_topo_create(MPI_CART);
-    MPIR_Cart_Topology newCart = static_cast<MPIR_Cart_Topology>(xbt_malloc(sizeof(*newCart)));
-    newCart->nnodes = 0;
-    newCart->ndims = ndims;
-    newCart->dims = new int[ndims];
-    newCart->periodic = new int[ndims];
-    newCart->position = new int[ndims];
-    newTopo->topo.cart = newCart;
-    return newTopo;
+Topo_Cart::Topo_Cart(int ndims) : ndims_(ndims)
+{
+  dims_ = new int[ndims];
+  periodic_ = new int[ndims];
+  position_ = new int[ndims];
 }
 
 /* reorder is ignored, don't know what would be the consequences of a dumb reordering but neither do I see the point of
  * reordering*/
-int smpi_mpi_cart_create(MPI_Comm comm_old, int ndims, int dims[], int periods[], int reorder, MPI_Comm *comm_cart) {
-  int retval = MPI_SUCCESS;
-  MPI_Topology newCart;
+Topo_Cart::Topo_Cart(MPI_Comm comm_old, int ndims, int dims[], int periods[], int reorder, MPI_Comm *comm_cart) : Topo_Cart(ndims) {
   MPI_Group newGroup;
   MPI_Group oldGroup;
-  int nranks;
 
-  int rank = smpi_comm_rank(comm_old);
+  int rank = comm_old->rank();
 
-  int newSize = 1;
   if(ndims != 0) {
+    int newSize = 1;
     for (int i = 0 ; i < ndims ; i++) {
       newSize *= dims[i];
     }
     if(rank >= newSize) {
       *comm_cart = MPI_COMM_NULL;
-      return retval;
+      return;
     }
-    newCart = smpi_cart_topo_create(ndims);
-    oldGroup = smpi_comm_group(comm_old);
-    newGroup = new simgrid::SMPI::Group(newSize);
+    oldGroup = comm_old->group();
+    newGroup = new  Group(newSize);
     for (int i = 0 ; i < newSize ; i++) {
       newGroup->set_mapping(oldGroup->index(i), i);
     }
 
-    newCart->topo.cart->nnodes = newSize;
+    nnodes_ = newSize;
 
-    //  FIXME : code duplication... See smpi_mpi_cart_coords
-    nranks = newSize;
+    //  FIXME : code duplication... See coords
+    int nranks = newSize;
     for (int i=0; i<ndims; i++) {
-      newCart->topo.cart->dims[i] = dims[i];
-      newCart->topo.cart->periodic[i] = periods[i];
+      dims_[i] = dims[i];
+     periodic_[i] = periods[i];
       nranks = nranks / dims[i];
       /* FIXME: nranks could be zero (?) */
-      newCart->topo.cart->position[i] = rank / nranks;
+      position_[i] = rank / nranks;
       rank = rank % nranks;
     }
 
-    *comm_cart = smpi_comm_new(newGroup, newCart);
+    *comm_cart = new  Comm(newGroup, this);
   } else {
     if (rank == 0) {
-      newCart = smpi_cart_topo_create(ndims);
-      *comm_cart = smpi_comm_new(new simgrid::SMPI::Group(smpi_comm_group(MPI_COMM_SELF)), newCart);
+      *comm_cart = new  Comm(new  Group(MPI_COMM_SELF->group()), this);
     } else {
       *comm_cart = MPI_COMM_NULL;
     }
   }
-  return retval;
+  comm_=*comm_cart;
 }
 
-int smpi_mpi_cart_sub(MPI_Comm comm, const int remain_dims[], MPI_Comm *newcomm) {
-  MPI_Topology oldTopo = smpi_comm_topo(comm);
-  int oldNDims = oldTopo->topo.cart->ndims;
-  int j = 0;
+Topo_Cart* Topo_Cart::sub(const int remain_dims[], MPI_Comm *newcomm) {
+  int oldNDims = ndims_;
   int *newDims = nullptr;
   int *newPeriodic = nullptr;
 
   if (remain_dims == nullptr && oldNDims != 0) {
-    return MPI_ERR_ARG;
+    return nullptr;
   }
   int newNDims = 0;
   for (int i = 0 ; i < oldNDims ; i++) {
@@ -189,65 +116,62 @@ int smpi_mpi_cart_sub(MPI_Comm comm, const int remain_dims[], MPI_Comm *newcomm)
     newPeriodic = xbt_new(int, newNDims);
 
     // that should not segfault
+    int j = 0;
     for (int i = 0 ; j < newNDims ; i++) {
       if(remain_dims[i]) {
-        newDims[j] = oldTopo->topo.cart->dims[i];
-        newPeriodic[j] = oldTopo->topo.cart->periodic[i];
+        newDims[j] =dims_[i];
+        newPeriodic[j] =periodic_[i];
         j++;
       }
     }
   }
-  return smpi_mpi_cart_create(comm, newNDims, newDims, newPeriodic, 0, newcomm);
+  return new Topo_Cart(comm_, newNDims, newDims, newPeriodic, 0, newcomm);
 }
 
-int smpi_mpi_cart_coords(MPI_Comm comm, int rank, int maxdims, int coords[]) {
-  MPI_Topology topo = smpi_comm_topo(comm);
-  int nnodes = topo->topo.cart->nnodes;
-  for (int i = 0; i< topo->topo.cart->ndims; i++ ) {
-    nnodes    = nnodes / topo->topo.cart->dims[i];
+int Topo_Cart::coords(int rank, int maxdims, int coords[]) {
+  int nnodes = nnodes_;
+  for (int i = 0; i< ndims_; i++ ) {
+    nnodes    = nnodes /dims_[i];
     coords[i] = rank / nnodes;
     rank      = rank % nnodes;
   }
   return MPI_SUCCESS;
 }
 
-int smpi_mpi_cart_get(MPI_Comm comm, int maxdims, int* dims, int* periods, int* coords) {
-  MPI_Topology topo = smpi_comm_topo(comm);
-  int ndims=topo->topo.cart->ndims < maxdims ? topo->topo.cart->ndims : maxdims;
+int Topo_Cart::get(int maxdims, int* dims, int* periods, int* coords) {
+  int ndims=ndims_ < maxdims ?ndims_ : maxdims;
   for(int i = 0 ; i < ndims ; i++) {
-    dims[i] = topo->topo.cart->dims[i];
-    periods[i] = topo->topo.cart->periodic[i];
-    coords[i] = topo->topo.cart->position[i];
+    dims[i] =dims_[i];
+    periods[i] =periodic_[i];
+    coords[i] =position_[i];
   }
   return MPI_SUCCESS;
 }
 
-int smpi_mpi_cart_rank(MPI_Comm comm, int* coords, int* rank) {
-  MPI_Topology topo = smpi_comm_topo(comm);
-  int ndims = topo->topo.cart->ndims;
-  int coord;
+int Topo_Cart::rank(int* coords, int* rank) {
+  int ndims =ndims_;
   *rank = 0;
   int multiplier = 1;
 
   for (int i=ndims-1; i >=0; i-- ) {
-    coord = coords[i];
+    int coord = coords[i];
 
     /* The user can give us whatever coordinates he wants. If one of them is out of range, either this dimension is
      * periodic, and we consider the equivalent coordinate inside the bounds, or it's not and then it's an error
      */
-    if (coord >= topo->topo.cart->dims[i]) {
-      if ( topo->topo.cart->periodic[i] ) {
-        coord = coord % topo->topo.cart->dims[i];
+    if (coord >=dims_[i]) {
+      if (periodic_[i] ) {
+        coord = coord %dims_[i];
       } else {
         // Should I do that ?
         *rank = -1;
         return MPI_ERR_ARG;
       }
     } else if (coord <  0) {
-      if(topo->topo.cart->periodic[i]) {
-        coord = coord % topo->topo.cart->dims[i];
+      if(periodic_[i]) {
+        coord = coord %dims_[i];
         if (coord)
-          coord = topo->topo.cart->dims[i] + coord;
+          coord =dims_[i] + coord;
       } else {
         *rank = -1;
         return MPI_ERR_ARG;
@@ -255,56 +179,54 @@ int smpi_mpi_cart_rank(MPI_Comm comm, int* coords, int* rank) {
     }
 
     *rank += multiplier * coord;
-    multiplier *= topo->topo.cart->dims[i];
+    multiplier *=dims_[i];
   }
   return MPI_SUCCESS;
 }
 
-int smpi_mpi_cart_shift(MPI_Comm comm, int direction, int disp, int *rank_source, int *rank_dest) {
-  MPI_Topology topo = smpi_comm_topo(comm);
-  int position[topo->topo.cart->ndims];
+int Topo_Cart::shift(int direction, int disp, int *rank_source, int *rank_dest) {
 
-  if(topo->topo.cart->ndims == 0) {
+  int position[ndims_];
+
+  if(ndims_ == 0) {
     return MPI_ERR_ARG;
   }
-  if (topo->topo.cart->ndims < direction) {
+  if (ndims_ < direction) {
     return MPI_ERR_DIMS;
   }
 
-  smpi_mpi_cart_coords(comm, smpi_comm_rank(comm), topo->topo.cart->ndims, position);
+  this->coords(comm_->rank(),ndims_, position);
   position[direction] += disp;
 
   if(position[direction] < 0 ||
-      position[direction] >= topo->topo.cart->dims[direction]) {
-    if(topo->topo.cart->periodic[direction]) {
-      position[direction] %= topo->topo.cart->dims[direction];
-      smpi_mpi_cart_rank(comm, position, rank_dest);
+      position[direction] >=dims_[direction]) {
+    if(periodic_[direction]) {
+      position[direction] %=dims_[direction];
+      this->rank(position, rank_dest);
     } else {
       *rank_dest = MPI_PROC_NULL;
     }
   } else {
-    smpi_mpi_cart_rank(comm, position, rank_dest);
+    this->rank(position, rank_dest);
   }
 
-  position[direction] =  topo->topo.cart->position[direction] - disp;
-  if(position[direction] < 0 || position[direction] >= topo->topo.cart->dims[direction]) {
-    if(topo->topo.cart->periodic[direction]) {
-      position[direction] %= topo->topo.cart->dims[direction];
-      smpi_mpi_cart_rank(comm, position, rank_source);
+  position[direction] = position_[direction] - disp;
+  if(position[direction] < 0 || position[direction] >=dims_[direction]) {
+    if(periodic_[direction]) {
+      position[direction] %=dims_[direction];
+      this->rank(position, rank_source);
     } else {
       *rank_source = MPI_PROC_NULL;
     }
   } else {
-    smpi_mpi_cart_rank(comm, position, rank_source);
+    this->rank(position, rank_source);
   }
 
   return MPI_SUCCESS;
 }
 
-int smpi_mpi_cartdim_get(MPI_Comm comm, int *ndims) {
-  MPI_Topology topo = smpi_comm_topo(comm);
-
-  *ndims = topo->topo.cart->ndims;
+int Topo_Cart::dim_get(int *ndims) {
+  *ndims =ndims_;
   return MPI_SUCCESS;
 }
 
@@ -317,12 +239,12 @@ int smpi_mpi_cartdim_get(MPI_Comm comm, int *ndims) {
  * Copyright (c) 2004-2005 The University of Tennessee and The University
  *                         of Tennessee Research Foundation.  All rights
  *                         reserved.
- * Copyright (c) 2004-2014 High Performance Computing Center Stuttgart, 
+ * Copyright (c) 2004-2014 High Performance Computing Center Stuttgart,
  *                         University of Stuttgart.  All rights reserved.
  * Copyright (c) 2004-2005 The Regents of the University of California.
  *                         All rights reserved.
  * Copyright (c) 2012      Los Alamos National Security, LLC.  All rights
- *                         reserved. 
+ *                         reserved.
  * Copyright (c) 2014      Intel, Inc. All rights reserved
  * $COPYRIGHT$
  *
@@ -331,14 +253,10 @@ int smpi_mpi_cartdim_get(MPI_Comm comm, int *ndims) {
  * $HEADER$
  */
 
-/* static functions */
-static int assignnodes(int ndim, int nfactor, int *pfacts,int **pdims);
-static int getfactors(int num, int *nfators, int **factors);
-
 /*
  * This is a utility function, no need to have anything in the lower layer for this at all
  */
-int smpi_mpi_dims_create(int nnodes, int ndims, int dims[])
+int Topo_Cart::Dims_create(int nnodes, int ndims, int dims[])
 {
   /* Get # of free-to-be-assigned processes and # of free dimensions */
   int freeprocs = nnodes;
@@ -402,6 +320,9 @@ int smpi_mpi_dims_create(int nnodes, int ndims, int dims[])
   return MPI_SUCCESS;
 }
 
+}
+}
+
 /*
  *  assignnodes
  *
@@ -507,3 +428,4 @@ static int getfactors(int num, int *nfactors, int **factors) {
   (*nfactors) = i;
   return MPI_SUCCESS;
 }
+