Tpetra parallel linear algebra  Version of the Day
Tpetra_withLocalAccess_MultiVector.hpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Tpetra: Templated Linear Algebra Services Package
6 // Copyright (2008) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ************************************************************************
41 // @HEADER
42 */
43 
44 #ifndef TPETRA_WITHLOCALACCESS_MULTIVECTOR_HPP
45 #define TPETRA_WITHLOCALACCESS_MULTIVECTOR_HPP
46 
48 #include "Tpetra_MultiVector.hpp"
49 #include "Tpetra_Vector.hpp"
50 #include <memory>
51 
55 
56 namespace Tpetra {
57  namespace Details {
58 
60  template<class SC, class LO, class GO, class NT,
61  class MemorySpace,
62  const AccessMode am>
65  Tpetra::MultiVector<SC, LO, GO, NT>, MemorySpace, am> >
66  {
67  public:
68  using local_access_type =
70  private:
72 
73  // FIXME (mfh 22 Oct 2018, 25 Apr 2019) Need to make sure that
74  // the execution space matches. If not, we would need to
75  // allocate a new View, and then we should actually make the
76  // std::unique_ptr's destructor "copy back." This is why
77  // master_local_object_type is a std::unique_ptr<view_type>, not
78  // just a view_type.
79  //
80  // mfh 01 May 2019: For now, we avoid allocation and copy back,
81  // by using only the Views available in the MV's DualView.
82  using dual_view_type = typename global_object_type::dual_view_type;
83 
84  // MemorySpace=CudaSpace: false.
85  // MemorySpace=CudaUVMSpace: false.
86  // MemorySpace=CudaHostPinnedSpace: true.
87  // MemorySpace=HostSpace: true.
88  static constexpr bool is_host =
89  std::is_same<
90  typename MemorySpace::execution_space::memory_space,
91  Kokkos::HostSpace>::value;
92 
93  public:
94  // This alias is for the MultiVector specialization of
95  // GetNonowningLocalObject. withLocalAccess itself does not
96  // need this to be public.
97  //
98  // Owning View type is always a View of nonconst. If you own
99  // the data, you need to be able to modify them.
100  using master_local_view_type = typename std::conditional<
101  is_host,
102  typename dual_view_type::t_host,
103  typename dual_view_type::t_dev>::type;
104 
105  static_assert
106  (static_cast<int> (master_local_view_type::Rank) == 2,
107  "Rank of master_local_view_type must be 2. "
108  "Please report this bug to the Tpetra developers.");
109 
110  // This alias is required by withLocalAccess.
111  using master_local_object_type =
112  std::unique_ptr<master_local_view_type>;
113 
114  // This method is required by withLocalAccess.
115  static master_local_object_type
116  get (local_access_type LA)
117  {
118  if (LA.isValid ()) {
119  // Intel 17.0.1 requires the static_cast. Otherwise, you'll
120  // get build errors of the form "error: a built-in binary
121  // operator applied to a scoped enumeration requires two
122  // operands of the same type."
123  if (static_cast<AccessMode> (am) == AccessMode::WriteOnly) {
124  LA.G_.clear_sync_state ();
125  }
126 
127  // mfh 06 Jun 2019: It could be that
128  // Kokkos::DefaultHostExecutionSpace != the Vector's
129  // execution_space. For example, the first could be
130  // Kokkos::OpenMP, but the second could be Kokkos::Serial.
131  // That's why we go through the trouble below.
132  //
133  // It's easier to use an execution space than a memory
134  // space. Otherwise, DualView of CudaUVMSpace complains
135  // that HostSpace is not one of its two memory spaces.
136  // (Both the device and the host Views of a DualView of
137  // CudaUVMSpace have memory_space = CudaUVMSpace.)
138  using space = typename std::conditional<is_host,
139  typename dual_view_type::t_host::execution_space,
140  typename dual_view_type::t_dev::execution_space>::type;
141 
142  if (LA.G_.template need_sync<space> ()) {
143  LA.G_.template sync<space> ();
144  }
145  // Intel 17.0.1 requires the static_cast. Otherwise, you'll
146  // get build errors of the form "error: a built-in binary
147  // operator applied to a scoped enumeration requires two
148  // operands of the same type."
149  if (static_cast<AccessMode> (am) != AccessMode::ReadOnly) {
150  LA.G_.template modify<space> ();
151  }
152 
153  // See note about "copy back" above.
154  auto G_lcl_2d = LA.G_.template getLocalView<space> ();
155  // This converts the View to const if applicable.
156  // Once we can use C++14, switch to std::make_unique.
157  return std::unique_ptr<master_local_view_type>
158  (new master_local_view_type (G_lcl_2d));
159  }
160  else { // invalid; return "null" Kokkos::View
161  return std::unique_ptr<master_local_view_type>
162  (new master_local_view_type ());
163  }
164  }
165  };
166 
168  template<class SC, class LO, class GO, class NT,
169  class MemorySpace,
170  const Details::AccessMode am>
172  LocalAccess<
173  Tpetra::Vector<SC, LO, GO, NT>, MemorySpace, am> >
174  {
175  private:
182  using parent_master_local_view_type =
183  typename mv_gmlo::master_local_view_type;
184  using dual_view_type =
186  static constexpr bool is_host = std::is_same<
187  typename MemorySpace::execution_space::memory_space,
188  Kokkos::HostSpace>::value;
189 
190  public:
191  using local_access_type =
193 
194  public:
195  // This alias is for the Vector specialization of
196  // GetNonowningLocalObject. withLocalAccess itself does not
197  // need this to be public.
198  using master_local_view_type = decltype (Kokkos::subview
199  (parent_master_local_view_type (), Kokkos::ALL (), 0));
200 
201  static_assert
202  (static_cast<int> (master_local_view_type::Rank) == 1,
203  "Rank of master_local_view_type must be 1. "
204  "Please report this bug to the Tpetra developers.");
205 
206  // This alias is required by withLocalAccess.
207  using master_local_object_type =
208  std::unique_ptr<master_local_view_type>;
209 
210  // This method is required by withLocalAccess.
211  static master_local_object_type
212  get (local_access_type LA)
213  {
214  if (LA.isValid ()) {
215  // Intel 17.0.1 requires the static_cast. Otherwise, you'll
216  // get build errors of the form "error: a built-in binary
217  // operator applied to a scoped enumeration requires two
218  // operands of the same type."
219  if (static_cast<AccessMode> (am) == AccessMode::WriteOnly) {
220  LA.G_.clear_sync_state ();
221  }
222 
223  // mfh 06 Jun 2019: It could be that
224  // Kokkos::DefaultHostExecutionSpace != the Vector's
225  // execution_space. For example, the first could be
226  // Kokkos::OpenMP, but the second could be Kokkos::Serial.
227  // That's why we go through the trouble below.
228  //
229  // It's easier to use an execution space than a memory
230  // space. Otherwise, DualView of CudaUVMSpace complains
231  // that HostSpace is not one of its two memory spaces.
232  // (Both the device and the host Views of a DualView of
233  // CudaUVMSpace have memory_space = CudaUVMSpace.)
234  using space = typename std::conditional<is_host,
235  typename dual_view_type::t_host::execution_space,
236  typename dual_view_type::t_dev::execution_space>::type;
237 
238  if (LA.G_.template need_sync<space> ()) {
239  LA.G_.template sync<space> ();
240  }
241  // Intel 17.0.1 requires the static_cast. Otherwise, you'll
242  // get build errors of the form "error: a built-in binary
243  // operator applied to a scoped enumeration requires two
244  // operands of the same type."
245  if (static_cast<AccessMode> (am) != AccessMode::ReadOnly) {
246  LA.G_.template modify<space> ();
247  }
248 
249  // See note about "copy back" above.
250  auto G_lcl_2d = LA.G_.template getLocalView<space> ();
251  auto G_lcl_1d = Kokkos::subview (G_lcl_2d, Kokkos::ALL (), 0);
252  // This converts the View to const if applicable.
253  // Once we can use C++14, switch to std::make_unique.
254  return std::unique_ptr<master_local_view_type>
255  (new master_local_view_type (G_lcl_1d));
256  }
257  else { // invalid; return "null" Kokkos::View
258  return std::unique_ptr<master_local_view_type>
259  (new master_local_view_type ());
260  }
261  }
262  };
263 
266  template<class SC, class LO, class GO, class NT,
267  class MemorySpace,
268  const AccessMode am>
270  LocalAccess<
271  Tpetra::MultiVector<SC, LO, GO, NT>, MemorySpace, am> >
272  {
273  public:
275  Tpetra::MultiVector<SC, LO, GO, NT>, MemorySpace, am>;
276 
277  private:
278  using input_view_type =
280  // input_view_type::non_const_data_type is
281  // MV::impl_scalar_type**, where
282  // MV = Tpetra::MultiVector<SC, LO, GO, NT>.
283  //
284  // Intel 17.0.1 requires the static_cast. Otherwise, you'll get
285  // build errors of the form "error: a built-in binary operator
286  // applied to a scoped enumeration requires two operands of the
287  // same type."
288  using output_data_type = typename std::conditional<
289  static_cast<AccessMode> (am) == AccessMode::ReadOnly,
290  typename input_view_type::const_data_type,
291  typename input_view_type::non_const_data_type>::type;
292  using output_view_type =
293  Kokkos::View<output_data_type,
294  typename input_view_type::array_layout,
295  typename input_view_type::device_type,
296  Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
297  public:
298  using master_local_object_type =
300  using nonowning_local_object_type = output_view_type;
301 
302  static nonowning_local_object_type
303  get (local_access_type /* LA */,
304  const master_local_object_type& M)
305  {
306  input_view_type* viewPtr = M.get ();
307  return viewPtr == nullptr ?
308  nonowning_local_object_type () :
309  nonowning_local_object_type (*viewPtr);
310  }
311  };
312 
315  template<class SC, class LO, class GO, class NT,
316  class MemorySpace,
317  const AccessMode am>
319  LocalAccess<
320  ::Tpetra::Vector<SC, LO, GO, NT>, MemorySpace, am> >
321  {
322  public:
324  Tpetra::Vector<SC, LO, GO, NT>, MemorySpace, am>;
325 
326  private:
327  using input_view_type =
329  // input_view_type::non_const_data_type is V::impl_scalar_type*,
330  // where V = Tpetra::Vector<SC, LO, GO, NT>.
331  //
332  // Intel 17.0.1 requires the static_cast. Otherwise, you'll get
333  // build errors of the form "error: a built-in binary operator
334  // applied to a scoped enumeration requires two operands of the
335  // same type."
336  using output_data_type = typename std::conditional<
337  static_cast<AccessMode> (am) == AccessMode::ReadOnly,
338  typename input_view_type::const_data_type,
339  typename input_view_type::non_const_data_type>::type;
340  using output_view_type =
341  Kokkos::View<output_data_type,
342  typename input_view_type::array_layout,
343  typename input_view_type::device_type,
344  Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
345  public:
346  using master_local_object_type =
348  using nonowning_local_object_type = output_view_type;
349 
350  static nonowning_local_object_type
351  get (local_access_type /* LA */,
352  const master_local_object_type& M)
353  {
354  input_view_type* viewPtr = M.get ();
355  return viewPtr == nullptr ?
356  nonowning_local_object_type () :
357  nonowning_local_object_type (*viewPtr);
358  }
359  };
360  } // namespace Details
361 } // namespace Tpetra
362 
363 #endif // TPETRA_WITHLOCALACCESS_MULTIVECTOR_HPP
364 
Declaration and definition of Tpetra::withLocalAccess; declaration of helper classes for users to spe...
Declaration of access intent for a global object.
global_object_type & G_
Reference to the global object whose data the user will access.
bool isValid() const
Is access supposed to be valid? (See valid() above.)
One or more distributed dense vectors.
Kokkos::DualView< impl_scalar_type **, Kokkos::LayoutLeft, execution_space > dual_view_type
Kokkos::DualView specialization used by this class.
A distributed dense vector.
Implementation details of Tpetra.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Mapping from LocalAccess to the "master" local object type.
Mapping from "master" local object type to the nonowning "local view" type that users see (as argumen...