Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
Mapping from &quot;master&quot; local object type to the nonowning &quot;local view&quot; type that users see (as argumen...
Declaration of access intent for a global object.
Kokkos::DualView< impl_scalar_type **, Kokkos::LayoutLeft, execution_space > dual_view_type
Kokkos::DualView specialization used by this class.
One or more distributed dense vectors.
Declaration and definition of Tpetra::withLocalAccess; declaration of helper classes for users to spe...
A distributed dense vector.
Mapping from LocalAccess to the &quot;master&quot; local object type.