Page MenuHomec4science

lm_communicator.cc
No OneTemporary

File Metadata

Created
Thu, Jul 11, 14:16

lm_communicator.cc

/**
* @file communicator.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Fri Mar 08 09:36:00 2013
*
* @brief Mother class of LM communicators
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but
* WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "lm_communicator.hh"
#include "comm_group.hh"
#include "id_manager.hh"
#include "lm_common.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
template <>
std::unique_ptr<IDManager<CommGroup>> IDManager<CommGroup>::static_pointer =
nullptr;
/* -------------------------------------------------------------------------- */
Communicator &Communicator::getCommunicator() {
if (!static_pointer)
createCommunicator();
Communicator &ref = dynamic_cast<Communicator &>(*static_pointer);
return ref;
}
/* -------------------------------------------------------------------------- */
void Communicator::createCommunicator() {
Communicator::getManager<Communicator>();
}
/* -------------------------------------------------------------------------- */
void Communicator::reset() {
IDManager<CommGroup>::reset();
auto new_group = std::make_shared<AllGroup>();
this->addObject(new_group);
auto self_group = std::make_shared<SelfGroup>();
this->addObject(self_group);
}
/* -------------------------------------------------------------------------- */
void Communicator::addGroup(const LMID &id, UInt nb_procs) {
auto free_procs = this->getNumberFreeProcs();
if (free_procs < nb_procs) {
LM_FATAL(
"group "
<< id << " While trying to add " << nb_procs
<< " procs: There are not enough processors for the required topology!"
<< "(only " << free_procs << " are available)");
}
DUMP("free_procs " << free_procs, DBG_INFO);
DUMP("nb_procs " << nb_procs, DBG_INFO);
int color;
if (lm_my_proc_id < free_procs && lm_my_proc_id >= free_procs - nb_procs)
color = 0;
else
color = MPI_UNDEFINED;
DUMP("my color " << color, DBG_INFO);
auto new_group = std::make_shared<CommGroup>(id, color, nb_procs);
this->addObject(new_group);
#ifndef LM_OPTIMIZED
auto nb_groups = objects.size();
#endif
DUMP("Building processor group number " << nb_groups, DBG_INFO);
DUMP("free_procs " << free_procs << " nb_procs " << nb_procs << " diff "
<< free_procs - nb_procs << " color " << color,
DBG_ALL);
DUMP("group pointer (" << nb_groups << ")=" << new_group, DBG_DETAIL);
MPI_Barrier(MPI_COMM_WORLD);
DUMP("for proc " << lm_my_proc_id << ", group " << nb_groups << " built",
DBG_INFO);
}
/* -------------------------------------------------------------------------- */
UInt Communicator::getNbGroups() {
return Communicator::getCommunicator().objects.size();
}
/* -------------------------------------------------------------------------- */
decltype(Communicator::objects) &Communicator::getGroups() {
return Communicator::getCommunicator().objects;
}
/* -------------------------------------------------------------------------- */
CommGroup &Communicator::getGroup(const LMID &id) {
if (lm_world_size == 1)
return Communicator::getCommunicator().getObject("all");
return Communicator::getCommunicator().getObject(id);
}
/* -------------------------------------------------------------------------- */
UInt Communicator::getNumberFreeProcs() {
DUMP("world size is: " << lm_world_size, DBG_INFO);
int used_procs = 0;
for (auto &group : objects) {
if (group.first == "all" or group.first == "self")
continue;
DUMP("group " << group.first << ": " << group.second->size(), DBG_INFO);
used_procs += group.second->size();
}
return lm_world_size - used_procs;
}
/* -------------------------------------------------------------------------- */
void Communicator::waitForPendingComs() {
DUMP("this routine does nothing. At the moment every communication is "
"synchronized ?",
DBG_INFO);
}
/* -------------------------------------------------------------------------- */
template <typename T> void register_mpi_type(MPI_Datatype &type) {
int err = MPI_Type_contiguous(sizeof(T), MPI_BYTE, &type);
if (err != MPI_SUCCESS)
LM_FATAL("biip");
MPI_Type_commit(&type);
}
Communicator::Communicator() {
register_mpi_type<MPIProc>(Communicator::mpi_type_processor);
auto new_group = std::make_shared<AllGroup>();
this->addObject(new_group);
auto self_group = std::make_shared<SelfGroup>();
this->addObject(self_group);
}
/* -------------------------------------------------------------------------- */
Communicator::~Communicator() {}
/* -------------------------------------------------------------------------- */
MPI_Datatype Communicator::mpi_type_processor;
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__

Event Timeline