Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_DualView.hpp
Go to the documentation of this file.
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 3.0
6 // Copyright (2020) National Technology & Engineering
7 // Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44 
50 
51 #ifndef KOKKOS_DUALVIEW_HPP
52 #define KOKKOS_DUALVIEW_HPP
53 
54 #include <Kokkos_Core.hpp>
55 #include <impl/Kokkos_Error.hpp>
56 
57 namespace Kokkos {
58 
59 /* \class DualView
60  * \brief Container to manage mirroring a Kokkos::View that lives
61  * in device memory with a Kokkos::View that lives in host memory.
62  *
63  * This class provides capabilities to manage data which exists in two
64  * memory spaces at the same time. It keeps views of the same layout
65  * on two memory spaces as well as modified flags for both
66  * allocations. Users are responsible for setting the modified flags
67  * manually if they change the data in either memory space, by calling
68  * the sync() method templated on the device where they modified the
69  * data. Users may synchronize data by calling the modify() function,
70  * templated on the device towards which they want to synchronize
71  * (i.e., the target of the one-way copy operation).
72  *
73  * The DualView class also provides convenience methods such as
74  * realloc, resize and capacity which call the appropriate methods of
75  * the underlying Kokkos::View objects.
76  *
77  * The four template arguments are the same as those of Kokkos::View.
78  * (Please refer to that class' documentation for a detailed
79  * description.)
80  *
81  * \tparam DataType The type of the entries stored in the container.
82  *
83  * \tparam Layout The array's layout in memory.
84  *
85  * \tparam Device The Kokkos Device type. If its memory space is
86  * not the same as the host's memory space, then DualView will
87  * contain two separate Views: one in device memory, and one in
88  * host memory. Otherwise, DualView will only store one View.
89  *
90  * \tparam MemoryTraits (optional) The user's intended memory access
91  * behavior. Please see the documentation of Kokkos::View for
92  * examples. The default suffices for most users.
93  */
94 template <class DataType, class Arg1Type = void, class Arg2Type = void,
95  class Arg3Type = void>
96 class DualView : public ViewTraits<DataType, Arg1Type, Arg2Type, Arg3Type> {
97  template <class, class, class, class>
98  friend class DualView;
99 
100  public:
102 
103  typedef ViewTraits<DataType, Arg1Type, Arg2Type, Arg3Type> traits;
104 
106  typedef typename traits::host_mirror_space host_mirror_space;
107 
109  typedef View<typename traits::data_type, Arg1Type, Arg2Type, Arg3Type> t_dev;
110 
113  typedef typename t_dev::HostMirror t_host;
114 
117  typedef View<typename traits::const_data_type, Arg1Type, Arg2Type, Arg3Type>
118  t_dev_const;
119 
122  typedef typename t_dev_const::HostMirror t_host_const;
123 
125  typedef View<typename traits::const_data_type, typename traits::array_layout,
126  typename traits::device_type,
127  Kokkos::MemoryTraits<Kokkos::RandomAccess> >
128  t_dev_const_randomread;
129 
133  typedef typename t_dev_const_randomread::HostMirror t_host_const_randomread;
134 
136  typedef View<typename traits::data_type, typename traits::array_layout,
137  typename traits::device_type, MemoryUnmanaged>
138  t_dev_um;
139 
141  typedef View<typename t_host::data_type, typename t_host::array_layout,
142  typename t_host::device_type, MemoryUnmanaged>
143  t_host_um;
144 
146  typedef View<typename traits::const_data_type, typename traits::array_layout,
147  typename traits::device_type, MemoryUnmanaged>
148  t_dev_const_um;
149 
151  typedef View<typename t_host::const_data_type, typename t_host::array_layout,
152  typename t_host::device_type, MemoryUnmanaged>
153  t_host_const_um;
154 
156  typedef View<typename t_host::const_data_type, typename t_host::array_layout,
157  typename t_host::device_type,
158  Kokkos::MemoryTraits<Kokkos::Unmanaged | Kokkos::RandomAccess> >
159  t_dev_const_randomread_um;
160 
164  typedef
165  typename t_dev_const_randomread::HostMirror t_host_const_randomread_um;
166 
168 
170 
171  t_dev d_view;
172  t_host h_view;
173 
175 
177 
178 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE
179  protected:
180  // modified_flags[0] -> host
181  // modified_flags[1] -> device
182  typedef View<unsigned int[2], LayoutLeft, Kokkos::HostSpace> t_modified_flags;
183  t_modified_flags modified_flags;
184 
185  public:
186 #else
187  typedef View<unsigned int[2], LayoutLeft, typename t_host::execution_space>
188  t_modified_flags;
189  typedef View<unsigned int, LayoutLeft, typename t_host::execution_space>
190  t_modified_flag;
191  t_modified_flags modified_flags;
192  t_modified_flag modified_host, modified_device;
193 #endif
194 
196 
198 
204 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE
205  DualView() = default;
206 #else
207  DualView() : modified_flags(t_modified_flags("DualView::modified_flags")) {
208  modified_host = t_modified_flag(modified_flags, 0);
209  modified_device = t_modified_flag(modified_flags, 1);
210  }
211 #endif
212 
222  DualView(const std::string& label,
223  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
224  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
225  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
226  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
227  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
228  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
229  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
230  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
231  : d_view(label, n0, n1, n2, n3, n4, n5, n6, n7),
232  h_view(create_mirror_view(d_view)) // without UVM, host View mirrors
233  ,
234  modified_flags(t_modified_flags("DualView::modified_flags")) {
235 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
236  modified_host = t_modified_flag(modified_flags, 0);
237  modified_device = t_modified_flag(modified_flags, 1);
238 #endif
239  }
240 
251  template <class... P>
252  DualView(const Impl::ViewCtorProp<P...>& arg_prop,
253  typename std::enable_if<!Impl::ViewCtorProp<P...>::has_pointer,
254  size_t>::type const n0 =
255  KOKKOS_IMPL_CTOR_DEFAULT_ARG,
256  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
257  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
258  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
259  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
260  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
261  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
262  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
263  : d_view(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7),
264  h_view(create_mirror_view(d_view)) // without UVM, host View mirrors
265  ,
266  modified_flags(t_modified_flags("DualView::modified_flags")) {
267 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
268  modified_host = t_modified_flag(modified_flags, 0);
269  modified_device = t_modified_flag(modified_flags, 1);
270 #endif
271  }
272 
273  explicit inline DualView(const ViewAllocateWithoutInitializing& arg_prop,
274  const size_t arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
275  const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
276  const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
277  const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
278  const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
279  const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
280  const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
281  const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
282  : DualView(Impl::ViewCtorProp<std::string,
283  Kokkos::Impl::WithoutInitializing_t>(
284  arg_prop.label, Kokkos::WithoutInitializing),
285  arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6,
286  arg_N7) {}
287 
289  template <class SS, class LS, class DS, class MS>
290  DualView(const DualView<SS, LS, DS, MS>& src)
291  : d_view(src.d_view),
292  h_view(src.h_view),
293  modified_flags(src.modified_flags)
294 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
295  ,
296  modified_host(src.modified_host),
297  modified_device(src.modified_device)
298 #endif
299  {
300  }
301 
303  template <class SD, class S1, class S2, class S3, class Arg0, class... Args>
304  DualView(const DualView<SD, S1, S2, S3>& src, const Arg0& arg0, Args... args)
305  : d_view(Kokkos::subview(src.d_view, arg0, args...)),
306  h_view(Kokkos::subview(src.h_view, arg0, args...)),
307  modified_flags(src.modified_flags)
308 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
309  ,
310  modified_host(src.modified_host),
311  modified_device(src.modified_device)
312 #endif
313  {
314  }
315 
326  DualView(const t_dev& d_view_, const t_host& h_view_)
327  : d_view(d_view_),
328  h_view(h_view_),
329  modified_flags(t_modified_flags("DualView::modified_flags")) {
330  if (int(d_view.rank) != int(h_view.rank) ||
331  d_view.extent(0) != h_view.extent(0) ||
332  d_view.extent(1) != h_view.extent(1) ||
333  d_view.extent(2) != h_view.extent(2) ||
334  d_view.extent(3) != h_view.extent(3) ||
335  d_view.extent(4) != h_view.extent(4) ||
336  d_view.extent(5) != h_view.extent(5) ||
337  d_view.extent(6) != h_view.extent(6) ||
338  d_view.extent(7) != h_view.extent(7) ||
339  d_view.stride_0() != h_view.stride_0() ||
340  d_view.stride_1() != h_view.stride_1() ||
341  d_view.stride_2() != h_view.stride_2() ||
342  d_view.stride_3() != h_view.stride_3() ||
343  d_view.stride_4() != h_view.stride_4() ||
344  d_view.stride_5() != h_view.stride_5() ||
345  d_view.stride_6() != h_view.stride_6() ||
346  d_view.stride_7() != h_view.stride_7() ||
347  d_view.span() != h_view.span()) {
348  Kokkos::Impl::throw_runtime_exception(
349  "DualView constructed with incompatible views");
350  }
351 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
352  modified_host = t_modified_flag(modified_flags, 0);
353  modified_device = t_modified_flag(modified_flags, 1);
354 #endif
355  }
356 
358 
360 
377  template <class Device>
378  KOKKOS_INLINE_FUNCTION const typename Impl::if_c<
379  std::is_same<typename t_dev::memory_space,
380  typename Device::memory_space>::value,
381  t_dev, t_host>::type&
382  view() const {
383 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE
384  constexpr bool device_is_memspace =
385  std::is_same<Device, typename Device::memory_space>::value;
386  constexpr bool device_is_execspace =
387  std::is_same<Device, typename Device::execution_space>::value;
388  constexpr bool device_exec_is_t_dev_exec =
389  std::is_same<typename Device::execution_space,
390  typename t_dev::execution_space>::value;
391  constexpr bool device_mem_is_t_dev_mem =
392  std::is_same<typename Device::memory_space,
393  typename t_dev::memory_space>::value;
394  constexpr bool device_exec_is_t_host_exec =
395  std::is_same<typename Device::execution_space,
396  typename t_host::execution_space>::value;
397  constexpr bool device_mem_is_t_host_mem =
398  std::is_same<typename Device::memory_space,
399  typename t_host::memory_space>::value;
400  constexpr bool device_is_t_host_device =
401  std::is_same<typename Device::execution_space,
402  typename t_host::device_type>::value;
403  constexpr bool device_is_t_dev_device =
404  std::is_same<typename Device::memory_space,
405  typename t_host::device_type>::value;
406 
407  static_assert(
408  device_is_t_dev_device || device_is_t_host_device ||
409  (device_is_memspace &&
410  (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
411  (device_is_execspace &&
412  (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
413  ((!device_is_execspace && !device_is_memspace) &&
414  ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
415  (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
416  "Template parameter to .view() must exactly match one of the "
417  "DualView's device types or one of the execution or memory spaces");
418 #endif
419 
420  return Impl::if_c<std::is_same<typename t_dev::memory_space,
421  typename Device::memory_space>::value,
422  t_dev, t_host>::select(d_view, h_view);
423  }
424 
425  KOKKOS_INLINE_FUNCTION
426  t_host view_host() const { return h_view; }
427 
428  KOKKOS_INLINE_FUNCTION
429  t_dev view_device() const { return d_view; }
430 
431  template <class Device>
432  static int get_device_side() {
433  constexpr bool device_is_memspace =
434  std::is_same<Device, typename Device::memory_space>::value;
435  constexpr bool device_is_execspace =
436  std::is_same<Device, typename Device::execution_space>::value;
437  constexpr bool device_exec_is_t_dev_exec =
438  std::is_same<typename Device::execution_space,
439  typename t_dev::execution_space>::value;
440  constexpr bool device_mem_is_t_dev_mem =
441  std::is_same<typename Device::memory_space,
442  typename t_dev::memory_space>::value;
443  constexpr bool device_exec_is_t_host_exec =
444  std::is_same<typename Device::execution_space,
445  typename t_host::execution_space>::value;
446  constexpr bool device_mem_is_t_host_mem =
447  std::is_same<typename Device::memory_space,
448  typename t_host::memory_space>::value;
449  constexpr bool device_is_t_host_device =
450  std::is_same<typename Device::execution_space,
451  typename t_host::device_type>::value;
452  constexpr bool device_is_t_dev_device =
453  std::is_same<typename Device::memory_space,
454  typename t_host::device_type>::value;
455 
456 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE
457  static_assert(
458  device_is_t_dev_device || device_is_t_host_device ||
459  (device_is_memspace &&
460  (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
461  (device_is_execspace &&
462  (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
463  ((!device_is_execspace && !device_is_memspace) &&
464  ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
465  (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
466  "Template parameter to .sync() must exactly match one of the "
467  "DualView's device types or one of the execution or memory spaces");
468 #endif
469 
470 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE
471  int dev = -1;
472 #else
473  int dev = 0;
474 #endif
475  if (device_is_t_dev_device)
476  dev = 1;
477  else if (device_is_t_host_device)
478  dev = 0;
479  else {
480  if (device_is_memspace) {
481  if (device_mem_is_t_dev_mem) dev = 1;
482  if (device_mem_is_t_host_mem) dev = 0;
483  if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
484  }
485  if (device_is_execspace) {
486  if (device_exec_is_t_dev_exec) dev = 1;
487  if (device_exec_is_t_host_exec) dev = 0;
488  if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
489  }
490  if (!device_is_execspace && !device_is_memspace) {
491  if (device_mem_is_t_dev_mem) dev = 1;
492  if (device_mem_is_t_host_mem) dev = 0;
493  if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
494  if (device_exec_is_t_dev_exec) dev = 1;
495  if (device_exec_is_t_host_exec) dev = 0;
496  if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
497  }
498  }
499  return dev;
500  }
501 
519  template <class Device>
520  void sync(const typename std::enable_if<
521  (std::is_same<typename traits::data_type,
522  typename traits::non_const_data_type>::value) ||
523  (std::is_same<Device, int>::value),
524  int>::type& = 0) {
525  if (modified_flags.data() == nullptr) return;
526 
527  int dev = get_device_side<Device>();
528 
529  if (dev == 1) { // if Device is the same as DualView's device type
530  if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
531 #ifdef KOKKOS_ENABLE_CUDA
532  if (std::is_same<typename t_dev::memory_space,
533  Kokkos::CudaUVMSpace>::value) {
534  if (d_view.data() == h_view.data())
535  Kokkos::Impl::cuda_prefetch_pointer(
536  Kokkos::Cuda(), d_view.data(),
537  sizeof(typename t_dev::value_type) * d_view.span(), true);
538  }
539 #endif
540 
541  deep_copy(d_view, h_view);
542  modified_flags(0) = modified_flags(1) = 0;
543  }
544  }
545  if (dev == 0) { // hopefully Device is the same as DualView's host type
546  if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
547 #ifdef KOKKOS_ENABLE_CUDA
548  if (std::is_same<typename t_dev::memory_space,
549  Kokkos::CudaUVMSpace>::value) {
550  if (d_view.data() == h_view.data())
551  Kokkos::Impl::cuda_prefetch_pointer(
552  Kokkos::Cuda(), d_view.data(),
553  sizeof(typename t_dev::value_type) * d_view.span(), false);
554  }
555 #endif
556 
557  deep_copy(h_view, d_view);
558  modified_flags(0) = modified_flags(1) = 0;
559  }
560  }
561  if (std::is_same<typename t_host::memory_space,
562  typename t_dev::memory_space>::value) {
563  typename t_dev::execution_space().fence();
564  typename t_host::execution_space().fence();
565  }
566  }
567 
568  template <class Device>
569  void sync(const typename std::enable_if<
570  (!std::is_same<typename traits::data_type,
571  typename traits::non_const_data_type>::value) ||
572  (std::is_same<Device, int>::value),
573  int>::type& = 0) {
574  if (modified_flags.data() == nullptr) return;
575 
576  int dev = get_device_side<Device>();
577 
578  if (dev == 1) { // if Device is the same as DualView's device type
579  if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
580  Impl::throw_runtime_exception(
581  "Calling sync on a DualView with a const datatype.");
582  }
583  }
584  if (dev == 0) { // hopefully Device is the same as DualView's host type
585  if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
586  Impl::throw_runtime_exception(
587  "Calling sync on a DualView with a const datatype.");
588  }
589  }
590  }
591 
592  void sync_host() {
593  if (!std::is_same<typename traits::data_type,
594  typename traits::non_const_data_type>::value)
595  Impl::throw_runtime_exception(
596  "Calling sync_host on a DualView with a const datatype.");
597  if (modified_flags.data() == nullptr) return;
598  if (modified_flags(1) > modified_flags(0)) {
599 #ifdef KOKKOS_ENABLE_CUDA
600  if (std::is_same<typename t_dev::memory_space,
601  Kokkos::CudaUVMSpace>::value) {
602  if (d_view.data() == h_view.data())
603  Kokkos::Impl::cuda_prefetch_pointer(
604  Kokkos::Cuda(), d_view.data(),
605  sizeof(typename t_dev::value_type) * d_view.span(), false);
606  }
607 #endif
608 
609  deep_copy(h_view, d_view);
610  modified_flags(1) = modified_flags(0) = 0;
611  }
612  }
613 
614  void sync_device() {
615  if (!std::is_same<typename traits::data_type,
616  typename traits::non_const_data_type>::value)
617  Impl::throw_runtime_exception(
618  "Calling sync_device on a DualView with a const datatype.");
619  if (modified_flags.data() == nullptr) return;
620  if (modified_flags(0) > modified_flags(1)) {
621 #ifdef KOKKOS_ENABLE_CUDA
622  if (std::is_same<typename t_dev::memory_space,
623  Kokkos::CudaUVMSpace>::value) {
624  if (d_view.data() == h_view.data())
625  Kokkos::Impl::cuda_prefetch_pointer(
626  Kokkos::Cuda(), d_view.data(),
627  sizeof(typename t_dev::value_type) * d_view.span(), true);
628  }
629 #endif
630 
631  deep_copy(d_view, h_view);
632  modified_flags(1) = modified_flags(0) = 0;
633  }
634  }
635 
636  template <class Device>
637  bool need_sync() const {
638  if (modified_flags.data() == nullptr) return false;
639  int dev = get_device_side<Device>();
640 
641  if (dev == 1) { // if Device is the same as DualView's device type
642  if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
643  return true;
644  }
645  }
646  if (dev == 0) { // hopefully Device is the same as DualView's host type
647  if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
648  return true;
649  }
650  }
651  return false;
652  }
653 
654  inline bool need_sync_host() const {
655  if (modified_flags.data() == nullptr) return false;
656  return modified_flags(0) < modified_flags(1);
657  }
658 
659  inline bool need_sync_device() const {
660  if (modified_flags.data() == nullptr) return false;
661  return modified_flags(1) < modified_flags(0);
662  }
663 
669  template <class Device>
670  void modify() {
671  if (modified_flags.data() == nullptr) return;
672  int dev = get_device_side<Device>();
673 
674  if (dev == 1) { // if Device is the same as DualView's device type
675  // Increment the device's modified count.
676  modified_flags(1) =
677  (modified_flags(1) > modified_flags(0) ? modified_flags(1)
678  : modified_flags(0)) +
679  1;
680  }
681  if (dev == 0) { // hopefully Device is the same as DualView's host type
682  // Increment the host's modified count.
683  modified_flags(0) =
684  (modified_flags(1) > modified_flags(0) ? modified_flags(1)
685  : modified_flags(0)) +
686  1;
687  }
688 
689 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
690  if (modified_flags(0) && modified_flags(1)) {
691  std::string msg = "Kokkos::DualView::modify ERROR: ";
692  msg += "Concurrent modification of host and device views ";
693  msg += "in DualView \"";
694  msg += d_view.label();
695  msg += "\"\n";
696  Kokkos::abort(msg.c_str());
697  }
698 #endif
699  }
700 
701  inline void modify_host() {
702  if (modified_flags.data() != nullptr) {
703  modified_flags(0) =
704  (modified_flags(1) > modified_flags(0) ? modified_flags(1)
705  : modified_flags(0)) +
706  1;
707 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
708  if (modified_flags(0) && modified_flags(1)) {
709  std::string msg = "Kokkos::DualView::modify_host ERROR: ";
710  msg += "Concurrent modification of host and device views ";
711  msg += "in DualView \"";
712  msg += d_view.label();
713  msg += "\"\n";
714  Kokkos::abort(msg.c_str());
715  }
716 #endif
717  }
718  }
719 
720  inline void modify_device() {
721  if (modified_flags.data() != nullptr) {
722  modified_flags(1) =
723  (modified_flags(1) > modified_flags(0) ? modified_flags(1)
724  : modified_flags(0)) +
725  1;
726 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
727  if (modified_flags(0) && modified_flags(1)) {
728  std::string msg = "Kokkos::DualView::modify_device ERROR: ";
729  msg += "Concurrent modification of host and device views ";
730  msg += "in DualView \"";
731  msg += d_view.label();
732  msg += "\"\n";
733  Kokkos::abort(msg.c_str());
734  }
735 #endif
736  }
737  }
738 
739  inline void clear_sync_state() {
740  if (modified_flags.data() != nullptr)
741  modified_flags(1) = modified_flags(0) = 0;
742  }
743 
745 
747 
753  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
754  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
755  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
756  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
757  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
758  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
759  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
760  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
761  ::Kokkos::realloc(d_view, n0, n1, n2, n3, n4, n5, n6, n7);
762  h_view = create_mirror_view(d_view);
763 
764  /* Reset dirty flags */
765  if (modified_flags.data() == nullptr) {
766  modified_flags = t_modified_flags("DualView::modified_flags");
767  } else
768  modified_flags(1) = modified_flags(0) = 0;
769  }
770 
775  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
776  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
777  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
778  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
779  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
780  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
781  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
782  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
783  if (modified_flags.data() == nullptr) {
784  modified_flags = t_modified_flags("DualView::modified_flags");
785  }
786  if (modified_flags(1) >= modified_flags(0)) {
787  /* Resize on Device */
788  ::Kokkos::resize(d_view, n0, n1, n2, n3, n4, n5, n6, n7);
789  h_view = create_mirror_view(d_view);
790 
791  /* Mark Device copy as modified */
792  modified_flags(1) = modified_flags(1) + 1;
793 
794  } else {
795  /* Realloc on Device */
796 
797  ::Kokkos::realloc(d_view, n0, n1, n2, n3, n4, n5, n6, n7);
798 
799  const bool sizeMismatch =
800  (h_view.extent(0) != n0) || (h_view.extent(1) != n1) ||
801  (h_view.extent(2) != n2) || (h_view.extent(3) != n3) ||
802  (h_view.extent(4) != n4) || (h_view.extent(5) != n5) ||
803  (h_view.extent(6) != n6) || (h_view.extent(7) != n7);
804  if (sizeMismatch)
805  ::Kokkos::resize(h_view, n0, n1, n2, n3, n4, n5, n6, n7);
806 
807  t_host temp_view = create_mirror_view(d_view);
808 
809  /* Remap on Host */
810  Kokkos::deep_copy(temp_view, h_view);
811 
812  h_view = temp_view;
813 
814  d_view = create_mirror_view(typename t_dev::execution_space(), h_view);
815 
816  /* Mark Host copy as modified */
817  modified_flags(0) = modified_flags(0) + 1;
818  }
819  }
820 
822 
824 
825 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
826  size_t capacity() const { return d_view.span(); }
828 #endif
829 
831  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return d_view.span(); }
832 
833  KOKKOS_INLINE_FUNCTION bool span_is_contiguous() const {
834  return d_view.span_is_contiguous();
835  }
836 
838  template <typename iType>
839  void stride(iType* stride_) const {
840  d_view.stride(stride_);
841  }
842 
843  template <typename iType>
844  KOKKOS_INLINE_FUNCTION constexpr
845  typename std::enable_if<std::is_integral<iType>::value, size_t>::type
846  extent(const iType& r) const {
847  return d_view.extent(r);
848  }
849 
850  template <typename iType>
851  KOKKOS_INLINE_FUNCTION constexpr
852  typename std::enable_if<std::is_integral<iType>::value, int>::type
853  extent_int(const iType& r) const {
854  return static_cast<int>(d_view.extent(r));
855  }
856 
857 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
858  /* Deprecate all 'dimension' functions in favor of
859  * ISO/C++ vocabulary 'extent'.
860  */
861 
862  /* \brief return size of dimension 0 */
863  size_t dimension_0() const { return d_view.extent(0); }
864  /* \brief return size of dimension 1 */
865  size_t dimension_1() const { return d_view.extent(1); }
866  /* \brief return size of dimension 2 */
867  size_t dimension_2() const { return d_view.extent(2); }
868  /* \brief return size of dimension 3 */
869  size_t dimension_3() const { return d_view.extent(3); }
870  /* \brief return size of dimension 4 */
871  size_t dimension_4() const { return d_view.extent(4); }
872  /* \brief return size of dimension 5 */
873  size_t dimension_5() const { return d_view.extent(5); }
874  /* \brief return size of dimension 6 */
875  size_t dimension_6() const { return d_view.extent(6); }
876  /* \brief return size of dimension 7 */
877  size_t dimension_7() const { return d_view.extent(7); }
878 #endif
879 
881 };
882 
883 } // namespace Kokkos
884 
885 //----------------------------------------------------------------------------
886 //----------------------------------------------------------------------------
887 //
888 // Partial specializations of Kokkos::subview() for DualView objects.
889 //
890 
891 namespace Kokkos {
892 namespace Impl {
893 
894 template <class D, class A1, class A2, class A3, class... Args>
895 struct DualViewSubview {
896  typedef typename Kokkos::Impl::ViewMapping<
897  void, Kokkos::ViewTraits<D, A1, A2, A3>, Args...>::traits_type dst_traits;
898 
899  typedef Kokkos::DualView<
900  typename dst_traits::data_type, typename dst_traits::array_layout,
901  typename dst_traits::device_type, typename dst_traits::memory_traits>
902  type;
903 };
904 
905 } /* namespace Impl */
906 
907 template <class D, class A1, class A2, class A3, class... Args>
908 typename Impl::DualViewSubview<D, A1, A2, A3, Args...>::type subview(
909  const DualView<D, A1, A2, A3>& src, Args... args) {
910  return typename Impl::DualViewSubview<D, A1, A2, A3, Args...>::type(src,
911  args...);
912 }
913 
914 } /* namespace Kokkos */
915 
916 //----------------------------------------------------------------------------
917 //----------------------------------------------------------------------------
918 
919 namespace Kokkos {
920 
921 //
922 // Partial specialization of Kokkos::deep_copy() for DualView objects.
923 //
924 
925 template <class DT, class DL, class DD, class DM, class ST, class SL, class SD,
926  class SM>
927 void deep_copy(
928  DualView<DT, DL, DD, DM> dst, // trust me, this must not be a reference
929  const DualView<ST, SL, SD, SM>& src) {
930  if (src.need_sync_device()) {
931  deep_copy(dst.h_view, src.h_view);
932  dst.modify_host();
933  } else {
934  deep_copy(dst.d_view, src.d_view);
935  dst.modify_device();
936  }
937 }
938 
939 template <class ExecutionSpace, class DT, class DL, class DD, class DM,
940  class ST, class SL, class SD, class SM>
941 void deep_copy(
942  const ExecutionSpace& exec,
943  DualView<DT, DL, DD, DM> dst, // trust me, this must not be a reference
944  const DualView<ST, SL, SD, SM>& src) {
945  if (src.need_sync_device()) {
946  deep_copy(exec, dst.h_view, src.h_view);
947  dst.modify_host();
948  } else {
949  deep_copy(exec, dst.d_view, src.d_view);
950  dst.modify_device();
951  }
952 }
953 
954 } // namespace Kokkos
955 
956 //----------------------------------------------------------------------------
957 //----------------------------------------------------------------------------
958 
959 namespace Kokkos {
960 
961 //
962 // Non-member resize and realloc
963 //
964 
965 template <class... Properties, class... Args>
966 void resize(DualView<Properties...>& dv, Args&&... args) noexcept(
967  noexcept(dv.resize(std::forward<Args>(args)...))) {
968  dv.resize(std::forward<Args>(args)...);
969 }
970 
971 template <class... Properties, class... Args>
972 void realloc(DualView<Properties...>& dv, Args&&... args) noexcept(
973  noexcept(dv.realloc(std::forward<Args>(args)...))) {
974  dv.realloc(std::forward<Args>(args)...);
975 }
976 
977 } // end namespace Kokkos
978 
979 #endif
void deep_copy(const View< DT, DP...> &dst, typename ViewTraits< DT, DP...>::const_value_type &value, typename std::enable_if< std::is_same< typename ViewTraits< DT, DP...>::specialize, void >::value >::type *=nullptr)
Deep copy a value from Host memory into a view.
View< typename traits::non_const_data_type, typename traits::array_layout, Device< DefaultHostExecutionSpace, typename traits::host_mirror_space::memory_space > > HostMirror
Compatible HostMirror view.
std::enable_if< std::is_same< typename Kokkos::View< T, P...>::array_layout, Kokkos::LayoutLeft >::value||std::is_same< typename Kokkos::View< T, P...>::array_layout, Kokkos::LayoutRight >::value >::type resize(Kokkos::View< T, P...> &v, const size_t n0=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n1=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n2=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n3=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n4=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n5=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n6=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n7=KOKKOS_IMPL_CTOR_DEFAULT_ARG)
Resize a view with copying old data to new data at the corresponding indices.
std::enable_if< std::is_same< typename Kokkos::View< T, P...>::array_layout, Kokkos::LayoutLeft >::value||std::is_same< typename Kokkos::View< T, P...>::array_layout, Kokkos::LayoutRight >::value >::type realloc(Kokkos::View< T, P...> &v, const size_t n0=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n1=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n2=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n3=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n4=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n5=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n6=KOKKOS_IMPL_CTOR_DEFAULT_ARG, const size_t n7=KOKKOS_IMPL_CTOR_DEFAULT_ARG)
Resize a view with discarding old data.
Traits class for accessing attributes of a View.