23 #ifndef KOKKOS_DUALVIEW_HPP
24 #define KOKKOS_DUALVIEW_HPP
25 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
26 #define KOKKOS_IMPL_PUBLIC_INCLUDE
27 #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
30 #include <Kokkos_Core.hpp>
31 #include <impl/Kokkos_Error.hpp>
73 #ifdef KOKKOS_ENABLE_CUDA
75 inline const Kokkos::Cuda& get_cuda_space(
const Kokkos::Cuda& in) {
return in; }
77 inline const Kokkos::Cuda& get_cuda_space() {
78 return *Kokkos::Impl::cuda_get_deep_copy_space();
81 template <
typename NonCudaExecSpace>
82 inline const Kokkos::Cuda& get_cuda_space(
const NonCudaExecSpace&) {
83 return get_cuda_space();
86 #endif // KOKKOS_ENABLE_CUDA
90 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
91 template <
class DataType,
class Arg1Type = void,
class Arg2Type = void,
92 class Arg3Type =
void>
95 template <
class DataType,
class... Properties>
100 struct is_dual_view :
public std::false_type {};
102 template <
class DT,
class... DP>
103 struct is_dual_view<DualView<DT, DP...>> :
public std::true_type {};
105 template <
class DT,
class... DP>
106 struct is_dual_view<const DualView<DT, DP...>> :
public std::true_type {};
109 inline constexpr
bool is_dual_view_v = is_dual_view<T>::value;
111 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
112 template <
class DataType,
class Arg1Type,
class Arg2Type,
class Arg3Type>
113 class DualView :
public ViewTraits<DataType, Arg1Type, Arg2Type, Arg3Type> {
114 template <
class,
class,
class,
class>
116 template <
class DataType,
class... Properties>
117 class DualView :
public ViewTraits<DataType, Properties...> {
118 template <
class,
class...>
120 friend class DualView;
125 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
126 using traits = ViewTraits<DataType, Arg1Type, Arg2Type, Arg3Type>;
128 using traits = ViewTraits<DataType, Properties...>;
132 using host_mirror_space =
typename traits::host_mirror_space;
135 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
136 using t_dev = View<typename traits::data_type, Arg1Type, Arg2Type, Arg3Type>;
138 using t_dev =
View<
typename traits::data_type, Properties...>;
147 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
149 View<typename traits::const_data_type, Arg1Type, Arg2Type, Arg3Type>;
151 using t_dev_const =
View<
typename traits::const_data_type, Properties...>;
159 using t_dev_const_randomread =
160 View<
typename traits::const_data_type,
typename traits::array_layout,
161 typename traits::device_type,
162 Kokkos::MemoryTraits<Kokkos::RandomAccess>>;
171 View<
typename traits::data_type,
typename traits::array_layout,
172 typename traits::device_type, MemoryUnmanaged>;
176 View<
typename t_host::data_type,
typename t_host::array_layout,
177 typename t_host::device_type, MemoryUnmanaged>;
180 using t_dev_const_um =
181 View<
typename traits::const_data_type,
typename traits::array_layout,
182 typename traits::device_type, MemoryUnmanaged>;
185 using t_host_const_um =
186 View<
typename t_host::const_data_type,
typename t_host::array_layout,
187 typename t_host::device_type, MemoryUnmanaged>;
190 using t_dev_const_randomread_um =
191 View<
typename t_host::const_data_type,
typename t_host::array_layout,
192 typename t_host::device_type,
193 Kokkos::MemoryTraits<Kokkos::Unmanaged | Kokkos::RandomAccess>>;
198 using t_host_const_randomread_um =
208 using t_modified_flags = View<unsigned int[2], LayoutLeft, Kokkos::HostSpace>;
209 t_modified_flags modified_flags;
230 DualView() =
default;
241 DualView(
const std::string& label,
242 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
243 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
244 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
245 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
246 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
247 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
248 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
249 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
251 Kokkos::view_alloc(typename t_modified_flags::execution_space{},
252 "DualView::modified_flags")),
253 d_view(label, n0, n1, n2, n3, n4, n5, n6, n7),
254 h_view(create_mirror_view(d_view))
267 template <
class... P>
268 DualView(
const Impl::ViewCtorProp<P...>& arg_prop,
269 std::enable_if_t<!Impl::ViewCtorProp<P...>::has_pointer,
270 size_t>
const n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
271 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
272 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
273 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
274 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
275 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
276 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
277 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
278 : modified_flags(t_modified_flags(
"DualView::modified_flags")),
279 d_view(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7) {
281 if constexpr (Kokkos::Impl::has_type<Impl::WithoutInitializing_t,
283 h_view = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, d_view);
285 h_view = Kokkos::create_mirror_view(d_view);
289 template <typename DT, typename... DP>
290 DualView(const DualView<DT, DP...>& src)
291 : modified_flags(src.modified_flags),
293 h_view(src.h_view) {}
296 template <
class DT,
class... DP,
class Arg0,
class... Args>
297 DualView(
const DualView<DT, DP...>& src,
const Arg0& arg0, Args... args)
298 : modified_flags(src.modified_flags),
299 d_view(Kokkos::subview(src.d_view, arg0, args...)),
300 h_view(Kokkos::subview(src.h_view, arg0, args...)) {}
312 DualView(
const t_dev& d_view_,
const t_host& h_view_)
313 : modified_flags(t_modified_flags(
"DualView::modified_flags")),
316 if (
int(d_view.rank) !=
int(h_view.rank) ||
317 d_view.extent(0) != h_view.extent(0) ||
318 d_view.extent(1) != h_view.extent(1) ||
319 d_view.extent(2) != h_view.extent(2) ||
320 d_view.extent(3) != h_view.extent(3) ||
321 d_view.extent(4) != h_view.extent(4) ||
322 d_view.extent(5) != h_view.extent(5) ||
323 d_view.extent(6) != h_view.extent(6) ||
324 d_view.extent(7) != h_view.extent(7) ||
325 d_view.stride_0() != h_view.stride_0() ||
326 d_view.stride_1() != h_view.stride_1() ||
327 d_view.stride_2() != h_view.stride_2() ||
328 d_view.stride_3() != h_view.stride_3() ||
329 d_view.stride_4() != h_view.stride_4() ||
330 d_view.stride_5() != h_view.stride_5() ||
331 d_view.stride_6() != h_view.stride_6() ||
332 d_view.stride_7() != h_view.stride_7() ||
333 d_view.span() != h_view.span()) {
334 Kokkos::Impl::throw_runtime_exception(
335 "DualView constructed with incompatible views");
339 struct impl_dualview_is_single_device {
341 value = std::is_same<
typename t_dev::device_type,
342 typename t_host::device_type>::value
347 template <
typename Device>
348 struct impl_device_matches_tdev_device {
350 value = std::is_same<typename t_dev::device_type, Device>::value
354 template <
typename Device>
355 struct impl_device_matches_thost_device {
357 value = std::is_same<typename t_host::device_type, Device>::value
362 template <
typename Device>
363 struct impl_device_matches_thost_exec {
365 value = std::is_same<typename t_host::execution_space, Device>::value
370 template <
typename Device>
371 struct impl_device_matches_tdev_exec {
373 value = std::is_same<typename t_dev::execution_space, Device>::value
378 template <
typename Device>
379 struct impl_device_matches_tdev_memory_space {
381 value = std::is_same<
typename t_dev::memory_space,
382 typename Device::memory_space>::value
412 template <
class Device>
413 KOKKOS_INLINE_FUNCTION
const typename std::conditional_t<
414 impl_device_matches_tdev_device<Device>::value, t_dev,
415 typename std::conditional_t<
416 impl_device_matches_thost_device<Device>::value, t_host,
417 typename std::conditional_t<
418 impl_device_matches_thost_exec<Device>::value, t_host,
419 typename std::conditional_t<
420 impl_device_matches_tdev_exec<Device>::value, t_dev,
421 typename std::conditional_t<
422 impl_device_matches_tdev_memory_space<Device>::value,
425 constexpr
bool device_is_memspace =
426 std::is_same<Device, typename Device::memory_space>::value;
427 constexpr
bool device_is_execspace =
428 std::is_same<Device, typename Device::execution_space>::value;
429 constexpr
bool device_exec_is_t_dev_exec =
430 std::is_same<
typename Device::execution_space,
431 typename t_dev::execution_space>::value;
432 constexpr
bool device_mem_is_t_dev_mem =
433 std::is_same<
typename Device::memory_space,
434 typename t_dev::memory_space>::value;
435 constexpr
bool device_exec_is_t_host_exec =
436 std::is_same<
typename Device::execution_space,
437 typename t_host::execution_space>::value;
438 constexpr
bool device_mem_is_t_host_mem =
439 std::is_same<
typename Device::memory_space,
440 typename t_host::memory_space>::value;
441 constexpr
bool device_is_t_host_device =
442 std::is_same<
typename Device::execution_space,
443 typename t_host::device_type>::value;
444 constexpr
bool device_is_t_dev_device =
445 std::is_same<
typename Device::memory_space,
446 typename t_host::device_type>::value;
449 device_is_t_dev_device || device_is_t_host_device ||
450 (device_is_memspace &&
451 (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
452 (device_is_execspace &&
453 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
454 ((!device_is_execspace && !device_is_memspace) &&
455 ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
456 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
457 "Template parameter to .view() must exactly match one of the "
458 "DualView's device types or one of the execution or memory spaces");
460 return Impl::if_c<std::is_same<
typename t_dev::memory_space,
461 typename Device::memory_space>::value,
462 t_dev, t_host>::select(d_view, h_view);
465 KOKKOS_INLINE_FUNCTION
466 t_host view_host()
const {
return h_view; }
468 KOKKOS_INLINE_FUNCTION
469 t_dev view_device()
const {
return d_view; }
471 KOKKOS_INLINE_FUNCTION constexpr
bool is_allocated()
const {
472 return (d_view.is_allocated() && h_view.is_allocated());
475 template <
class Device>
476 static int get_device_side() {
477 constexpr
bool device_is_memspace =
478 std::is_same<Device, typename Device::memory_space>::value;
479 constexpr
bool device_is_execspace =
480 std::is_same<Device, typename Device::execution_space>::value;
481 constexpr
bool device_exec_is_t_dev_exec =
482 std::is_same<
typename Device::execution_space,
483 typename t_dev::execution_space>::value;
484 constexpr
bool device_mem_is_t_dev_mem =
485 std::is_same<
typename Device::memory_space,
486 typename t_dev::memory_space>::value;
487 constexpr
bool device_exec_is_t_host_exec =
488 std::is_same<
typename Device::execution_space,
489 typename t_host::execution_space>::value;
490 constexpr
bool device_mem_is_t_host_mem =
491 std::is_same<
typename Device::memory_space,
492 typename t_host::memory_space>::value;
493 constexpr
bool device_is_t_host_device =
494 std::is_same<
typename Device::execution_space,
495 typename t_host::device_type>::value;
496 constexpr
bool device_is_t_dev_device =
497 std::is_same<
typename Device::memory_space,
498 typename t_host::device_type>::value;
501 device_is_t_dev_device || device_is_t_host_device ||
502 (device_is_memspace &&
503 (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
504 (device_is_execspace &&
505 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
506 ((!device_is_execspace && !device_is_memspace) &&
507 ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
508 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
509 "Template parameter to .sync() must exactly match one of the "
510 "DualView's device types or one of the execution or memory spaces");
513 if (device_is_t_dev_device)
515 else if (device_is_t_host_device)
518 if (device_is_memspace) {
519 if (device_mem_is_t_dev_mem) dev = 1;
520 if (device_mem_is_t_host_mem) dev = 0;
521 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
523 if (device_is_execspace) {
524 if (device_exec_is_t_dev_exec) dev = 1;
525 if (device_exec_is_t_host_exec) dev = 0;
526 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
528 if (!device_is_execspace && !device_is_memspace) {
529 if (device_mem_is_t_dev_mem) dev = 1;
530 if (device_mem_is_t_host_mem) dev = 0;
531 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
532 if (device_exec_is_t_dev_exec) dev = 1;
533 if (device_exec_is_t_host_exec) dev = 0;
534 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
539 static constexpr
const int view_header_size = 128;
540 void impl_report_host_sync() const noexcept {
541 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
543 Kokkos::Tools::syncDualView(
545 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
550 void impl_report_device_sync() const noexcept {
551 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
553 Kokkos::Tools::syncDualView(
555 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
579 template <
class Device,
class... Args>
580 void sync_impl(std::true_type, Args
const&... args) {
581 if (modified_flags.data() ==
nullptr)
return;
583 int dev = get_device_side<Device>();
586 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
587 #ifdef KOKKOS_ENABLE_CUDA
588 if (std::is_same<
typename t_dev::memory_space,
589 Kokkos::CudaUVMSpace>::value) {
590 if (d_view.data() == h_view.data())
591 Kokkos::Impl::cuda_prefetch_pointer(
592 Impl::get_cuda_space(args...), d_view.data(),
593 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
597 deep_copy(args..., d_view, h_view);
598 modified_flags(0) = modified_flags(1) = 0;
599 impl_report_device_sync();
603 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
604 #ifdef KOKKOS_ENABLE_CUDA
605 if (std::is_same<
typename t_dev::memory_space,
606 Kokkos::CudaUVMSpace>::value) {
607 if (d_view.data() == h_view.data())
608 Kokkos::Impl::cuda_prefetch_pointer(
609 Impl::get_cuda_space(args...), d_view.data(),
610 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
614 deep_copy(args..., h_view, d_view);
615 modified_flags(0) = modified_flags(1) = 0;
616 impl_report_host_sync();
619 if constexpr (std::is_same<
typename t_host::memory_space,
620 typename t_dev::memory_space>::value) {
621 typename t_dev::execution_space().fence(
622 "Kokkos::DualView<>::sync: fence after syncing DualView");
623 typename t_host::execution_space().fence(
624 "Kokkos::DualView<>::sync: fence after syncing DualView");
628 template <
class Device>
629 void sync(
const std::enable_if_t<
630 (std::is_same<
typename traits::data_type,
631 typename traits::non_const_data_type>::value) ||
632 (std::is_same<Device, int>::value),
634 sync_impl<Device>(std::true_type{});
637 template <
class Device,
class ExecutionSpace>
638 void sync(
const ExecutionSpace& exec,
639 const std::enable_if_t<
640 (std::is_same<
typename traits::data_type,
641 typename traits::non_const_data_type>::value) ||
642 (std::is_same<Device, int>::value),
644 sync_impl<Device>(std::true_type{}, exec);
648 template <
class Device,
class... Args>
649 void sync_impl(std::false_type, Args
const&...) {
650 if (modified_flags.data() ==
nullptr)
return;
652 int dev = get_device_side<Device>();
655 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
656 Impl::throw_runtime_exception(
657 "Calling sync on a DualView with a const datatype.");
659 impl_report_device_sync();
662 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
663 Impl::throw_runtime_exception(
664 "Calling sync on a DualView with a const datatype.");
666 impl_report_host_sync();
670 template <
class Device>
671 void sync(
const std::enable_if_t<
672 (!std::is_same<
typename traits::data_type,
673 typename traits::non_const_data_type>::value) ||
674 (std::is_same<Device, int>::value),
676 sync_impl<Device>(std::false_type{});
678 template <
class Device,
class ExecutionSpace>
679 void sync(
const ExecutionSpace& exec,
680 const std::enable_if_t<
681 (!std::is_same<
typename traits::data_type,
682 typename traits::non_const_data_type>::value) ||
683 (std::is_same<Device, int>::value),
685 sync_impl<Device>(std::false_type{}, exec);
689 template <
typename... Args>
690 void sync_host_impl(Args
const&... args) {
691 if (!std::is_same<
typename traits::data_type,
692 typename traits::non_const_data_type>::value)
693 Impl::throw_runtime_exception(
694 "Calling sync_host on a DualView with a const datatype.");
695 if (modified_flags.data() ==
nullptr)
return;
696 if (modified_flags(1) > modified_flags(0)) {
697 #ifdef KOKKOS_ENABLE_CUDA
698 if (std::is_same<
typename t_dev::memory_space,
699 Kokkos::CudaUVMSpace>::value) {
700 if (d_view.data() == h_view.data())
701 Kokkos::Impl::cuda_prefetch_pointer(
702 Impl::get_cuda_space(args...), d_view.data(),
703 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
707 deep_copy(args..., h_view, d_view);
708 modified_flags(1) = modified_flags(0) = 0;
709 impl_report_host_sync();
713 template <
class ExecSpace>
714 void sync_host(
const ExecSpace& exec) {
715 sync_host_impl(exec);
717 void sync_host() { sync_host_impl(); }
720 template <
typename... Args>
721 void sync_device_impl(Args
const&... args) {
722 if (!std::is_same<
typename traits::data_type,
723 typename traits::non_const_data_type>::value)
724 Impl::throw_runtime_exception(
725 "Calling sync_device on a DualView with a const datatype.");
726 if (modified_flags.data() ==
nullptr)
return;
727 if (modified_flags(0) > modified_flags(1)) {
728 #ifdef KOKKOS_ENABLE_CUDA
729 if (std::is_same<
typename t_dev::memory_space,
730 Kokkos::CudaUVMSpace>::value) {
731 if (d_view.data() == h_view.data())
732 Kokkos::Impl::cuda_prefetch_pointer(
733 Impl::get_cuda_space(args...), d_view.data(),
734 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
738 deep_copy(args..., d_view, h_view);
739 modified_flags(1) = modified_flags(0) = 0;
740 impl_report_device_sync();
744 template <
class ExecSpace>
745 void sync_device(
const ExecSpace& exec) {
746 sync_device_impl(exec);
748 void sync_device() { sync_device_impl(); }
750 template <
class Device>
751 bool need_sync()
const {
752 if (modified_flags.data() ==
nullptr)
return false;
753 int dev = get_device_side<Device>();
756 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
761 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
768 inline bool need_sync_host()
const {
769 if (modified_flags.data() ==
nullptr)
return false;
770 return modified_flags(0) < modified_flags(1);
773 inline bool need_sync_device()
const {
774 if (modified_flags.data() ==
nullptr)
return false;
775 return modified_flags(1) < modified_flags(0);
777 void impl_report_device_modification() {
778 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
780 Kokkos::Tools::modifyDualView(
782 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
787 void impl_report_host_modification() {
788 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
790 Kokkos::Tools::modifyDualView(
792 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
802 template <
class Device,
class Dummy = DualView,
803 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
806 if (modified_flags.data() ==
nullptr) {
807 modified_flags = t_modified_flags(
"DualView::modified_flags");
810 int dev = get_device_side<Device>();
815 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
816 : modified_flags(0)) +
818 impl_report_device_modification();
823 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
824 : modified_flags(0)) +
826 impl_report_host_modification();
829 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
830 if (modified_flags(0) && modified_flags(1)) {
831 std::string msg =
"Kokkos::DualView::modify ERROR: ";
832 msg +=
"Concurrent modification of host and device views ";
833 msg +=
"in DualView \"";
834 msg += d_view.label();
836 Kokkos::abort(msg.c_str());
842 class Device,
class Dummy = DualView,
843 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
848 template <
class Dummy = DualView,
849 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
851 inline void modify_host() {
852 if (modified_flags.data() !=
nullptr) {
854 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
855 : modified_flags(0)) +
857 impl_report_host_modification();
858 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
859 if (modified_flags(0) && modified_flags(1)) {
860 std::string msg =
"Kokkos::DualView::modify_host ERROR: ";
861 msg +=
"Concurrent modification of host and device views ";
862 msg +=
"in DualView \"";
863 msg += d_view.label();
865 Kokkos::abort(msg.c_str());
872 class Dummy = DualView,
873 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
874 inline void modify_host() {
878 template <
class Dummy = DualView,
879 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
881 inline void modify_device() {
882 if (modified_flags.data() !=
nullptr) {
884 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
885 : modified_flags(0)) +
887 impl_report_device_modification();
888 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
889 if (modified_flags(0) && modified_flags(1)) {
890 std::string msg =
"Kokkos::DualView::modify_device ERROR: ";
891 msg +=
"Concurrent modification of host and device views ";
892 msg +=
"in DualView \"";
893 msg += d_view.label();
895 Kokkos::abort(msg.c_str());
902 class Dummy = DualView,
903 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
904 inline void modify_device() {
908 inline void clear_sync_state() {
909 if (modified_flags.data() !=
nullptr)
910 modified_flags(1) = modified_flags(0) = 0;
922 template <
class... ViewCtorArgs>
923 void impl_realloc(
const size_t n0,
const size_t n1,
const size_t n2,
924 const size_t n3,
const size_t n4,
const size_t n5,
925 const size_t n6,
const size_t n7,
926 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
927 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
929 static_assert(!alloc_prop_input::has_label,
930 "The view constructor arguments passed to Kokkos::realloc "
931 "must not include a label!");
933 !alloc_prop_input::has_pointer,
934 "The view constructor arguments passed to Kokkos::realloc must "
935 "not include a pointer!");
937 !alloc_prop_input::has_memory_space,
938 "The view constructor arguments passed to Kokkos::realloc must "
939 "not include a memory space instance!");
941 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
942 const bool sizeMismatch =
943 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
946 ::Kokkos::realloc(arg_prop, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
947 if constexpr (alloc_prop_input::initialize) {
948 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
950 h_view = create_mirror_view(Kokkos::WithoutInitializing,
951 typename t_host::memory_space(), d_view);
953 }
else if constexpr (alloc_prop_input::initialize) {
954 if constexpr (alloc_prop_input::has_execution_space) {
955 const auto& exec_space =
956 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
957 ::Kokkos::deep_copy(exec_space, d_view,
typename t_dev::value_type{});
959 ::Kokkos::deep_copy(d_view,
typename t_dev::value_type{});
963 if (modified_flags.data() ==
nullptr) {
964 modified_flags = t_modified_flags(
"DualView::modified_flags");
966 modified_flags(1) = modified_flags(0) = 0;
969 template <
class... ViewCtorArgs>
970 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
971 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
972 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
973 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
974 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
975 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
976 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
977 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
978 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
979 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, arg_prop);
982 void realloc(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
983 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
984 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
985 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
986 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
987 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
988 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
989 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
990 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Impl::ViewCtorProp<>{});
993 template <
typename I>
994 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
995 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
996 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
997 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
998 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
999 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1000 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1001 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1002 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1003 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Kokkos::view_alloc(arg_prop));
1010 template <
class... ViewCtorArgs>
1011 void impl_resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1012 const size_t n0,
const size_t n1,
const size_t n2,
1013 const size_t n3,
const size_t n4,
const size_t n5,
1014 const size_t n6,
const size_t n7) {
1015 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1017 static_assert(!alloc_prop_input::has_label,
1018 "The view constructor arguments passed to Kokkos::resize "
1019 "must not include a label!");
1021 !alloc_prop_input::has_pointer,
1022 "The view constructor arguments passed to Kokkos::resize must "
1023 "not include a pointer!");
1025 !alloc_prop_input::has_memory_space,
1026 "The view constructor arguments passed to Kokkos::resize must "
1027 "not include a memory space instance!");
1029 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
1030 const bool sizeMismatch =
1031 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
1033 if (modified_flags.data() ==
nullptr) {
1034 modified_flags = t_modified_flags(
"DualView::modified_flags");
1037 [[maybe_unused]]
auto resize_on_device = [&](
const auto& properties) {
1040 ::Kokkos::resize(properties, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
1044 resync_host(properties);
1047 ++modified_flags(1);
1051 [[maybe_unused]]
auto resize_on_host = [&](
const auto& properties) {
1054 ::Kokkos::resize(properties, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
1058 resync_device(properties);
1061 ++modified_flags(0);
1065 constexpr
bool has_execution_space = alloc_prop_input::has_execution_space;
1067 if constexpr (has_execution_space) {
1068 using ExecSpace =
typename alloc_prop_input::execution_space;
1069 const auto& exec_space =
1070 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
1071 constexpr
bool exec_space_can_access_device =
1072 SpaceAccessibility<ExecSpace,
1073 typename t_dev::memory_space>::accessible;
1074 constexpr
bool exec_space_can_access_host =
1075 SpaceAccessibility<ExecSpace,
1076 typename t_host::memory_space>::accessible;
1077 static_assert(exec_space_can_access_device || exec_space_can_access_host);
1078 if constexpr (exec_space_can_access_device) {
1079 sync<typename t_dev::memory_space>(exec_space);
1080 resize_on_device(arg_prop);
1083 if constexpr (exec_space_can_access_host) {
1084 sync<typename t_host::memory_space>(exec_space);
1085 resize_on_host(arg_prop);
1089 if (modified_flags(1) >= modified_flags(0)) {
1090 resize_on_device(arg_prop);
1092 resize_on_host(arg_prop);
1101 template <
class... ViewCtorArgs>
1102 inline void resync_host(Impl::ViewCtorProp<ViewCtorArgs...>
const&) {
1103 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1105 if constexpr (alloc_prop_input::initialize) {
1106 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
1108 h_view = create_mirror_view(Kokkos::WithoutInitializing,
1109 typename t_host::memory_space(), d_view);
1116 template <
class... ViewCtorArgs>
1117 inline void resync_device(Impl::ViewCtorProp<ViewCtorArgs...>
const&) {
1118 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1120 if constexpr (alloc_prop_input::initialize) {
1121 d_view = create_mirror_view(
typename t_dev::memory_space(), h_view);
1124 d_view = create_mirror_view(Kokkos::WithoutInitializing,
1125 typename t_dev::memory_space(), h_view);
1130 void resize(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1131 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1132 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1133 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1134 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1135 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1136 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1137 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1138 impl_resize(Impl::ViewCtorProp<>{}, n0, n1, n2, n3, n4, n5, n6, n7);
1141 template <
class... ViewCtorArgs>
1142 void resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1143 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1144 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1145 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1146 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1147 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1148 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1149 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1150 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1151 impl_resize(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
1155 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1156 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1157 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1158 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1159 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1160 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1161 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1162 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1163 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1164 impl_resize(Kokkos::view_alloc(arg_prop), n0, n1, n2, n3, n4, n5, n6, n7);
1172 KOKKOS_INLINE_FUNCTION constexpr
size_t span()
const {
return d_view.span(); }
1174 KOKKOS_INLINE_FUNCTION
bool span_is_contiguous()
const {
1175 return d_view.span_is_contiguous();
1179 template <
typename iType>
1180 void stride(iType* stride_)
const {
1181 d_view.stride(stride_);
1184 template <
typename iType>
1185 KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<
1186 std::is_integral<iType>::value,
size_t>
1187 extent(
const iType& r)
const {
1188 return d_view.extent(r);
1191 template <
typename iType>
1192 KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<
1193 std::is_integral<iType>::value,
int>
1194 extent_int(
const iType& r)
const {
1195 return static_cast<int>(d_view.extent(r));
1215 template <
class D,
class... P>
1216 struct V2DV<
View<D, P...>> {
1217 using type = DualView<D, P...>;
1221 template <
class DataType,
class... Properties,
class... Args>
1222 auto subview(
const DualView<DataType, Properties...>& src, Args&&... args) {
1224 using deduce_subview_type =
1225 decltype(subview(std::declval<View<DataType, Properties...>>(),
1226 std::forward<Args>(args)...));
1228 return typename Impl::V2DV<deduce_subview_type>::type(
1229 src, std::forward<Args>(args)...);
1243 template <
class DT,
class... DP,
class ST,
class... SP>
1244 void deep_copy(DualView<DT, DP...>& dst,
const DualView<ST, SP...>& src) {
1245 if (src.need_sync_device()) {
1246 deep_copy(dst.h_view, src.h_view);
1249 deep_copy(dst.d_view, src.d_view);
1250 dst.modify_device();
1254 template <
class ExecutionSpace,
class DT,
class... DP,
class ST,
class... SP>
1255 void deep_copy(
const ExecutionSpace& exec, DualView<DT, DP...>& dst,
1256 const DualView<ST, SP...>& src) {
1257 if (src.need_sync_device()) {
1258 deep_copy(exec, dst.h_view, src.h_view);
1261 deep_copy(exec, dst.d_view, src.d_view);
1262 dst.modify_device();
1277 template <
class... Properties,
class... Args>
1278 void resize(DualView<Properties...>& dv, Args&&... args) noexcept(
1279 noexcept(dv.resize(std::forward<Args>(args)...))) {
1280 dv.resize(std::forward<Args>(args)...);
1283 template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1285 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1286 DualView<Properties...>& dv,
1287 Args&&... args) noexcept(noexcept(dv.resize(arg_prop,
1288 std::forward<Args>(args)...))) {
1289 dv.resize(arg_prop, std::forward<Args>(args)...);
1292 template <
class I,
class... Properties,
class... Args>
1293 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1294 const I& arg_prop, DualView<Properties...>& dv,
1295 Args&&... args) noexcept(noexcept(dv.resize(arg_prop,
1296 std::forward<Args>(args)...))) {
1297 dv.resize(arg_prop, std::forward<Args>(args)...);
1300 template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1301 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1302 DualView<Properties...>& dv,
1303 Args&&... args) noexcept(noexcept(dv
1304 .realloc(std::forward<Args>(
1306 dv.realloc(arg_prop, std::forward<Args>(args)...);
1309 template <
class... Properties,
class... Args>
1310 void realloc(DualView<Properties...>& dv, Args&&... args) noexcept(
1311 noexcept(dv.realloc(std::forward<Args>(args)...))) {
1312 dv.realloc(std::forward<Args>(args)...);
1315 template <
class I,
class... Properties,
class... Args>
1316 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
1317 const I& arg_prop, DualView<Properties...>& dv,
1318 Args&&... args) noexcept(noexcept(dv.realloc(arg_prop,
1321 dv.realloc(arg_prop, std::forward<Args>(args)...);
1326 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
1327 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1328 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
View< typename traits::non_const_data_type, typename traits::array_layout, Device< DefaultHostExecutionSpace, typename traits::host_mirror_space::memory_space >, typename traits::hooks_policy > HostMirror
Compatible HostMirror view.