-// Copyright (C) 2007-2015 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2024 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
using namespace std;
-/*! \defgroup processor_group Processor Groups
- *
- * \section processor_group_overview Overview
- * The MPIProcessorGroup class is used to set up processor groups that help to define
- * the MPI topology of the couplings. They can be set up in various ways, the most common being
- * the use of the \c MPIProcessorGroup(Comminterface, int pfirst, int plast)
- * constructor.
- *
- * The following code excerpt creates two processor groups on respectively 3 and 2 processors.
- \verbatim
- int main()
- {
- MPI_Init(&argc,&argv);
- CommInterface comm_interface;
- MPIProcessorGroup codeA_group(comm_interface, 0, 2);
- MPIProcessorGroup codeB_group(comm_interface, 3, 4);
-
- ...
- }
- \endverbatim
-*/
-
-namespace ParaMEDMEM
+namespace MEDCoupling
{
- /*!
- \addtogroup processor_group
- @{
+ /*!
+ \anchor MPIProcessorGroup-det
+ \class MPIProcessorGroup
+
+ The MPIProcessorGroup class represents a set of distinct "processors" (computation nodes)
+ in a MPI code. It is used to define the MPI topology of code couplings.
+
+ Groups can be set up in various ways, the most common being
+ the use of the \c MPIProcessorGroup(Comminterface, int pfirst, int plast)
+ constructor.
+
+ The following code excerpt creates two processor groups on respectively 3 and 2 processors.
+ \verbatim
+ int main()
+ {
+ MPI_Init(&argc,&argv);
+ CommInterface comm_interface;
+ MPIProcessorGroup codeA_group(comm_interface, 0, 2); // groups processors 0, 1 and 2
+ MPIProcessorGroup codeB_group(comm_interface, 3, 4); // groups processors 3 and 4
+
+ ...
+ }
+ \endverbatim
*/
+
/*!
* Creates a processor group that is based on all the
- MPI_COMM_WORLD processor.This routine must be called by all processors in MPI_COMM_WORLD.
+ processors of MPI_COMM_WORLD .This routine must be called by all processors in MPI_COMM_WORLD.
\param interface CommInterface object giving access to the MPI
communication layer
*/
*/
MPIProcessorGroup::MPIProcessorGroup(const CommInterface& interface, set<int> proc_ids, const MPI_Comm& world_comm):
- ProcessorGroup(interface, proc_ids),_world_comm(world_comm)
+ ProcessorGroup(interface, proc_ids), _world_comm(world_comm)
+ {
+ updateMPISpecificAttributes();
+ }
+
+
+ /*! Creates a processor group that is based on the processors included in \a proc_ids_by_name[name].
+ This routine must be called by all processors in MPI_COMM_WORLD.
+
+ \param interface CommInterface object giving access to the MPI
+ communication layer
+ \param proc_ids_by_name a map defining a relation between a name and a set of ids that are to be integrated in the group.
+ The ids number are to be understood in terms of MPI_COMM_WORLD ranks.
+ \param simCodeTag identifier of the group
+ */
+
+ MPIProcessorGroup::MPIProcessorGroup(const CommInterface& interface, std::map<std::string,std::set<int>> proc_ids_by_name, const std::string& simCodeTag, const MPI_Comm& world_comm):
+ ProcessorGroup(interface, proc_ids_by_name, simCodeTag), _world_comm(world_comm)
{
updateMPISpecificAttributes();
}
copy<set<int>::const_iterator,int*> (_proc_ids.begin(), _proc_ids.end(), ranks);
for (int i=0; i< (int)_proc_ids.size();i++)
if (ranks[i]>size_world-1)
- throw INTERP_KERNEL::Exception("invalid rank in set<int> argument of MPIProcessorGroup constructor");
+ {
+ delete[] ranks;
+ _comm_interface.groupFree(&group_world); // MPI_Group is a C structure and won't get de-allocated automatically?
+ throw INTERP_KERNEL::Exception("invalid rank in set<int> argument of MPIProcessorGroup constructor");
+ }
- _comm_interface.groupIncl(group_world, _proc_ids.size(), ranks, &_group);
+ _comm_interface.groupIncl(group_world, (int)_proc_ids.size(), ranks, &_group);
_comm_interface.commCreate(_world_comm, _group, &_comm);
+
+ // clean-up
delete[] ranks;
+ _comm_interface.groupFree(&group_world); // MPI_Group is a C structure and won't get de-allocated automatically?
}
/*! Creates a processor group that is based on the processors between \a pstart and \a pend.
_comm_interface.commGroup(_world_comm, &group_world);
if (pend>size_world-1 || pend <pstart || pstart<0)
- throw INTERP_KERNEL::Exception("invalid argument in MPIProcessorGroup constructor (comm,pfirst,plast)");
+ {
+ _comm_interface.groupFree(&group_world);
+ throw INTERP_KERNEL::Exception("invalid argument in MPIProcessorGroup constructor (comm,pfirst,plast)");
+ }
int nprocs=pend-pstart+1;
int* ranks=new int[nprocs];
for (int i=pstart; i<=pend;i++)
_comm_interface.groupIncl(group_world, nprocs, ranks, &_group);
_comm_interface.commCreate(_world_comm, _group, &_comm);
+
+ // clean-up
delete[] ranks;
+ _comm_interface.groupFree(&group_world); // MPI_Group is a C structured and won't get de-allocated automatically?
}
- /*!
- @}
- */
MPIProcessorGroup::MPIProcessorGroup (const ProcessorGroup& proc_group, set<int> proc_ids) :
- ProcessorGroup(proc_group.getCommInterface()),_world_comm(MPI_COMM_WORLD)
+ ProcessorGroup(proc_group.getCommInterface()),
+ _world_comm(MPI_COMM_WORLD), _group(MPI_GROUP_NULL), _comm(MPI_COMM_NULL)
{
cout << "MPIProcessorGroup (const ProcessorGroup& proc_group, set<int> proc_ids)" <<endl;
cout << "Not implemented yet !"<<endl;
exit(1);
}
- MPIProcessorGroup::MPIProcessorGroup(const MPIProcessorGroup& other):ProcessorGroup(other),_world_comm(other._world_comm)
+ MPIProcessorGroup::MPIProcessorGroup(const MPIProcessorGroup& other):
+ ProcessorGroup(other),_world_comm(other._world_comm)
{
updateMPISpecificAttributes();
}
MPIProcessorGroup::~MPIProcessorGroup()
{
- _comm_interface.groupFree(&_group);
+ release();
+ }
+
+ /** Destructor involves MPI operations: make sure this is accessible from a proper
+ * method for Python wrapping.
+ */
+ void MPIProcessorGroup::release()
+ {
+ if (_group != MPI_GROUP_EMPTY)
+ _comm_interface.groupFree(&_group);
+ _group = MPI_GROUP_EMPTY;
if (_comm!=_world_comm && _comm !=MPI_COMM_NULL)
_comm_interface.commFree(&_comm);
-
+ _comm = MPI_COMM_NULL;
}
- /*!
- \addtogroup processor_group
- @{
- */
/*! Translation of the rank id between two processor groups. This method translates rank \a rank
on the current processor group to the rank on group pointed by \a group.
}
- ProcessorGroup *MPIProcessorGroup::deepCpy() const
+ MPIProcessorGroup *MPIProcessorGroup::deepCopy() const
{
return new MPIProcessorGroup(*this);
}
return rank;
}
- /*!
- @}
- */
ProcessorGroup* MPIProcessorGroup::createProcGroup() const
{
set <int> procs;