X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/8527dceda7ab2782503ea6cdbbe2ab26ca128535..HEAD:/src/smpi/mpi/smpi_topo.cpp diff --git a/src/smpi/mpi/smpi_topo.cpp b/src/smpi/mpi/smpi_topo.cpp index 82bfd74f33..48b723dc3c 100644 --- a/src/smpi/mpi/smpi_topo.cpp +++ b/src/smpi/mpi/smpi_topo.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2019. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2014-2023. 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. */ @@ -8,16 +8,21 @@ #include "smpi_comm.hpp" #include "smpi_topo.hpp" #include "xbt/sysdep.h" -#include + +#include #include /* static functions */ -static int assignnodes(int ndim, int nfactor, int *pfacts,int **pdims); -static int getfactors(int num, int *nfators, int **factors); +static int assignnodes(int ndim, const std::vector& factors, std::vector& dims); +static int getfactors(int num, std::vector& factors); +namespace simgrid::smpi { -namespace simgrid{ -namespace smpi{ +void Topo::setComm(MPI_Comm comm) +{ + xbt_assert(not comm_); + comm_ = comm; +} /******************************************************************************* * Cartesian topologies @@ -29,10 +34,9 @@ Topo_Cart::Topo_Cart(int ndims) : ndims_(ndims), dims_(ndims), periodic_(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*/ -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; - +Topo_Cart::Topo_Cart(MPI_Comm comm_old, int ndims, const int dims[], const int periods[], int /*reorder*/, MPI_Comm* comm_cart) + : Topo_Cart(ndims) +{ int rank = comm_old->rank(); if(ndims != 0) { @@ -41,14 +45,10 @@ Topo_Cart::Topo_Cart(MPI_Comm comm_old, int ndims, int dims[], int periods[], in newSize *= dims[i]; } if(rank >= newSize) { - *comm_cart = MPI_COMM_NULL; + if(comm_cart != nullptr) + *comm_cart = MPI_COMM_NULL; return; } - oldGroup = comm_old->group(); - newGroup = new Group(newSize); - for (int i = 0 ; i < newSize ; i++) { - newGroup->set_mapping(oldGroup->actor(i), i); - } nnodes_ = newSize; @@ -63,21 +63,33 @@ Topo_Cart::Topo_Cart(MPI_Comm comm_old, int ndims, int dims[], int periods[], in rank = rank % nranks; } - *comm_cart = new Comm(newGroup, this); + if(comm_cart != nullptr){ + const Group* oldGroup = comm_old->group(); + auto* newGroup = new Group(newSize); + for (int i = 0 ; i < newSize ; i++) { + newGroup->set_mapping(oldGroup->actor(i), i); + } + *comm_cart = new Comm(newGroup, std::shared_ptr(this)); + } } else { - if (rank == 0) { - *comm_cart = new Comm(new Group(MPI_COMM_SELF->group()), this); - } else { - *comm_cart = MPI_COMM_NULL; + if(comm_cart != nullptr){ + if (rank == 0) { + auto* group = new Group(MPI_COMM_SELF->group()); + *comm_cart = new Comm(group, std::shared_ptr(this)); + } else { + *comm_cart = MPI_COMM_NULL; + } } } - setComm(*comm_cart); + if(comm_cart != nullptr){ + setComm(*comm_cart); + } } Topo_Cart* Topo_Cart::sub(const int remain_dims[], MPI_Comm *newcomm) { int oldNDims = ndims_; - int *newDims = nullptr; - int *newPeriodic = nullptr; + std::vector newDims; + std::vector newPeriodic; if (remain_dims == nullptr && oldNDims != 0) { return nullptr; @@ -89,12 +101,12 @@ Topo_Cart* Topo_Cart::sub(const int remain_dims[], MPI_Comm *newcomm) { } if (newNDims > 0) { - newDims = new int[newNDims]; - newPeriodic = new int[newNDims]; + newDims.resize(newNDims); + newPeriodic.resize(newNDims); // that should not segfault int j = 0; - for (int i = 0 ; j < newNDims ; i++) { + for (int i = 0; i < oldNDims; i++) { if(remain_dims[i]) { newDims[j] =dims_[i]; newPeriodic[j] =periodic_[i]; @@ -102,13 +114,29 @@ Topo_Cart* Topo_Cart::sub(const int remain_dims[], MPI_Comm *newcomm) { } } } - Topo_Cart* res = new Topo_Cart(getComm(), newNDims, newDims, newPeriodic, 0, newcomm); - delete[] newDims; - delete[] newPeriodic; + + //split into several communicators + int color = 0; + for (int i = 0; i < oldNDims; i++) { + if (not remain_dims[i]) { + color = (color * dims_[i] + position_[i]); + } + } + Topo_Cart* res; + if (newNDims == 0){ + res = new Topo_Cart(getComm(), newNDims, newDims.data(), newPeriodic.data(), 0, newcomm); + } else { + *newcomm = getComm()->split(color, getComm()->rank()); + auto topo = std::make_shared(getComm(), newNDims, newDims.data(), newPeriodic.data(), 0, nullptr); + res = topo.get(); + res->setComm(*newcomm); + (*newcomm)->set_topo(topo); + } return res; } -int Topo_Cart::coords(int rank, int maxdims, int coords[]) { +int Topo_Cart::coords(int rank, int /*maxdims*/, int coords[]) +{ int nnodes = nnodes_; for (int i = 0; i< ndims_; i++ ) { nnodes = nnodes /dims_[i]; @@ -128,7 +156,7 @@ int Topo_Cart::get(int maxdims, int* dims, int* periods, int* coords) { return MPI_SUCCESS; } -int Topo_Cart::rank(int* coords, int* rank) { +int Topo_Cart::rank(const int* coords, int* rank) { int ndims =ndims_; *rank = 0; int multiplier = 1; @@ -164,10 +192,8 @@ int Topo_Cart::rank(int* coords, int* rank) { return MPI_SUCCESS; } -int Topo_Cart::shift(int direction, int disp, int *rank_source, int *rank_dest) { - - int position[ndims_]; - +int Topo_Cart::shift(int direction, int disp, int* rank_source, int* rank_dest) +{ if(ndims_ == 0) { return MPI_ERR_ARG; } @@ -175,37 +201,38 @@ int Topo_Cart::shift(int direction, int disp, int *rank_source, int *rank_dest) return MPI_ERR_DIMS; } - this->coords(getComm()->rank(), ndims_, position); + std::vector position(ndims_); + this->coords(getComm()->rank(), ndims_, position.data()); position[direction] += disp; if(position[direction] < 0 || position[direction] >=dims_[direction]) { if(periodic_[direction]) { position[direction] %=dims_[direction]; - this->rank(position, rank_dest); + this->rank(position.data(), rank_dest); } else { *rank_dest = MPI_PROC_NULL; } } else { - this->rank(position, rank_dest); + this->rank(position.data(), rank_dest); } 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); + this->rank(position.data(), rank_source); } else { *rank_source = MPI_PROC_NULL; } } else { - this->rank(position, rank_source); + this->rank(position.data(), rank_source); } - return MPI_SUCCESS; } -int Topo_Cart::dim_get(int *ndims) { +int Topo_Cart::dim_get(int* ndims) const +{ *ndims =ndims_; return MPI_SUCCESS; } @@ -241,17 +268,15 @@ 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; int freedims = 0; - int *p = dims; for (int i = 0; i < ndims; ++i) { - if (*p == 0) { + if (dims[i] == 0) { ++freedims; - } else if ((*p < 0) || ((nnodes % *p) != 0)) { + } else if ((dims[i] < 0) || ((nnodes % dims[i]) != 0)) { return MPI_ERR_DIMS; } else { - freeprocs /= *p; + freeprocs /= dims[i]; } - p++; } if (freedims == 0) { @@ -263,45 +288,38 @@ int Topo_Cart::Dims_create(int nnodes, int ndims, int dims[]) if (freeprocs == 1) { for (int i = 0; i < ndims; ++i) { - if (*dims == 0) { - *dims = 1; + if (dims[i] == 0) { + dims[i] = 1; } - dims++; } return MPI_SUCCESS; } /* Factor the number of free processes */ - int nfactors; - int *factors; - int err = getfactors(freeprocs, &nfactors, &factors); + std::vector factors; + int err = getfactors(freeprocs, factors); if (MPI_SUCCESS != err) return err; /* Assign free processes to free dimensions */ - int *procs; - err = assignnodes(freedims, nfactors, factors, &procs); + std::vector procs; + err = assignnodes(freedims, factors, procs); if (MPI_SUCCESS != err) return err; /* Return assignment results */ - p = procs; + auto p = procs.begin(); for (int i = 0; i < ndims; ++i) { - if (*dims == 0) { - *dims = *p++; + if (dims[i] == 0) { + dims[i] = *p++; } - dims++; } - delete[] factors; - delete[] procs; - /* all done */ return MPI_SUCCESS; } -} -} +} // namespace simgrid::smpi /* * assignnodes @@ -312,58 +330,29 @@ int Topo_Cart::Dims_create(int nnodes, int ndims, int dims[]) * - sort dimensions in decreasing order * - dimensions array dynamically allocated * Accepts: - # of dimensions - * - # of prime factors - * - array of prime factors - * - ptr to array of dimensions (returned value) + * - std::vector of prime factors + * - reference to std::vector of dimensions (returned value) * Returns: - 0 or ERROR */ -static int assignnodes(int ndim, int nfactor, int *pfacts, int **pdims) +static int assignnodes(int ndim, const std::vector& factors, std::vector& dims) { - int *pmin; - if (0 >= ndim) { return MPI_ERR_DIMS; } /* Allocate and initialize the bins */ - int *bins = new int[ndim]; + dims.clear(); + dims.resize(ndim, 1); - *pdims = bins; - int *p = bins; - - for (int i = 0 ; i < ndim; ++i) { - *p = 1; - p++; - } /* Loop assigning factors from the highest to the lowest */ - for (int j = nfactor - 1; j >= 0; --j) { - int f = pfacts[j]; + for (auto pfact = factors.crbegin(); pfact != factors.crend(); ++pfact) { /* Assign a factor to the smallest bin */ - pmin = bins; - p = pmin + 1; - for (int i = 1; i < ndim; ++i) { - if (*p < *pmin) { - pmin = p; - } - p++; - } - *pmin *= f; + auto pmin = std::min_element(dims.begin(), dims.end()); + *pmin *= *pfact; } - /* Sort dimensions in decreasing order (O(n^2) for now) */ - pmin = bins; - for (int i = 0; i < ndim - 1; ++i) { - p = pmin + 1; - for (int j = i + 1; j < ndim; ++j) { - if (*p > *pmin) { - int n = *p; - *p = *pmin; - *pmin = n; - } - p++; - } - pmin++; - } + /* Sort dimensions in decreasing order */ + std::sort(dims.begin(), dims.end(), std::greater<>()); return MPI_SUCCESS; } @@ -373,39 +362,33 @@ static int assignnodes(int ndim, int nfactor, int *pfacts, int **pdims) * * Function: - factorize a number * Accepts: - number - * - # prime factors - * - array of prime factors + * - reference to std::vector of prime factors * Returns: - MPI_SUCCESS or ERROR */ -static int getfactors(int num, int *nfactors, int **factors) { - if(num < 2) { - (*nfactors) = 0; - (*factors) = nullptr; +static int getfactors(int num, std::vector& factors) +{ + factors.clear(); + if (num < 2) { return MPI_SUCCESS; } - /* Allocate the array of prime factors which cannot exceed log_2(num) entries */ - int sqrtnum = ceil(sqrt(num)); - int size = ceil(log(num) / log(2)); - *factors = new int[size]; - int i = 0; /* determine all occurrences of factor 2 */ while((num % 2) == 0) { num /= 2; - (*factors)[i++] = 2; + factors.push_back(2); } /* determine all occurrences of uneven prime numbers up to sqrt(num) */ - for(int d = 3; (num > 1) && (d < sqrtnum); d += 2) { + int d = 3; + while ((num > 1) && (d * d < num)) { while((num % d) == 0) { num /= d; - (*factors)[i++] = d; + factors.push_back(d); } + d += 2; } /* as we looped only up to sqrt(num) one factor > sqrt(num) may be left over */ if(num != 1) { - (*factors)[i++] = num; + factors.push_back(num); } - (*nfactors) = i; return MPI_SUCCESS; } -