Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Apply_Helpers.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Tpetra: Templated Linear Algebra Services Package
4 //
5 // Copyright 2008 NTESS and the Tpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TPETRA_APPLY_HELPERS_HPP
11 #define TPETRA_APPLY_HELPERS_HPP
12 #include <type_traits>
13 #include "Teuchos_ScalarTraits.hpp"
14 #include "Tpetra_CrsMatrix.hpp"
16 
17 namespace Tpetra {
19 
20 
43 template <class MatrixArray, class MultiVectorArray>
44 void batchedApply(const MatrixArray &Matrices,
45  const typename std::remove_pointer<typename MultiVectorArray::value_type>::type &X,
46  MultiVectorArray &Y,
47  typename std::remove_pointer<typename MatrixArray::value_type>::type::scalar_type alpha = Teuchos::ScalarTraits<typename std::remove_pointer<typename MatrixArray::value_type>::type::scalar_type>::one(),
48  typename std::remove_pointer<typename MatrixArray::value_type>::type::scalar_type beta = Teuchos::ScalarTraits<typename std::remove_pointer<typename MatrixArray::value_type>::type::scalar_type>::zero(),
49  Teuchos::RCP<Teuchos::ParameterList> params = Teuchos::null) {
50  Tpetra::Details::ProfilingRegion regionTotal("Tpetra::batchedApply");
51 
52  using size_type = typename MatrixArray::size_type;
53  using matrix_type = typename std::remove_pointer<typename MatrixArray::value_type>::type;
54  using map_type = typename matrix_type::map_type;
55  using import_type = typename matrix_type::import_type;
56  using export_type = typename matrix_type::export_type;
57  using MV = typename matrix_type::MV;
58  using scalar_type = typename matrix_type::scalar_type;
59 
60  using Teuchos::RCP;
61  using Teuchos::rcp_const_cast;
62 
63  const scalar_type ONE = Teuchos::ScalarTraits<scalar_type>::one();
64  const scalar_type ZERO = Teuchos::ScalarTraits<scalar_type>::zero();
65 
66  size_type N = Matrices.size();
67  if (N == 0) return;
68  int numRanks = X.getMap()->getComm()->getSize();
69 
70  // If X is aliased to any Y but the last one, throw
71  for (size_type i = 0; i < N - 1; i++) {
72  TEUCHOS_TEST_FOR_EXCEPTION(&X == Y[i], std::runtime_error, "Tpetra::batchedApply(): X cannot be aliased to any Y except the final one.");
73  }
74 
75  /* Checks for whether the reduced communication path can be used */
76  RCP<const map_type> compare_colMap = Matrices[0]->getColMap();
77  RCP<const import_type> importer = Matrices[0]->getGraph()->getImporter();
78 
79  bool can_batch, check_maps;
80  if (params.is_null() || !params->isParameter("can batch")) {
81  can_batch = (importer.is_null() || N == 1) ? false : true;
82  check_maps = true;
83  } else {
84  can_batch = (!params->get<bool>("can batch") || importer.is_null() || N == 1) ? false : true;
85  check_maps = false;
86  }
87  // We can't batch with replicated Y's
88  if (numRanks > 1) {
89  for (size_type i = 0; i < N && can_batch; i++) {
90  if (!Y[i]->isDistributed())
91  can_batch = false;
92  }
93  }
94 
95  // Do the domain/column maps all match?
96  for (size_type i = 1; i < N && check_maps && can_batch; i++) {
97  if (!Matrices[i]->getColMap()->isSameAs(*compare_colMap)) {
98  can_batch = false;
99  }
100  }
101 
102  if (can_batch) {
103  /* Batching path: Guarantees an existing importer and N>1 */
104 
105  // Special case for alpha = 0
106  if (alpha == ZERO) {
107  if (beta == ZERO) {
108  for (size_type i = 0; i < N; i++) Y[i]->putScalar(ZERO);
109  } else if (beta != ONE) {
110  for (size_type i = 0; i < N; i++) Y[i]->scale(beta);
111  }
112  if (!params.is_null()) params->set("can batch", true);
113  return;
114  }
115 
116  const bool Y_is_overwritten = (beta == ZERO);
117 
118  // Start by importing X to Matrices[0]'s temporary
119  RCP<const MV> X_colMap;
120  {
121  Tpetra::Details::ProfilingRegion regionImport("Tpetra::batchedApply: Import");
122  RCP<MV> X_colMapNonConst = Matrices[0]->getColumnMapMultiVector(X);
123 
124  // Import from the domain Map MV to the column Map MV.
125  X_colMapNonConst->doImport(X, *importer, INSERT);
126  X_colMap = rcp_const_cast<const MV>(X_colMapNonConst);
127  }
128 
129  for (size_type i = 0; i < N; i++) {
130  RCP<const export_type> exporter = Matrices[i]->getGraph()->getExporter();
131 
132  // Temporary MV for doExport (if needed),
133  RCP<MV> Y_rowMap = Matrices[i]->getRowMapMultiVector(*Y[i]);
134  if (!exporter.is_null()) {
135  Matrices[i]->localApply(*X_colMap, *Y_rowMap, Teuchos::NO_TRANS, alpha, ZERO);
136  {
137  Tpetra::Details::ProfilingRegion regionExport("Tpetra::batchedApply: Export");
138  if (Y_is_overwritten) {
139  Y[i]->putScalar(ZERO);
140  } else {
141  Y[i]->scale(beta);
142  }
143  Y[i]->doExport(*Y_rowMap, *exporter, ADD_ASSIGN);
144  }
145  } else { // Don't do an Export: row Map and range Map are the same.
146  // Check for aliasing
147  if (!Y[i]->isConstantStride() || X_colMap.getRawPtr() == Y[i]) {
148  Y_rowMap = Matrices[i]->getRowMapMultiVector(*Y[i], true);
149  if (beta != ZERO) {
150  Tpetra::deep_copy(*Y_rowMap, *Y[i]);
151  }
152 
153  Matrices[i]->localApply(*X_colMap, *Y_rowMap, Teuchos::NO_TRANS, alpha, beta);
154  Tpetra::deep_copy(*Y[i], *Y_rowMap);
155  } else {
156  Matrices[i]->localApply(*X_colMap, *Y[i], Teuchos::NO_TRANS, alpha, beta);
157  }
158  }
159  }
160  if (!params.is_null()) params->set("can batch", true);
161  } else {
162  /* Non-batching path */
163  for (size_type i = 0; i < N; i++) {
164  Matrices[i]->apply(X, *Y[i], Teuchos::NO_TRANS, alpha, beta);
165  }
166  if (!params.is_null()) params->set("can batch", false);
167  }
168 }
170 
171 } // namespace Tpetra
172 
173 #endif // TPETRA_APPLY_HELPERS_HPP
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
void batchedApply(const MatrixArray &Matrices, const typename std::remove_pointer< typename MultiVectorArray::value_type >::type &X, MultiVectorArray &Y, typename std::remove_pointer< typename MatrixArray::value_type >::type::scalar_type alpha=Teuchos::ScalarTraits< typename std::remove_pointer< typename MatrixArray::value_type >::type::scalar_type >::one(), typename std::remove_pointer< typename MatrixArray::value_type >::type::scalar_type beta=Teuchos::ScalarTraits< typename std::remove_pointer< typename MatrixArray::value_type >::type::scalar_type >::zero(), Teuchos::RCP< Teuchos::ParameterList > params=Teuchos::null)
Does multiply matrix apply() calls with a single X vector.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
Insert new values that don&#39;t currently exist.
Replace old values with zero.
Accumulate new values into existing values (may not be supported in all classes)