]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add Utilities::MPI::MPI_Comm_create_group
authorDaniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Sat, 28 Apr 2018 12:18:54 +0000 (14:18 +0200)
committerDaniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Sun, 29 Apr 2018 09:55:01 +0000 (11:55 +0200)
include/deal.II/base/mpi.h
source/base/mpi.cc

index 58e0878a3974e13ca50aae7d6a0b8726a6a172f4..4d50ccb9d2443ed5e7611465c0677d6feba02682 100644 (file)
@@ -125,6 +125,40 @@ namespace Utilities
      */
     MPI_Comm duplicate_communicator (const MPI_Comm &mpi_communicator);
 
+    /**
+     * If @comm is an intracommunicator, this function returns a new
+     * communicator @p newcomm with communication group defined by the
+     * @p group argument. The function is only collective over the group of
+     * processes that actually want to create the communicator, i.e., that
+     * are named in the @p group argument. If multiple threads at a given
+     * process perform concurrent create_group() operations, the user must
+     * distinguish these operations by providing different @p tag or @p comm
+     * arguments.
+     *
+     * This function was introduced in the MPI-3.0 standard. If available,
+     * the corresponding function in the provided MPI implementation is used.
+     * Otherwise, the implementation follows the one described in the
+     * following publication:
+     * @code{.bib}
+     * @inproceedings{dinan2011noncollective,
+     *  title={Noncollective communicator creation in MPI},
+     *  author={Dinan, James and Krishnamoorthy, Sriram and Balaji, Pavan and
+     *          Hammond, Jeff R and Krishnan, Manojkumar and Tipparaju, Vinod
+     *          and Vishnu, Abhinav},
+     *  booktitle={European MPI Users' Group Meeting},
+     *  pages={282--291},
+     *  year={2011},
+     *  organization={Springer}
+     * }
+     * @endcode
+     */
+#ifdef DEAL_II_WITH_MPI
+    int create_group(const MPI_Comm  &comm,
+                     const MPI_Group &group,
+                     const int        tag,
+                     MPI_Comm        *new_comm);
+#endif
+
     /**
      * Return the sum over all processors of the value @p t. This function is
      * collective over all processors given in the
index a5ba1c84d885dbcddb327b2d4f89b4386fa39486..8ba56974120717d37fc220c4d87e456b5284f51d 100644 (file)
@@ -91,6 +91,85 @@ namespace Utilities
     }
 
 
+
+    int create_group(const MPI_Comm  &comm,
+                     const MPI_Group &group,
+                     const int        tag,
+                     MPI_Comm        *new_comm)
+    {
+#if DEAL_II_MPI_VERSION_GTE(3, 0)
+      return MPI_Comm_create_group(comm, group, tag, new_comm);
+#else
+      int rank;
+      int ierr = MPI_Comm_rank(comm, &rank);
+      AssertThrowMPI(ierr);
+
+      int grp_rank;
+      ierr = MPI_Group_rank(group, &grp_rank);
+      AssertThrowMPI(ierr);
+      if (grp_rank == MPI_UNDEFINED)
+        {
+          *new_comm = MPI_COMM_NULL;
+          return MPI_SUCCESS;
+        }
+
+      int grp_size;
+      ierr = MPI_Group_size(group, &grp_size);
+      AssertThrowMPI(ierr);
+
+      ierr = MPI_Comm_dup(MPI_COMM_SELF, new_comm);
+      AssertThrowMPI(ierr);
+
+      MPI_Group parent_grp;
+      ierr = MPI_Comm_group(comm, &parent_grp);
+      AssertThrowMPI(ierr);
+
+      std::vector<int> pids(grp_size);
+      std::vector<int> grp_pids(grp_size);
+      std::iota(grp_pids.begin(), grp_pids.end(), 0);
+      ierr = MPI_Group_translate_ranks(group, grp_size, grp_pids.data(), parent_grp, pids.data());
+      AssertThrowMPI(ierr);
+      ierr = MPI_Group_free(&parent_grp);
+      AssertThrowMPI(ierr);
+
+      MPI_Comm comm_old = *new_comm;
+      MPI_Comm ic;
+      for (int merge_sz = 1; merge_sz < grp_size; merge_sz *=2)
+        {
+          const int gid = grp_rank/merge_sz;
+          comm_old = *new_comm;
+          if (gid % 2 == 0)
+            {
+              if ((gid + 1) * merge_sz < grp_size)
+                {
+                  ierr = (MPI_Intercomm_create(*new_comm, 0, comm, pids[(gid + 1) * merge_sz], tag, &ic));
+                  AssertThrowMPI(ierr);
+                  ierr = MPI_Intercomm_merge(ic, 0 /* LOW */, new_comm);
+                  AssertThrowMPI(ierr);
+                }
+            }
+          else
+            {
+              ierr = MPI_Intercomm_create(*new_comm, 0, comm, pids[(gid - 1) * merge_sz], tag, &ic);
+              AssertThrowMPI(ierr);
+              ierr = MPI_Intercomm_merge(ic, 1 /* HIGH */, new_comm);
+              AssertThrowMPI(ierr);
+            }
+          if (*new_comm != comm_old)
+            {
+              ierr = MPI_Comm_free(&ic);
+              AssertThrowMPI(ierr);
+              ierr = MPI_Comm_free(&comm_old);
+              AssertThrowMPI(ierr);
+            }
+        }
+
+      return MPI_SUCCESS;
+#endif
+    }
+
+
+
     std::vector<unsigned int>
     compute_point_to_point_communication_pattern (const MPI_Comm &mpi_comm,
                                                   const std::vector<unsigned int> &destinations)

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.