]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Use a template variable rather than a dummy function to infer MPI types.
authorWolfgang Bangerth <bangerth@colostate.edu>
Tue, 15 Feb 2022 22:45:51 +0000 (15:45 -0700)
committerWolfgang Bangerth <bangerth@colostate.edu>
Thu, 3 Mar 2022 16:21:22 +0000 (09:21 -0700)
include/deal.II/base/mpi.h
include/deal.II/base/mpi.templates.h
include/deal.II/base/mpi_noncontiguous_partitioner.templates.h
include/deal.II/multigrid/mg_transfer_global_coarsening.templates.h
source/base/mpi.cc
source/base/partitioner.cc
source/base/process_grid.cc
source/distributed/repartitioning_policy_tools.cc
source/distributed/tria_base.cc
source/lac/scalapack.cc
source/matrix_free/vector_data_exchange.cc

index 97621696246cde40485be454134ff1b67e5bdbe3..4c9e5ccfec6d645bf3dcd51be873021540fd79bf 100644 (file)
@@ -1303,154 +1303,180 @@ namespace Utilities
 
     /* --------------------------- inline functions ------------------------- */
 
-    /**
-     * Given a pointer to an object of class T, return the matching
-     * `MPI_Datatype` to be used for MPI communication.
-     *
-     * As an example, passing an `int*` to this function returns `MPI_INT`.
-     *
-     * @note In reality, these functions are not template functions templated
-     * on the parameter T, but free standing inline function overloads. This
-     * templated version only exists so that it shows up in the documentation.
-     * The `=delete` statement at the end of the declaration ensures that the
-     * compiler will never choose this general template and instead look
-     * for one of the overloads.
-     */
-    template <typename T>
-    inline MPI_Datatype
-    mpi_type_id(const T *) = delete;
+    namespace internal
+    {
+      namespace MPIDataTypes
+      {
+        /**
+         * Given a pointer to an object of class T, return the matching
+         * `MPI_Datatype` to be used for MPI communication.
+         *
+         * As an example, passing an `int*` to this function returns `MPI_INT`.
+         *
+         * @note In reality, these functions are not template functions templated
+         * on the parameter T, but free standing inline function overloads. This
+         * templated version only exists so that it shows up in the
+         * documentation. The `=delete` statement at the end of the declaration
+         * ensures that the compiler will never choose this general template and
+         * instead look for one of the overloads.
+         */
+        template <typename T>
+        inline MPI_Datatype
+        mpi_type_id(const T *) = delete;
 
 #ifndef DOXYGEN
 
 #  ifdef DEAL_II_WITH_MPI
-    inline MPI_Datatype
-    mpi_type_id(const bool *)
-    {
-      return MPI_CXX_BOOL;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const bool *)
+        {
+          return MPI_CXX_BOOL;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const char *)
-    {
-      return MPI_CHAR;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const char *)
+        {
+          return MPI_CHAR;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const signed char *)
-    {
-      return MPI_SIGNED_CHAR;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const signed char *)
+        {
+          return MPI_SIGNED_CHAR;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const short *)
-    {
-      return MPI_SHORT;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const short *)
+        {
+          return MPI_SHORT;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const int *)
-    {
-      return MPI_INT;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const int *)
+        {
+          return MPI_INT;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const long int *)
-    {
-      return MPI_LONG;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const long int *)
+        {
+          return MPI_LONG;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const unsigned char *)
-    {
-      return MPI_UNSIGNED_CHAR;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const unsigned char *)
+        {
+          return MPI_UNSIGNED_CHAR;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const unsigned short *)
-    {
-      return MPI_UNSIGNED_SHORT;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const unsigned short *)
+        {
+          return MPI_UNSIGNED_SHORT;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const unsigned int *)
-    {
-      return MPI_UNSIGNED;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const unsigned int *)
+        {
+          return MPI_UNSIGNED;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const unsigned long int *)
-    {
-      return MPI_UNSIGNED_LONG;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const unsigned long int *)
+        {
+          return MPI_UNSIGNED_LONG;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const unsigned long long int *)
-    {
-      return MPI_UNSIGNED_LONG_LONG;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const unsigned long long int *)
+        {
+          return MPI_UNSIGNED_LONG_LONG;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const float *)
-    {
-      return MPI_FLOAT;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const float *)
+        {
+          return MPI_FLOAT;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const double *)
-    {
-      return MPI_DOUBLE;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const double *)
+        {
+          return MPI_DOUBLE;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const long double *)
-    {
-      return MPI_LONG_DOUBLE;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const long double *)
+        {
+          return MPI_LONG_DOUBLE;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const std::complex<float> *)
-    {
-      return MPI_COMPLEX;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const std::complex<float> *)
+        {
+          return MPI_COMPLEX;
+        }
 
 
 
-    inline MPI_Datatype
-    mpi_type_id(const std::complex<double> *)
-    {
-      return MPI_DOUBLE_COMPLEX;
-    }
+        inline MPI_Datatype
+        mpi_type_id(const std::complex<double> *)
+        {
+          return MPI_DOUBLE_COMPLEX;
+        }
 #  endif
+#endif
+      } // namespace MPIDataTypes
+    }   // namespace internal
+
+
+
+    /**
+     * A template variable that translates from the data type given as
+     * template argument to the corresponding
+     * `MPI_Datatype` to be used for MPI communication.
+     *
+     * As an example, the value of `mpi_type_id<int>` is `MPI_INT`. A
+     * common way to use this variable is when sending an object `obj`
+     * via MPI functions to another process, and using
+     * `mpi_type_id<decltype(obj)>` to infer the correct MPI type to
+     * use for the communication.
+     */
+    template <typename T>
+    const MPI_Datatype mpi_type_id = internal::MPIDataTypes::mpi_type_id(
+      static_cast<std::remove_cv_t<
+        std::remove_reference_t<std::remove_all_extents_t<T>>> *>(nullptr));
 
 
+#ifndef DOXYGEN
     namespace internal
     {
       // declaration for an internal function that lives in mpi.templates.h
@@ -1808,7 +1834,7 @@ namespace Utilities
 
           const int ierr = MPI_Bcast(buffer + total_sent_count,
                                      current_count,
-                                     mpi_type_id(buffer),
+                                     mpi_type_id<decltype(*buffer)>,
                                      root,
                                      comm);
           AssertThrowMPI(ierr);
@@ -1846,8 +1872,11 @@ namespace Utilities
         }
 
       // Exchange the size of buffer
-      int ierr = MPI_Bcast(
-        &buffer_size, 1, mpi_type_id(&buffer_size), root_process, comm);
+      int ierr = MPI_Bcast(&buffer_size,
+                           1,
+                           mpi_type_id<decltype(buffer_size)>,
+                           root_process,
+                           comm);
       AssertThrowMPI(ierr);
 
       // If not on the root process, correctly size the buffer to
index ab5b455752810b1b9573f00e25c8913c487fb56c..0af2709a1c7c609abd08a1373ab53d039ac96f9f 100644 (file)
@@ -85,7 +85,7 @@ namespace Utilities
                               MPI_IN_PLACE,
                             static_cast<void *>(output.data()),
                             static_cast<int>(values.size()),
-                            mpi_type_id(values.data()),
+                            mpi_type_id<decltype(*values.data())>,
                             mpi_op,
                             mpi_communicator);
             AssertThrowMPI(ierr);
@@ -125,7 +125,7 @@ namespace Utilities
                               MPI_IN_PLACE,
                             static_cast<void *>(output.data()),
                             static_cast<int>(values.size() * 2),
-                            mpi_type_id(static_cast<T *>(nullptr)),
+                            mpi_type_id<T>,
                             mpi_op,
                             mpi_communicator);
             AssertThrowMPI(ierr);
index cb4b6f286c1d5f23a75e4cbb42cf4bb31631cdaf..e342968988b4c70cb90bc9a59362cddf9822668f 100644 (file)
@@ -106,14 +106,13 @@ namespace Utilities
       AssertIndexRange(recv_ranks.size(), recv_ptr.size());
       for (types::global_dof_index i = 0; i < recv_ranks.size(); ++i)
         {
-          const int ierr =
-            MPI_Irecv(buffers.data() + recv_ptr[i],
-                      recv_ptr[i + 1] - recv_ptr[i],
-                      Utilities::MPI::mpi_type_id(buffers.data()),
-                      recv_ranks[i],
-                      tag,
-                      communicator,
-                      &requests[i + send_ranks.size()]);
+          const int ierr = MPI_Irecv(buffers.data() + recv_ptr[i],
+                                     recv_ptr[i + 1] - recv_ptr[i],
+                                     Utilities::MPI::mpi_type_id<Number>,
+                                     recv_ranks[i],
+                                     tag,
+                                     communicator,
+                                     &requests[i + send_ranks.size()]);
           AssertThrowMPI(ierr);
         }
 
@@ -135,14 +134,13 @@ namespace Utilities
                    (send_ptr[i] == buffers.size() &&
                     send_ptr[i + 1] == send_ptr[i]),
                  ExcMessage("The input buffer doesn't contain enough entries"));
-          const int ierr =
-            MPI_Isend(buffers.data() + send_ptr[i],
-                      send_ptr[i + 1] - send_ptr[i],
-                      Utilities::MPI::mpi_type_id(buffers.data()),
-                      send_ranks[i],
-                      tag,
-                      communicator,
-                      &requests[i]);
+          const int ierr = MPI_Isend(buffers.data() + send_ptr[i],
+                                     send_ptr[i + 1] - send_ptr[i],
+                                     Utilities::MPI::mpi_type_id<Number>,
+                                     send_ranks[i],
+                                     tag,
+                                     communicator,
+                                     &requests[i]);
           AssertThrowMPI(ierr);
         }
 #endif
index 72b4aa717e6d6917e41742b5e69fdbf5c4ca83e6..742f8bc05af046d06aa15bed4a4741f42d4ebd6b 100644 (file)
@@ -571,7 +571,7 @@ namespace internal
             const auto ierr_1 = MPI_Isend(
               buffer.data(),
               buffer.size(),
-              Utilities::MPI::mpi_type_id(buffer.data()),
+              Utilities::MPI::mpi_type_id<decltype(*buffer.data())>,
               i.first,
               Utilities::MPI::internal::Tags::fine_dof_handler_view_reinit,
               communicator,
@@ -638,10 +638,10 @@ namespace internal
             std::vector<types::global_dof_index> buffer;
 
             int       message_length;
-            const int ierr_2 =
-              MPI_Get_count(&status,
-                            Utilities::MPI::mpi_type_id(buffer.data()),
-                            &message_length);
+            const int ierr_2 = MPI_Get_count(
+              &status,
+              Utilities::MPI::mpi_type_id<decltype(*buffer.data())>,
+              &message_length);
             AssertThrowMPI(ierr_2);
 
             buffer.resize(message_length);
@@ -649,7 +649,7 @@ namespace internal
             const int ierr_3 = MPI_Recv(
               buffer.data(),
               buffer.size(),
-              Utilities::MPI::mpi_type_id(buffer.data()),
+              Utilities::MPI::mpi_type_id<decltype(*buffer.data())>,
               status.MPI_SOURCE,
               Utilities::MPI::internal::Tags::fine_dof_handler_view_reinit,
               communicator,
index e392471d4d104d0b6db4c286936b25903c7bdaa5..3a94760614af20c894ea1f1db9300193d09311b1 100644 (file)
@@ -87,6 +87,26 @@ namespace Utilities
 
   namespace MPI
   {
+#ifdef DEAL_II_WITH_MPI
+    // Provide definitions of template variables for all valid instantiations.
+    template const MPI_Datatype mpi_type_id<bool>;
+    template const MPI_Datatype mpi_type_id<char>;
+    template const MPI_Datatype mpi_type_id<signed char>;
+    template const MPI_Datatype mpi_type_id<short>;
+    template const MPI_Datatype mpi_type_id<int>;
+    template const MPI_Datatype mpi_type_id<long int>;
+    template const MPI_Datatype mpi_type_id<unsigned char>;
+    template const MPI_Datatype mpi_type_id<unsigned short>;
+    template const MPI_Datatype mpi_type_id<unsigned long int>;
+    template const MPI_Datatype mpi_type_id<unsigned long long int>;
+    template const MPI_Datatype mpi_type_id<float>;
+    template const MPI_Datatype mpi_type_id<double>;
+    template const MPI_Datatype mpi_type_id<long double>;
+    template const MPI_Datatype mpi_type_id<std::complex<float>>;
+    template const MPI_Datatype mpi_type_id<std::complex<double>>;
+#endif
+
+
     MinMaxAvg
     min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
     {
index f1b87c5d7e716141c925d9cc89015bc8202d77dc..e6b12f3a2e4860ef318673b9444f2d251fa5a8bc 100644 (file)
@@ -76,12 +76,13 @@ namespace Utilities
       types::global_dof_index prefix_sum = 0;
 
 #ifdef DEAL_II_WITH_MPI
-      const int ierr = MPI_Exscan(&local_size,
-                                  &prefix_sum,
-                                  1,
-                                  Utilities::MPI::mpi_type_id(&prefix_sum),
-                                  MPI_SUM,
-                                  communicator);
+      const int ierr =
+        MPI_Exscan(&local_size,
+                   &prefix_sum,
+                   1,
+                   Utilities::MPI::mpi_type_id<decltype(prefix_sum)>,
+                   MPI_SUM,
+                   communicator);
       AssertThrowMPI(ierr);
 #endif
 
index 330df8f706da73c6bca8a4f759274118993b54e4..d7e97a616b612b145aeec9af49f5b4b0f397f445 100644 (file)
@@ -247,11 +247,12 @@ namespace Utilities
       Assert(count > 0, ExcInternalError());
       if (mpi_communicator_inactive_with_root != MPI_COMM_NULL)
         {
-          const int ierr = MPI_Bcast(value,
-                                     count,
-                                     Utilities::MPI::mpi_type_id(value),
-                                     0 /*from root*/,
-                                     mpi_communicator_inactive_with_root);
+          const int ierr =
+            MPI_Bcast(value,
+                      count,
+                      Utilities::MPI::mpi_type_id<decltype(*value)>,
+                      0 /*from root*/,
+                      mpi_communicator_inactive_with_root);
           AssertThrowMPI(ierr);
         }
     }
index e4a7e0c8d46e029b53b7dc3e012cae8e7f06acec..10b56b5dc7d342a986eb738291d6f8478a0d1982 100644 (file)
@@ -89,8 +89,8 @@ namespace RepartitioningPolicyTools
     const int ierr = MPI_Exscan(&process_has_active_locally_owned_cells,
                                 &offset,
                                 1,
-                                Utilities::MPI::mpi_type_id(
-                                  &process_has_active_locally_owned_cells),
+                                Utilities::MPI::mpi_type_id<decltype(
+                                  process_has_active_locally_owned_cells)>,
                                 MPI_SUM,
                                 comm);
     AssertThrowMPI(ierr);
@@ -308,12 +308,13 @@ namespace RepartitioningPolicyTools
     // determine partial sum of weights of this process
     uint64_t process_local_weight_offset = 0;
 
-    int ierr = MPI_Exscan(&process_local_weight,
-                          &process_local_weight_offset,
-                          1,
-                          Utilities::MPI::mpi_type_id(&process_local_weight),
-                          MPI_SUM,
-                          tria->get_communicator());
+    int ierr =
+      MPI_Exscan(&process_local_weight,
+                 &process_local_weight_offset,
+                 1,
+                 Utilities::MPI::mpi_type_id<decltype(process_local_weight)>,
+                 MPI_SUM,
+                 tria->get_communicator());
     AssertThrowMPI(ierr);
 
     // total weight of all processes
@@ -321,7 +322,7 @@ namespace RepartitioningPolicyTools
 
     ierr = MPI_Bcast(&total_weight,
                      1,
-                     Utilities::MPI::mpi_type_id(&total_weight),
+                     Utilities::MPI::mpi_type_id<decltype(total_weight)>,
                      n_subdomains - 1,
                      mpi_communicator);
     AssertThrowMPI(ierr);
index 18736bd4f28dd70bcf3e8c139035de03a4a3f2e5..9cbaeb689547c7f80518cd74f9854a98a2996e2e 100644 (file)
@@ -427,7 +427,7 @@ namespace parallel
       MPI_Exscan(&n_locally_owned_cells,
                  &cell_index,
                  1,
-                 Utilities::MPI::mpi_type_id(&n_locally_owned_cells),
+                 Utilities::MPI::mpi_type_id<decltype(n_locally_owned_cells)>,
                  MPI_SUM,
                  this->mpi_communicator);
     AssertThrowMPI(ierr);
@@ -493,13 +493,13 @@ namespace parallel
         std::vector<types::global_cell_index> cell_index(
           this->n_global_levels(), 0);
 
-        int ierr =
-          MPI_Exscan(n_locally_owned_cells.data(),
-                     cell_index.data(),
-                     this->n_global_levels(),
-                     Utilities::MPI::mpi_type_id(n_locally_owned_cells.data()),
-                     MPI_SUM,
-                     this->mpi_communicator);
+        int ierr = MPI_Exscan(
+          n_locally_owned_cells.data(),
+          cell_index.data(),
+          this->n_global_levels(),
+          Utilities::MPI::mpi_type_id<decltype(*n_locally_owned_cells.data())>,
+          MPI_SUM,
+          this->mpi_communicator);
         AssertThrowMPI(ierr);
 
         // 3) determine global number of "active" cells on each level
@@ -509,11 +509,12 @@ namespace parallel
         for (unsigned int l = 0; l < this->n_global_levels(); ++l)
           n_cells_level[l] = n_locally_owned_cells[l] + cell_index[l];
 
-        ierr = MPI_Bcast(n_cells_level.data(),
-                         this->n_global_levels(),
-                         Utilities::MPI::mpi_type_id(n_cells_level.data()),
-                         this->n_subdomains - 1,
-                         this->mpi_communicator);
+        ierr = MPI_Bcast(
+          n_cells_level.data(),
+          this->n_global_levels(),
+          Utilities::MPI::mpi_type_id<decltype(*n_cells_level.data())>,
+          this->n_subdomains - 1,
+          this->mpi_communicator);
         AssertThrowMPI(ierr);
 
         // 4) give global indices to locally-owned cells on level and mark
index f0b53bc05b0a5330d200e0f19fb65e7aeb7b318f..666056d90d916e680ff4f100878f1746353ecacb 100644 (file)
@@ -184,14 +184,14 @@ ScaLAPACKMatrix<NumberType>::ScaLAPACKMatrix(
     }
   int ierr = MPI_Bcast(&n_rows,
                        1,
-                       Utilities::MPI::mpi_type_id(&n_rows),
+                       Utilities::MPI::mpi_type_id<decltype(n_rows)>,
                        0 /*from root*/,
                        process_grid->mpi_communicator);
   AssertThrowMPI(ierr);
 
   ierr = MPI_Bcast(&n_columns,
                    1,
-                   Utilities::MPI::mpi_type_id(&n_columns),
+                   Utilities::MPI::mpi_type_id<decltype(n_columns)>,
                    0 /*from root*/,
                    process_grid->mpi_communicator);
   AssertThrowMPI(ierr);
index afb8ab83bb27664dfbb55d82e740f803dc362df6..dd6a1d4618e0da208be1ca166fbfe010240a23c7 100644 (file)
@@ -896,7 +896,7 @@ namespace internal
             const int ierr =
               MPI_Irecv(buffer.data() + ghost_targets_data[i][1] + offset,
                         ghost_targets_data[i][2],
-                        Utilities::MPI::mpi_type_id(buffer.data()),
+                        Utilities::MPI::mpi_type_id<decltype(*buffer.data())>,
                         ghost_targets_data[i][0],
                         communication_channel + 1,
                         comm,
@@ -917,16 +917,15 @@ namespace internal
                   data_this[import_indices_data.second[j].first + l];
 
             // send data away
-            const int ierr =
-              MPI_Isend(temporary_storage.data() + import_targets_data[i][1],
-                        import_targets_data[i][2],
-                        Utilities::MPI::mpi_type_id(data_this.data()),
-                        import_targets_data[i][0],
-                        communication_channel + 1,
-                        comm,
-                        requests.data() + sm_import_ranks.size() +
-                          sm_ghost_ranks.size() + ghost_targets_data.size() +
-                          i);
+            const int ierr = MPI_Isend(
+              temporary_storage.data() + import_targets_data[i][1],
+              import_targets_data[i][2],
+              Utilities::MPI::mpi_type_id<decltype(*data_this.data())>,
+              import_targets_data[i][0],
+              communication_channel + 1,
+              comm,
+              requests.data() + sm_import_ranks.size() + sm_ghost_ranks.size() +
+                ghost_targets_data.size() + i);
             AssertThrowMPI(ierr);
           }
 #endif
@@ -1173,7 +1172,7 @@ namespace internal
             const int ierr =
               MPI_Isend(buffer.data() + ghost_targets_data[i][1],
                         ghost_targets_data[i][2],
-                        Utilities::MPI::mpi_type_id(buffer.data()),
+                        Utilities::MPI::mpi_type_id<decltype(*buffer.data())>,
                         ghost_targets_data[i][0],
                         communication_channel + 0,
                         comm,
@@ -1184,16 +1183,15 @@ namespace internal
 
         for (unsigned int i = 0; i < import_targets_data.size(); ++i)
           {
-            const int ierr =
-              MPI_Irecv(temporary_storage.data() + import_targets_data[i][1],
-                        import_targets_data[i][2],
-                        Utilities::MPI::mpi_type_id(temporary_storage.data()),
-                        import_targets_data[i][0],
-                        communication_channel + 0,
-                        comm,
-                        requests.data() + sm_ghost_ranks.size() +
-                          sm_import_ranks.size() + ghost_targets_data.size() +
-                          i);
+            const int ierr = MPI_Irecv(
+              temporary_storage.data() + import_targets_data[i][1],
+              import_targets_data[i][2],
+              Utilities::MPI::mpi_type_id<decltype(*temporary_storage.data())>,
+              import_targets_data[i][0],
+              communication_channel + 0,
+              comm,
+              requests.data() + sm_ghost_ranks.size() + sm_import_ranks.size() +
+                ghost_targets_data.size() + i);
             AssertThrowMPI(ierr);
           }
 #endif

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.