]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Provide an overload of broadcast() for MPI types.
authorWolfgang Bangerth <bangerth@colostate.edu>
Sat, 5 Mar 2022 01:43:29 +0000 (18:43 -0700)
committerWolfgang Bangerth <bangerth@colostate.edu>
Sat, 5 Mar 2022 01:43:29 +0000 (18:43 -0700)
include/deal.II/base/mpi.h

index 3269e0a3068994ca504744081aa3d05b08979425..fd3ca10ca57c50c2f0726c763cc37aedc6acf916 100644 (file)
@@ -1178,33 +1178,70 @@ namespace Utilities
            const unsigned int root_process = 0);
 
     /**
-     * Sends an object @p object_to_send from the process @p root_process
+     * This function sends an object @p object_to_send from the process @p root_process
      * to all other processes.
      *
-     * A generalization of the classic `MPI_Bcast` function that accepts
-     * arbitrary data types `T`, as long as Utilities::pack() (which in turn
-     * uses `boost::serialize`, see in Utilities::pack() for details) accepts
-     * `T` as an argument.
+     * This function is a generalization of the classic `MPI_Bcast` function
+     * that accepts arbitrary data types `T`, as long as Utilities::pack()
+     * (which in turn uses `boost::serialize`, see in Utilities::pack() for
+     * details) accepts `T` as an argument.
      *
      * @note Be aware that this function is typically a lot more
-     * expensive than an `MPI_Bcast` if you are using simple types
-     * directly supported by MPI. This function will use
+     * expensive than an `MPI_Bcast` because the function will use
      * boost::serialization to (de)serialize, and execute a second
      * `MPI_Bcast` to transmit the size before sending the data
-     * itself. You can also use the other broadcast() function in this
-     * namespace.
+     * itself. On the other hand, if you have a single element of
+     * a data type `T` that is natively supported by MPI, then the
+     * compiler will choose another broadcast() overload that is efficient.
+     * If you have an array of such elements, you should use the other
+     * broadcast() function in this namespace that takes a pointer and a count
+     * argument.
      *
      * @param[in] comm MPI communicator.
      * @param[in] object_to_send An object to send to all processes.
      * @param[in] root_process The process that sends the object to all
      * processes. By default the process with rank 0 is the root process.
      *
+     * @tparam T Any type for which the Utilities::pack() and
+     *   Utilities::unpack() functions can be used to convert the object
+     *   into an array of `char`. The compiler will not select this function
+     *   if `T` is a type that is natively supported by MPI and instead
+     *   use a more efficient overload.
+     *
      * @return On the root process, return a copy of @p object_to_send.
      *   On every other process, return a copy of the object sent by
      *   the @p root_process.
      */
     template <typename T>
-    T
+    typename std::enable_if<is_mpi_type<T> == false, T>::type
+    broadcast(const MPI_Comm &   comm,
+              const T &          object_to_send,
+              const unsigned int root_process = 0);
+
+    /**
+     * This function sends an object @p object_to_send from the process @p root_process
+     * to all other processes.
+     *
+     * This function is wrapper around the `MPI_Bcast` function selected
+     * by the compiler whenever `T` is a data type natively supported by
+     * MPI.
+     *
+     * @param[in] comm MPI communicator.
+     * @param[in] object_to_send An object to send to all processes.
+     * @param[in] root_process The process that sends the object to all
+     * processes. By default the process with rank 0 is the root process.
+     *
+     * @tparam T Any type. The compiler will only select this function
+     *   if `T` is a type that is natively supported by MPI. It will choose
+     *   the other overloaded version of this function if that is not
+     *   the case.
+     *
+     * @return On the root process, return a copy of @p object_to_send.
+     *   On every other process, return a copy of the object sent by
+     *   the @p root_process.
+     */
+    template <typename T>
+    typename std::enable_if<is_mpi_type<T> == true, T>::type
     broadcast(const MPI_Comm &   comm,
               const T &          object_to_send,
               const unsigned int root_process = 0);
@@ -1886,7 +1923,7 @@ namespace Utilities
 
 
     template <typename T>
-    T
+    typename std::enable_if<is_mpi_type<T> == false, T>::type
     broadcast(const MPI_Comm &   comm,
               const T &          object_to_send,
               const unsigned int root_process)
@@ -1934,6 +1971,30 @@ namespace Utilities
     }
 
 
+
+    template <typename T>
+    typename std::enable_if<is_mpi_type<T> == true, T>::type
+    broadcast(const MPI_Comm &   comm,
+              const T &          object_to_send,
+              const unsigned int root_process)
+    {
+#  ifndef DEAL_II_WITH_MPI
+      (void)comm;
+      (void)root_process;
+      return object_to_send;
+#  else
+
+      T   object = object_to_send;
+      int ierr =
+        MPI_Bcast(&object, 1, mpi_type_id_for_type<T>, root_process, comm);
+      AssertThrowMPI(ierr);
+
+      return object;
+#  endif
+    }
+
+
+
 #  ifdef DEAL_II_WITH_MPI
     template <class Iterator, typename Number>
     std::pair<Number, typename numbers::NumberTraits<Number>::real_type>

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.