From af0d3a75b5edd997e221d422dedc8d7af151ba41 Mon Sep 17 00:00:00 2001 From: Daniel Arndt Date: Sat, 20 Jan 2018 15:51:00 +0100 Subject: [PATCH] Provide general template interface for Utilities::MPI::sum/min/max --- include/deal.II/base/array_view.h | 124 ++++++++++++++++++++++++++- include/deal.II/base/mpi.h | 109 ++++++++--------------- include/deal.II/base/mpi.templates.h | 108 +++++++++++------------ source/base/mpi.inst.in | 12 +-- 4 files changed, 215 insertions(+), 138 deletions(-) diff --git a/include/deal.II/base/array_view.h b/include/deal.II/base/array_view.h index 013e86a034..f003e5bad4 100644 --- a/include/deal.II/base/array_view.h +++ b/include/deal.II/base/array_view.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -420,6 +421,30 @@ ArrayView::operator[](const std::size_t i) const } + +/** + * Create a view to an entire C-style array. This is equivalent to + * initializing an ArrayView object with a pointer to the first element and + * the size of the given argument. + * + * Whether the resulting ArrayView is writable or not depends on the + * ElementType being a const type or not. + * + * @param[in] array The C-style array for which we want to have an ArrayView + * object. The ArrayView corresponds to the entire vector. + * + * @relates ArrayView + */ +template +inline +ArrayView +make_array_view (ElementType (&array)[N]) +{ + return ArrayView (array, N); +} + + + /** * Create a view to an entire std::vector object. This is equivalent to * initializing an ArrayView object with a pointer to the first element and @@ -444,6 +469,53 @@ make_array_view (std::vector &vector) +/** + * Create a view to an entire Vector object. This is equivalent to + * initializing an ArrayView object with a pointer to the first element and + * the size of the given argument. + * + * This function is used for @p const references to objects of Vector type + * because they contain immutable elements. Consequently, the return type of + * this function is a view to a set of @p const objects. + * + * @param[in] vector The Vector for which we want to have an array view + * object. The array view corresponds to the entire Vector. + * + * @relates ArrayView + */ +template +inline +ArrayView +make_array_view (Vector &vector) +{ + return ArrayView (vector.begin(), vector.size()); +} + + +/** + * Create a view to an entire Vector object. This is equivalent to + * initializing an ArrayView object with a pointer to the first element and + * the size of the given argument. + * + * This function is used for @p const references to objects of Vector type + * because they contain immutable elements. Consequently, the return type of + * this function is a view to a set of @p const objects. + * + * @param[in] vector The Vector for which we want to have an array view + * object. The array view corresponds to the entire Vector. + * + * @relates ArrayView + */ +template +inline +ArrayView +make_array_view (const Vector &vector) +{ + return ArrayView (vector.begin(), vector.size()); +} + + + /** * Create a view to an entire std::vector object. This is equivalent to * initializing an ArrayView object with a pointer to the first element and @@ -643,9 +715,10 @@ make_array_view (Table<2,ElementType> &table) * initializing an ArrayView object with a pointer to the first element of the * given table, and the number of table entries as the length of the view. * - * This function is used for @p const references to objects of Table type - * because they contain immutable elements. Consequently, the return type of - * this function is a view to a set of @p const objects. + * This function is used for non-@p const references to objects of + * LAPACKFullMatrix type. Such objects contain elements that can be + * written to. Consequently, the return type of this function is a + * view to a set of writable objects. * * @param[in] table The Table for which we want to have an array view object. * The array view corresponds to the entire table. @@ -661,6 +734,51 @@ make_array_view (const Table<2,ElementType> &table) } +/** + * Create a view to an entire LAPACKFullMatrix object. This is equivalent to + * initializing an ArrayView object with a pointer to the first element of the + * given object, and the number entries as the length of the view. + * + * This function is used for @p non-const references to objects of Table type + * because they contain immutable elements. Consequently, the return type of + * this function is a view to a set of @p non-const objects. + * + * @param[in] table The LAPACKFullMatrix for which we want to have an array view + * object. The array view corresponds to the entire object. + * + * @relates ArrayView + */ +template +inline +ArrayView +make_array_view (LAPACKFullMatrix &matrix) +{ + return ArrayView (&matrix(0,0), matrix.n_elements()); +} + + +/** + * Create a view to an entire LAPACKFullMatrix object. This is equivalent to + * initializing an ArrayView object with a pointer to the first element of the + * given object, and the number of entries as the length of the view. + * + * This function is used for @p const references to objects of LAPACKFullMatrix + * type because they contain immutable elements. Consequently, the return type + * of this function is a view to a set of @p const objects. + * + * @param[in] table The LAPACKFullMatrix for which we want to have an array view + * object. The array view corresponds to the entire object. + * + * @relates ArrayView + */ +template +inline +ArrayView +make_array_view (const LAPACKFullMatrix &matrix) +{ + return ArrayView (&matrix(0,0), matrix.n_elements()); +} + /** * Create a view to an entire row of a Table<2> object. This is equivalent to diff --git a/include/deal.II/base/mpi.h b/include/deal.II/base/mpi.h index 2790c9e8b0..6854cef75b 100644 --- a/include/deal.II/base/mpi.h +++ b/include/deal.II/base/mpi.h @@ -154,16 +154,16 @@ namespace Utilities /** * Like the previous function, but take the sums over the elements of an - * array of length N. In other words, the i-th element of the results + * array of type T. In other words, the i-th element of the results * array is the sum over the i-th entries of the input arrays from each - * processor. + * processor. T and U must decay to the same type. * * Input and output arrays may be the same. */ - template - void sum (const T (&values)[N], + template + void sum (const T &values, const MPI_Comm &mpi_communicator, - T (&sums)[N]); + U &sums); /** * Like the previous function, but take the sums over the elements of an @@ -179,48 +179,6 @@ namespace Utilities const MPI_Comm &mpi_communicator, const ArrayView &sums); - /** - * Like the previous function, but take the sums over the elements of a - * std::vector. In other words, the i-th element of the results array is - * the sum over the i-th entries of the input arrays from each processor. - * - * Input and output vectors may be the same. - */ - template - void sum (const std::vector &values, - const MPI_Comm &mpi_communicator, - std::vector &sums); - - /** - * Like the previous function, but take the sums over the elements of a - * Vector. - * - * Input and output vectors may be the same. - */ - template - void sum (const Vector &values, - const MPI_Comm &mpi_communicator, - Vector &sums); - - /** - * Like the previous function, but take the sums over the elements of a - * FullMatrix. - * - * Input and output matrices may be the same. - */ - template - void sum (const FullMatrix &values, - const MPI_Comm &mpi_communicator, - FullMatrix &sums); - - /** - * Same as above but for LAPACKFullMatrix. - */ - template - void sum (const LAPACKFullMatrix &values, - const MPI_Comm &mpi_communicator, - LAPACKFullMatrix &sums); - /** * Perform an MPI sum of the entries of a symmetric tensor. * @@ -265,30 +223,31 @@ namespace Utilities const MPI_Comm &mpi_communicator); /** - * Like the previous function, but take the maxima over the elements of an - * array of length N. In other words, the i-th element of the results - * array is the maximum of the i-th entries of the input arrays from each - * processor. + * Like the previous function, but take the maximum over the elements of an + * array of type T. In other words, the i-th element of the results array is + * the maximum over the i-th entries of the input arrays from each + * processor. T and U must decay to the same type. * - * Input and output arrays may be the same. + * Input and output vectors may be the same. */ - template - void max (const T (&values)[N], + template + void max (const T &values, const MPI_Comm &mpi_communicator, - T (&maxima)[N]); + U &maxima); /** - * Like the previous function, but take the maximum over the elements of a - * std::vector. In other words, the i-th element of the results array is - * the maximum over the i-th entries of the input arrays from each + * Like the previous function, but take the maximum over the elements of an + * array as specified by the ArrayView arguments. + * In other words, the i-th element of the results + * array is the maximum over the i-th entries of the input arrays from each * processor. * - * Input and output vectors may be the same. + * Input and output arrays may be the same. */ template - void max (const std::vector &values, - const MPI_Comm &mpi_communicator, - std::vector &maxima); + void max (const ArrayView &values, + const MPI_Comm &mpi_communicator, + const ArrayView &maxima); /** * Return the minimum over all processors of the value @p t. This function @@ -315,30 +274,30 @@ namespace Utilities /** * Like the previous function, but take the minima over the elements of an - * array of length N. In other words, the i-th element of the results + * array of type T. In other words, the i-th element of the results * array is the minimum of the i-th entries of the input arrays from each - * processor. + * processor. T and U must decay to the same type. * * Input and output arrays may be the same. */ - template - void min (const T (&values)[N], + template + void min (const T &values, const MPI_Comm &mpi_communicator, - T (&minima)[N]); + U &minima); /** - * Like the previous function, but take the minimum over the elements of a - * std::vector. In other words, the i-th element of the results array is - * the minimum over the i-th entries of the input arrays from each + * Like the previous function, but take the minimum over the elements of an + * array as specified by the ArrayView arguments. + * In other words, the i-th element of the results + * array is the minimum over the i-th entries of the input arrays from each * processor. * - * Input and output vectors may be the same. + * Input and output arrays may be the same. */ template - void min (const std::vector &values, - const MPI_Comm &mpi_communicator, - std::vector &minima); - + void min (const ArrayView &values, + const MPI_Comm &mpi_communicator, + const ArrayView &minima); /** * A data structure to store the result of the min_max_avg() function. diff --git a/include/deal.II/base/mpi.templates.h b/include/deal.II/base/mpi.templates.h index db4b33f35c..02ee73f80b 100644 --- a/include/deal.II/base/mpi.templates.h +++ b/include/deal.II/base/mpi.templates.h @@ -336,13 +336,19 @@ namespace Utilities - template - void sum (const std::vector &values, - const MPI_Comm &mpi_communicator, - std::vector &sums) + template + void sum (const T &values, + const MPI_Comm &mpi_communicator, + U &sums) { - internal::all_reduce(MPI_SUM, ArrayView(values), - mpi_communicator, ArrayView(sums)); + static_assert(std::is_same::type, + typename std::decay::type>::value, + "Input and output arguments must have the same type!"); + const auto array_view_values = make_array_view(values); + using const_type = ArrayView; + sum(static_cast (array_view_values), + mpi_communicator, + make_array_view(sums)); } @@ -357,44 +363,6 @@ namespace Utilities - template - void sum (const Vector &values, - const MPI_Comm &mpi_communicator, - Vector &sums) - { - const auto &size = values.size(); - internal::all_reduce(MPI_SUM, ArrayView(values.begin(), size), - mpi_communicator, ArrayView(sums.begin(), size)); - } - - - - template - void sum (const FullMatrix &values, - const MPI_Comm &mpi_communicator, - FullMatrix &sums) - { - const auto size_values = values.n()*values.m(); - const auto size_sums = sums.n()*sums.m(); - internal::all_reduce(MPI_SUM, ArrayView(&values[0][0], size_values), - mpi_communicator, ArrayView(&sums[0][0], size_sums)); - } - - - - template - void sum (const LAPACKFullMatrix &values, - const MPI_Comm &mpi_communicator, - LAPACKFullMatrix &sums) - { - const auto size_values = values.n()*values.m(); - const auto size_sums = sums.n()*sums.m(); - internal::all_reduce(MPI_SUM, ArrayView(&values(0,0), size_values), - mpi_communicator, ArrayView(&sums(0,0), size_sums)); - } - - - template Tensor sum (const Tensor &local, @@ -453,13 +421,29 @@ namespace Utilities + template + void max (const T &values, + const MPI_Comm &mpi_communicator, + U &maxima) + { + static_assert(std::is_same::type, + typename std::decay::type>::value, + "Input and output arguments must have the same type!"); + const auto array_view_values = make_array_view(values); + using const_type = ArrayView; + max(static_cast (array_view_values), + mpi_communicator, + make_array_view(maxima)); + } + + + template - void max (const std::vector &values, - const MPI_Comm &mpi_communicator, - std::vector &maxima) + void max (const ArrayView &values, + const MPI_Comm &mpi_communicator, + const ArrayView &maxima) { - internal::all_reduce(MPI_MAX, ArrayView(values), - mpi_communicator, ArrayView (maxima)); + internal::all_reduce(MPI_MAX, values, mpi_communicator, maxima); } @@ -476,13 +460,29 @@ namespace Utilities + template + void min (const T &values, + const MPI_Comm &mpi_communicator, + U &minima) + { + static_assert(std::is_same::type, + typename std::decay::type>::value, + "Input and output arguments must have the same type!"); + const auto array_view_values = make_array_view(values); + using const_type = ArrayView; + min(static_cast (array_view_values), + mpi_communicator, + make_array_view(minima)); + } + + + template - void min (const std::vector &values, - const MPI_Comm &mpi_communicator, - std::vector &minima) + void min (const ArrayView &values, + const MPI_Comm &mpi_communicator, + const ArrayView &minima) { - internal::all_reduce(MPI_MIN, ArrayView(values), - mpi_communicator, ArrayView (minima)); + internal::all_reduce(MPI_MIN, values, mpi_communicator, minima); } } // end of namespace MPI } // end of namespace Utilities diff --git a/source/base/mpi.inst.in b/source/base/mpi.inst.in index c96e796efd..a6acf7774e 100644 --- a/source/base/mpi.inst.in +++ b/source/base/mpi.inst.in @@ -17,13 +17,13 @@ for (S : MPI_SCALARS) { template - void sum (const LAPACKFullMatrix &, const MPI_Comm &, LAPACKFullMatrix &); + void sum > (const LAPACKFullMatrix &, const MPI_Comm &, LAPACKFullMatrix &); template - void sum (const Vector &, const MPI_Comm &, Vector &); + void sum > (const Vector &, const MPI_Comm &, Vector &); template - void sum (const FullMatrix &, const MPI_Comm &, FullMatrix &); + void sum > (const FullMatrix &, const MPI_Comm &, FullMatrix &); template void sum (const ArrayView &, const MPI_Comm &, const ArrayView &); @@ -32,19 +32,19 @@ for (S : MPI_SCALARS) S sum (const S &, const MPI_Comm &); template - void sum (const std::vector &, const MPI_Comm &, std::vector &); + void sum > (const std::vector &, const MPI_Comm &, std::vector &); template S max (const S &, const MPI_Comm &); template - void max (const std::vector &, const MPI_Comm &, std::vector &); + void max > (const std::vector &, const MPI_Comm &, std::vector &); template S min (const S &, const MPI_Comm &); template - void min (const std::vector &, const MPI_Comm &, std::vector &); + void min > (const std::vector &, const MPI_Comm &, std::vector &); // The fixed-length array (i.e., things declared like T(&values)[N]) // versions of the functions above live in the header file mpi.h since the -- 2.39.5