Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_checkView.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // ************************************************************************
38 // @HEADER
39 
40 #ifndef TPETRA_DETAILS_CHECKVIEW_HPP
41 #define TPETRA_DETAILS_CHECKVIEW_HPP
42 
49 
52 #include "Kokkos_DualView.hpp"
53 #include "Teuchos_TypeNameTraits.hpp"
54 #include "Teuchos_Comm.hpp"
55 #include "Teuchos_CommHelpers.hpp"
56 #include <sstream>
57 
58 namespace Tpetra {
59 namespace Details {
60 
61 template<class ExecutionSpace>
62 bool
64  const ExecutionSpace& space);
65 
66 std::string memorySpaceName (const void* ptr);
67 
95 template<class DataType, class ... Properties>
96 bool
98  (std::ostream* lclErrStrm,
99  const int myMpiProcessRank,
100  const Kokkos::View<DataType, Properties...>& view)
101 {
102  using Teuchos::TypeNameTraits;
103  using std::endl;
104  using view_type = Kokkos::View<DataType, Properties...>;
105  using ES = typename view_type::execution_space;
106 
107  if (view.size () == 0) {
108  // Kokkos::View can be zero size with a nonnull pointer.
109  // Even std::vector can have this behavior.
110  return true;
111  }
112  else { // nonzero size
113  auto ptr = view.data ();
114 
115  if (ptr == nullptr) {
116  if (lclErrStrm != nullptr) {
117  const std::string viewName = TypeNameTraits<view_type>::name ();
118  *lclErrStrm << "Proc " << myMpiProcessRank << ": Kokkos::View "
119  "of type " << viewName << " has nonzero size " << view.size ()
120  << " but a null pointer." << endl;
121  }
122  return false;
123  }
124  else { // nonnull pointer, nonzero size
125  const bool canAcc = pointerAccessibleFromExecutionSpace (ptr, ES ());
126  if (! canAcc && lclErrStrm != nullptr) {
127  const std::string viewName = TypeNameTraits<view_type>::name ();
128  const std::string esName = TypeNameTraits<ES>::name ();
129  *lclErrStrm << "Proc " << myMpiProcessRank << ": Kokkos::View "
130  "of type " << viewName << " and nonzero size " << view.size ()
131  << " has a pointer " << ptr << " which is nonnull, but not "
132  "accessible from the View's claimed execution space "
133  << esName << ". As far as I can tell, the View's pointer "
134  "(view.data()) lives in memory space " << memorySpaceName (ptr)
135  << "." << endl;
136  }
137  return canAcc;
138  }
139  }
140 }
141 
145 template<class DataType ,
146  class Arg1Type = void ,
147  class Arg2Type = void ,
148  class Arg3Type = void>
149 bool
151  (std::ostream* const lclErrStrm,
152  const int myMpiProcessRank,
153  const Kokkos::DualView<DataType, Arg1Type, Arg2Type, Arg3Type>& dv)
154 {
155  const bool dev_good =
156  checkLocalViewValidity (lclErrStrm, myMpiProcessRank,
157  dv.view_device ());
158  const bool host_good =
159  checkLocalViewValidity (lclErrStrm, myMpiProcessRank,
160  dv.view_host ());
161  const bool good = dev_good && host_good;
162  if (! good && lclErrStrm != nullptr) {
163  using Teuchos::TypeNameTraits;
164  using std::endl;
165  using dv_type =
166  Kokkos::DualView<DataType, Arg1Type, Arg2Type, Arg3Type>;
167 
168  const std::string dvName = TypeNameTraits<dv_type>::name ();
169  *lclErrStrm << "Proc " << myMpiProcessRank << ": Kokkos::DualView "
170  "of type " << dvName << " has one or more invalid Views. See "
171  "above error messages from this MPI process for details." << endl;
172  }
173  return good;
174 }
175 
176 template<class DataType ,
177  class Arg1Type = void ,
178  class Arg2Type = void ,
179  class Arg3Type = void>
180 bool
181 checkGlobalDualViewValidity
182 (std::ostream* const gblErrStrm,
183  const Kokkos::DualView<DataType, Arg1Type, Arg2Type, Arg3Type>& dv,
184  const bool verbose,
185  const Teuchos::Comm<int>* const comm)
186 {
187  using std::endl;
188  const int myRank = comm == nullptr ? 0 : comm->getRank ();
189  std::ostringstream lclErrStrm;
190  int lclSuccess = 1;
191 
192  try {
193  const bool lclValid =
194  checkLocalDualViewValidity (&lclErrStrm, myRank, dv);
195  lclSuccess = lclValid ? 1 : 0;
196  }
197  catch (std::exception& e) {
198  lclErrStrm << "Proc " << myRank << ": checkLocalDualViewValidity "
199  "threw an exception: " << e.what () << endl;
200  lclSuccess = 0;
201  }
202  catch (...) {
203  lclErrStrm << "Proc " << myRank << ": checkLocalDualViewValidity "
204  "threw an exception not a subclass of std::exception." << endl;
205  lclSuccess = 0;
206  }
207 
208  int gblSuccess = 0; // output argument
209  if (comm == nullptr) {
210  gblSuccess = lclSuccess;
211  }
212  else {
213  using Teuchos::outArg;
214  using Teuchos::REDUCE_MIN;
215  using Teuchos::reduceAll;
216  reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
217  }
218 
219  if (gblSuccess != 1 && gblErrStrm != nullptr) {
220  *gblErrStrm << "On at least one (MPI) process, the "
221  "Kokkos::DualView has either device or host pointer that "
222  "is not accessible from the corresponding execution space. "
223  "This can happen if you, the user, created the DualView "
224  "with raw pointer(s) that is/are not in the correct memory "
225  "space. For example, you may have a Kokkos::DualView whose "
226  "device memory_space is Kokkos::CudaUVMSpace, but you gave "
227  "the device View's constructor a raw host pointer. It may "
228  "also happen if either the device or host pointer in the "
229  "DualView is null, but the DualView has a nonzero number of "
230  "rows. For more detailed information, please rerun with the "
231  "TPETRA_VERBOSE environment variable set to 1. (You do not "
232  "need to recompile.)";
233  if (verbose) {
234  *gblErrStrm << " Here are error messages from all "
235  "processes:" << endl;
236  if (comm == nullptr) {
237  *gblErrStrm << lclErrStrm.str ();
238  }
239  else {
241  gathervPrint (*gblErrStrm, lclErrStrm.str (), *comm);
242  }
243  }
244  *gblErrStrm << endl;
245  }
246  return gblSuccess == 1;
247 }
248 
249 } // namespace Details
250 } // namespace Tpetra
251 
252 #endif // TPETRA_DETAILS_CHECKVIEW_HPP
bool checkLocalDualViewValidity(std::ostream *const lclErrStrm, const int myMpiProcessRank, const Kokkos::DualView< DataType, Arg1Type, Arg2Type, Arg3Type > &dv)
Is the given Kokkos::DualView valid?
std::string memorySpaceName(const void *ptr)
Return the Kokkos memory space name (without &quot;Kokkos::&quot;) corresponding to the given nonnull pointer...
Declaration of functions for checking whether a given pointer is accessible from a given Kokkos execu...
Declaration of a function that prints strings from each process.
bool pointerAccessibleFromExecutionSpace(const void *ptr, const ExecutionSpace &space)
Is the given nonnull ptr accessible from the given execution space?
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
bool checkLocalViewValidity(std::ostream *lclErrStrm, const int myMpiProcessRank, const Kokkos::View< DataType, Properties...> &view)
Is the given View valid?