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...>;
143 using t_host =
typename t_dev::HostMirror;
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...>;
156 using t_host_const =
typename t_dev_const::HostMirror;
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>>;
167 using t_host_const_randomread =
typename t_dev_const_randomread::HostMirror;
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 =
199 typename t_dev_const_randomread_um::HostMirror;
208 using t_modified_flags = View<unsigned int[2], LayoutLeft, Kokkos::HostSpace>;
209 t_modified_flags modified_flags;
214 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
237 DualView() =
default;
248 DualView(
const std::string& label,
249 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
250 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
251 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
252 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
253 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
254 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
255 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
256 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
258 Kokkos::view_alloc(typename t_modified_flags::execution_space{},
259 "DualView::modified_flags")),
260 d_view(label, n0, n1, n2, n3, n4, n5, n6, n7),
261 h_view(create_mirror_view(d_view))
274 template <
class... P>
275 DualView(
const Impl::ViewCtorProp<P...>& arg_prop,
276 std::enable_if_t<!Impl::ViewCtorProp<P...>::has_pointer,
277 size_t>
const n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
278 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
279 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
280 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
281 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
282 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
283 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
284 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
285 : modified_flags(t_modified_flags(
"DualView::modified_flags")) {
286 if constexpr (Impl::ViewCtorProp<P...>::sequential_host_init) {
287 h_view = t_host(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
288 static_assert(Impl::ViewCtorProp<P...>::initialize,
289 "DualView: SequentialHostInit isn't compatible with "
290 "WithoutInitializing!");
291 static_assert(!Impl::ViewCtorProp<P...>::has_execution_space,
292 "DualView: SequentialHostInit isn't compatible with "
293 "providing an execution space instance!");
295 d_view = Kokkos::create_mirror_view_and_copy(
296 typename traits::memory_space{}, h_view);
298 d_view = t_dev(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
301 if constexpr (Kokkos::Impl::has_type<Impl::WithoutInitializing_t,
304 Kokkos::create_mirror_view(Kokkos::WithoutInitializing, d_view);
306 h_view = Kokkos::create_mirror_view(d_view);
311 template <typename DT, typename... DP>
312 DualView(const DualView<DT, DP...>& src)
313 : modified_flags(src.modified_flags),
315 h_view(src.h_view) {}
318 template <
class DT,
class... DP,
class Arg0,
class... Args>
319 DualView(
const DualView<DT, DP...>& src,
const Arg0& arg0, Args... args)
320 : modified_flags(src.modified_flags),
321 d_view(Kokkos::subview(src.d_view, arg0, args...)),
322 h_view(Kokkos::subview(src.h_view, arg0, args...)) {}
334 DualView(
const t_dev& d_view_,
const t_host& h_view_)
335 : modified_flags(t_modified_flags(
"DualView::modified_flags")),
338 if (
int(d_view.rank) !=
int(h_view.rank) ||
339 d_view.extent(0) != h_view.extent(0) ||
340 d_view.extent(1) != h_view.extent(1) ||
341 d_view.extent(2) != h_view.extent(2) ||
342 d_view.extent(3) != h_view.extent(3) ||
343 d_view.extent(4) != h_view.extent(4) ||
344 d_view.extent(5) != h_view.extent(5) ||
345 d_view.extent(6) != h_view.extent(6) ||
346 d_view.extent(7) != h_view.extent(7) ||
347 d_view.stride_0() != h_view.stride_0() ||
348 d_view.stride_1() != h_view.stride_1() ||
349 d_view.stride_2() != h_view.stride_2() ||
350 d_view.stride_3() != h_view.stride_3() ||
351 d_view.stride_4() != h_view.stride_4() ||
352 d_view.stride_5() != h_view.stride_5() ||
353 d_view.stride_6() != h_view.stride_6() ||
354 d_view.stride_7() != h_view.stride_7() ||
355 d_view.span() != h_view.span()) {
356 Kokkos::Impl::throw_runtime_exception(
357 "DualView constructed with incompatible views");
361 struct impl_dualview_is_single_device {
363 value = std::is_same_v<
typename t_dev::device_type,
364 typename t_host::device_type>
369 template <
typename Device>
370 struct impl_device_matches_tdev_device {
371 enum :
bool { value = std::is_same_v<typename t_dev::device_type, Device> };
374 template <
typename Device>
375 struct impl_device_matches_thost_device {
377 value = std::is_same_v<typename t_host::device_type, Device>
382 template <
typename Device>
383 struct impl_device_matches_thost_exec {
385 value = std::is_same_v<typename t_host::execution_space, Device>
390 template <
typename Device>
391 struct impl_device_matches_tdev_exec {
393 value = std::is_same_v<typename t_dev::execution_space, Device>
398 template <
typename Device>
399 struct impl_device_matches_tdev_memory_space {
401 value = std::is_same_v<
typename t_dev::memory_space,
402 typename Device::memory_space>
427 template <
class Device>
428 KOKKOS_FUNCTION
auto view()
const {
429 if constexpr (std::is_same_v<Device, typename Device::memory_space>) {
430 if constexpr (std::is_same_v<
typename Device::memory_space,
431 typename t_dev::memory_space>) {
434 static_assert(std::is_same_v<
typename Device::memory_space,
435 typename t_host::memory_space>,
436 "The template argument is a memory space but doesn't "
437 "match either of DualView's memory spaces!");
441 if constexpr (std::is_same_v<Device, typename Device::execution_space>) {
442 if constexpr (std::is_same_v<
typename Device::execution_space,
443 typename t_dev::execution_space>) {
446 static_assert(std::is_same_v<
typename Device::execution_space,
447 typename t_host::execution_space>,
448 "The template argument is an execution space but "
449 "doesn't match either of DualView's execution spaces!");
453 static_assert(std::is_same_v<Device, typename Device::device_type>,
454 "The template argument is neither a memory space, "
455 "execution space, or device!");
456 if constexpr (std::is_same_v<Device, typename t_dev::device_type>)
459 static_assert(std::is_same_v<Device, typename t_host::device_type>,
460 "The template argument is a device but "
461 "doesn't match either of DualView's devices!");
468 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
469 KOKKOS_INLINE_FUNCTION
470 t_host view_host()
const {
return h_view; }
472 KOKKOS_INLINE_FUNCTION
473 t_dev view_device()
const {
return d_view; }
475 KOKKOS_INLINE_FUNCTION
476 const t_host& view_host()
const {
return h_view; }
478 KOKKOS_INLINE_FUNCTION
479 const t_dev& view_device()
const {
return d_view; }
482 KOKKOS_INLINE_FUNCTION constexpr
bool is_allocated()
const {
483 return (d_view.is_allocated() && h_view.is_allocated());
486 template <
class Device>
487 static int get_device_side() {
488 constexpr
bool device_is_memspace =
489 std::is_same_v<Device, typename Device::memory_space>;
490 constexpr
bool device_is_execspace =
491 std::is_same_v<Device, typename Device::execution_space>;
492 constexpr
bool device_exec_is_t_dev_exec =
493 std::is_same_v<
typename Device::execution_space,
494 typename t_dev::execution_space>;
495 constexpr
bool device_mem_is_t_dev_mem =
496 std::is_same_v<
typename Device::memory_space,
497 typename t_dev::memory_space>;
498 constexpr
bool device_exec_is_t_host_exec =
499 std::is_same_v<
typename Device::execution_space,
500 typename t_host::execution_space>;
501 constexpr
bool device_mem_is_t_host_mem =
502 std::is_same_v<
typename Device::memory_space,
503 typename t_host::memory_space>;
504 constexpr
bool device_is_t_host_device =
505 std::is_same_v<
typename Device::execution_space,
506 typename t_host::device_type>;
507 constexpr
bool device_is_t_dev_device =
508 std::is_same_v<
typename Device::memory_space,
509 typename t_host::device_type>;
512 device_is_t_dev_device || device_is_t_host_device ||
513 (device_is_memspace &&
514 (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
515 (device_is_execspace &&
516 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
517 ((!device_is_execspace && !device_is_memspace) &&
518 ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
519 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
520 "Template parameter to .sync() must exactly match one of the "
521 "DualView's device types or one of the execution or memory spaces");
524 if (device_is_t_dev_device)
526 else if (device_is_t_host_device)
529 if (device_is_memspace) {
530 if (device_mem_is_t_dev_mem) dev = 1;
531 if (device_mem_is_t_host_mem) dev = 0;
532 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
534 if (device_is_execspace) {
535 if (device_exec_is_t_dev_exec) dev = 1;
536 if (device_exec_is_t_host_exec) dev = 0;
537 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
539 if (!device_is_execspace && !device_is_memspace) {
540 if (device_mem_is_t_dev_mem) dev = 1;
541 if (device_mem_is_t_host_mem) dev = 0;
542 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
543 if (device_exec_is_t_dev_exec) dev = 1;
544 if (device_exec_is_t_host_exec) dev = 0;
545 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
550 static constexpr
const int view_header_size = 128;
551 void impl_report_host_sync() const noexcept {
552 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
554 Kokkos::Tools::syncDualView(
556 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
561 void impl_report_device_sync() const noexcept {
562 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
564 Kokkos::Tools::syncDualView(
566 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
590 template <
class Device,
class... Args>
591 void sync_impl(std::true_type, Args
const&... args) {
592 if (modified_flags.data() ==
nullptr)
return;
594 int dev = get_device_side<Device>();
597 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
598 #ifdef KOKKOS_ENABLE_CUDA
599 if (std::is_same<
typename t_dev::memory_space,
600 Kokkos::CudaUVMSpace>::value) {
601 if (d_view.data() == h_view.data())
602 Kokkos::Impl::cuda_prefetch_pointer(
603 Impl::get_cuda_space(args...), d_view.data(),
604 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
608 deep_copy(args..., d_view, h_view);
609 modified_flags(0) = modified_flags(1) = 0;
610 impl_report_device_sync();
614 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
615 #ifdef KOKKOS_ENABLE_CUDA
616 if (std::is_same<
typename t_dev::memory_space,
617 Kokkos::CudaUVMSpace>::value) {
618 if (d_view.data() == h_view.data())
619 Kokkos::Impl::cuda_prefetch_pointer(
620 Impl::get_cuda_space(args...), d_view.data(),
621 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
625 deep_copy(args..., h_view, d_view);
626 modified_flags(0) = modified_flags(1) = 0;
627 impl_report_host_sync();
630 if constexpr (std::is_same_v<
typename t_host::memory_space,
631 typename t_dev::memory_space>) {
632 typename t_dev::execution_space().fence(
633 "Kokkos::DualView<>::sync: fence after syncing DualView");
634 typename t_host::execution_space().fence(
635 "Kokkos::DualView<>::sync: fence after syncing DualView");
639 template <
class Device>
640 void sync(
const std::enable_if_t<
641 (std::is_same_v<
typename traits::data_type,
642 typename traits::non_const_data_type>) ||
643 (std::is_same_v<Device, int>),
645 sync_impl<Device>(std::true_type{});
648 template <
class Device,
class ExecutionSpace>
649 void sync(
const ExecutionSpace& exec,
650 const std::enable_if_t<
651 (std::is_same_v<
typename traits::data_type,
652 typename traits::non_const_data_type>) ||
653 (std::is_same_v<Device, int>),
655 sync_impl<Device>(std::true_type{}, exec);
659 template <
class Device,
class... Args>
660 void sync_impl(std::false_type, Args
const&...) {
661 if (modified_flags.data() ==
nullptr)
return;
663 int dev = get_device_side<Device>();
666 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
667 Impl::throw_runtime_exception(
668 "Calling sync on a DualView with a const datatype.");
670 impl_report_device_sync();
673 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
674 Impl::throw_runtime_exception(
675 "Calling sync on a DualView with a const datatype.");
677 impl_report_host_sync();
681 template <
class Device>
682 void sync(
const std::enable_if_t<
683 (!std::is_same_v<
typename traits::data_type,
684 typename traits::non_const_data_type>) ||
685 (std::is_same_v<Device, int>),
687 sync_impl<Device>(std::false_type{});
689 template <
class Device,
class ExecutionSpace>
690 void sync(
const ExecutionSpace& exec,
691 const std::enable_if_t<
692 (!std::is_same_v<
typename traits::data_type,
693 typename traits::non_const_data_type>) ||
694 (std::is_same_v<Device, int>),
696 sync_impl<Device>(std::false_type{}, exec);
700 template <
typename... Args>
701 void sync_host_impl(Args
const&... args) {
702 if (!std::is_same_v<
typename traits::data_type,
703 typename traits::non_const_data_type>)
704 Impl::throw_runtime_exception(
705 "Calling sync_host on a DualView with a const datatype.");
706 if (modified_flags.data() ==
nullptr)
return;
707 if (modified_flags(1) > modified_flags(0)) {
708 #ifdef KOKKOS_ENABLE_CUDA
709 if (std::is_same<
typename t_dev::memory_space,
710 Kokkos::CudaUVMSpace>::value) {
711 if (d_view.data() == h_view.data())
712 Kokkos::Impl::cuda_prefetch_pointer(
713 Impl::get_cuda_space(args...), d_view.data(),
714 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
718 deep_copy(args..., h_view, d_view);
719 modified_flags(1) = modified_flags(0) = 0;
720 impl_report_host_sync();
724 template <
class ExecSpace>
725 void sync_host(
const ExecSpace& exec) {
726 sync_host_impl(exec);
728 void sync_host() { sync_host_impl(); }
731 template <
typename... Args>
732 void sync_device_impl(Args
const&... args) {
733 if (!std::is_same_v<
typename traits::data_type,
734 typename traits::non_const_data_type>)
735 Impl::throw_runtime_exception(
736 "Calling sync_device on a DualView with a const datatype.");
737 if (modified_flags.data() ==
nullptr)
return;
738 if (modified_flags(0) > modified_flags(1)) {
739 #ifdef KOKKOS_ENABLE_CUDA
740 if (std::is_same<
typename t_dev::memory_space,
741 Kokkos::CudaUVMSpace>::value) {
742 if (d_view.data() == h_view.data())
743 Kokkos::Impl::cuda_prefetch_pointer(
744 Impl::get_cuda_space(args...), d_view.data(),
745 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
749 deep_copy(args..., d_view, h_view);
750 modified_flags(1) = modified_flags(0) = 0;
751 impl_report_device_sync();
755 template <
class ExecSpace>
756 void sync_device(
const ExecSpace& exec) {
757 sync_device_impl(exec);
759 void sync_device() { sync_device_impl(); }
761 template <
class Device>
762 bool need_sync()
const {
763 if (modified_flags.data() ==
nullptr)
return false;
764 int dev = get_device_side<Device>();
767 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
772 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
779 inline bool need_sync_host()
const {
780 if (modified_flags.data() ==
nullptr)
return false;
781 return modified_flags(0) < modified_flags(1);
784 inline bool need_sync_device()
const {
785 if (modified_flags.data() ==
nullptr)
return false;
786 return modified_flags(1) < modified_flags(0);
788 void impl_report_device_modification() {
789 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
791 Kokkos::Tools::modifyDualView(
793 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
798 void impl_report_host_modification() {
799 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
801 Kokkos::Tools::modifyDualView(
803 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
813 template <
class Device,
class Dummy = DualView,
814 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
817 if (modified_flags.data() ==
nullptr) {
818 modified_flags = t_modified_flags(
"DualView::modified_flags");
821 int dev = get_device_side<Device>();
826 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
827 : modified_flags(0)) +
829 impl_report_device_modification();
834 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
835 : modified_flags(0)) +
837 impl_report_host_modification();
840 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
841 if (modified_flags(0) && modified_flags(1)) {
842 std::string msg =
"Kokkos::DualView::modify ERROR: ";
843 msg +=
"Concurrent modification of host and device views ";
844 msg +=
"in DualView \"";
845 msg += d_view.label();
847 Kokkos::abort(msg.c_str());
853 class Device,
class Dummy = DualView,
854 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
859 template <
class Dummy = DualView,
860 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
862 inline void modify_host() {
863 if (modified_flags.data() !=
nullptr) {
865 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
866 : modified_flags(0)) +
868 impl_report_host_modification();
869 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
870 if (modified_flags(0) && modified_flags(1)) {
871 std::string msg =
"Kokkos::DualView::modify_host ERROR: ";
872 msg +=
"Concurrent modification of host and device views ";
873 msg +=
"in DualView \"";
874 msg += d_view.label();
876 Kokkos::abort(msg.c_str());
883 class Dummy = DualView,
884 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
885 inline void modify_host() {
889 template <
class Dummy = DualView,
890 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
892 inline void modify_device() {
893 if (modified_flags.data() !=
nullptr) {
895 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
896 : modified_flags(0)) +
898 impl_report_device_modification();
899 #ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
900 if (modified_flags(0) && modified_flags(1)) {
901 std::string msg =
"Kokkos::DualView::modify_device ERROR: ";
902 msg +=
"Concurrent modification of host and device views ";
903 msg +=
"in DualView \"";
904 msg += d_view.label();
906 Kokkos::abort(msg.c_str());
913 class Dummy = DualView,
914 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
915 inline void modify_device() {
919 inline void clear_sync_state() {
920 if (modified_flags.data() !=
nullptr)
921 modified_flags(1) = modified_flags(0) = 0;
933 template <
class... ViewCtorArgs>
934 void impl_realloc(
const size_t n0,
const size_t n1,
const size_t n2,
935 const size_t n3,
const size_t n4,
const size_t n5,
936 const size_t n6,
const size_t n7,
937 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
938 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
940 static_assert(!alloc_prop_input::has_label,
941 "The view constructor arguments passed to Kokkos::realloc "
942 "must not include a label!");
944 !alloc_prop_input::has_pointer,
945 "The view constructor arguments passed to Kokkos::realloc must "
946 "not include a pointer!");
948 !alloc_prop_input::has_memory_space,
949 "The view constructor arguments passed to Kokkos::realloc must "
950 "not include a memory space instance!");
952 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
953 const bool sizeMismatch =
954 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
957 if constexpr (alloc_prop_input::sequential_host_init) {
958 static_assert(alloc_prop_input::initialize,
959 "DualView: SequentialHostInit isn't compatible with "
960 "WithoutInitializing!");
961 ::Kokkos::realloc(arg_prop, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
963 create_mirror_view_and_copy(
typename t_dev::memory_space(), h_view);
965 ::Kokkos::realloc(arg_prop, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
966 if constexpr (alloc_prop_input::initialize) {
967 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
969 h_view = create_mirror_view(Kokkos::WithoutInitializing,
970 typename t_host::memory_space(), d_view);
973 }
else if constexpr (alloc_prop_input::initialize) {
974 if constexpr (alloc_prop_input::has_execution_space) {
975 const auto& exec_space =
976 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
977 ::Kokkos::deep_copy(exec_space, d_view,
typename t_dev::value_type{});
979 ::Kokkos::deep_copy(d_view,
typename t_dev::value_type{});
983 if (modified_flags.data() ==
nullptr) {
984 modified_flags = t_modified_flags(
"DualView::modified_flags");
986 modified_flags(1) = modified_flags(0) = 0;
989 template <
class... ViewCtorArgs>
990 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
991 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
992 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
993 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
994 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
995 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
996 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
997 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
998 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
999 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, arg_prop);
1002 void realloc(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1003 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1004 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1005 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1006 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1007 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1008 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1009 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1010 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Impl::ViewCtorProp<>{});
1013 template <
typename I>
1014 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
1015 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1016 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1017 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1018 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1019 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1020 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1021 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1022 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1023 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Kokkos::view_alloc(arg_prop));
1030 template <
class... ViewCtorArgs>
1031 void impl_resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1032 const size_t n0,
const size_t n1,
const size_t n2,
1033 const size_t n3,
const size_t n4,
const size_t n5,
1034 const size_t n6,
const size_t n7) {
1035 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1037 static_assert(!alloc_prop_input::has_label,
1038 "The view constructor arguments passed to Kokkos::resize "
1039 "must not include a label!");
1041 !alloc_prop_input::has_pointer,
1042 "The view constructor arguments passed to Kokkos::resize must "
1043 "not include a pointer!");
1045 !alloc_prop_input::has_memory_space,
1046 "The view constructor arguments passed to Kokkos::resize must "
1047 "not include a memory space instance!");
1049 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
1050 const bool sizeMismatch =
1051 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
1053 if (modified_flags.data() ==
nullptr) {
1054 modified_flags = t_modified_flags(
"DualView::modified_flags");
1057 [[maybe_unused]]
auto resize_on_device = [&](
const auto& properties) {
1060 ::Kokkos::resize(properties, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
1064 resync_host(properties);
1067 ++modified_flags(1);
1071 [[maybe_unused]]
auto resize_on_host = [&](
const auto& properties) {
1074 ::Kokkos::resize(properties, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
1078 resync_device(properties);
1081 ++modified_flags(0);
1085 if constexpr (alloc_prop_input::sequential_host_init) {
1086 static_assert(alloc_prop_input::initialize,
1087 "DualView: SequentialHostInit isn't compatible with "
1088 "WithoutInitializing!");
1089 static_assert(!alloc_prop_input::has_execution_space,
1090 "DualView: SequentialHostInit isn't compatible with "
1091 "providing an execution space instance!");
1094 sync<typename t_host::memory_space>();
1095 ::Kokkos::resize(arg_prop, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
1097 create_mirror_view_and_copy(
typename t_dev::memory_space(), h_view);
1100 }
else if constexpr (alloc_prop_input::has_execution_space) {
1101 using ExecSpace =
typename alloc_prop_input::execution_space;
1102 const auto& exec_space =
1103 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
1104 constexpr
bool exec_space_can_access_device =
1105 SpaceAccessibility<ExecSpace,
1106 typename t_dev::memory_space>::accessible;
1107 constexpr
bool exec_space_can_access_host =
1108 SpaceAccessibility<ExecSpace,
1109 typename t_host::memory_space>::accessible;
1110 static_assert(exec_space_can_access_device || exec_space_can_access_host);
1111 if constexpr (exec_space_can_access_device) {
1112 sync<typename t_dev::memory_space>(exec_space);
1113 resize_on_device(arg_prop);
1116 if constexpr (exec_space_can_access_host) {
1117 sync<typename t_host::memory_space>(exec_space);
1118 resize_on_host(arg_prop);
1122 if (modified_flags(1) >= modified_flags(0)) {
1123 resize_on_device(arg_prop);
1125 resize_on_host(arg_prop);
1134 template <
class... ViewCtorArgs>
1135 inline void resync_host(Impl::ViewCtorProp<ViewCtorArgs...>
const&) {
1136 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1138 if constexpr (alloc_prop_input::initialize) {
1139 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
1141 h_view = create_mirror_view(Kokkos::WithoutInitializing,
1142 typename t_host::memory_space(), d_view);
1149 template <
class... ViewCtorArgs>
1150 inline void resync_device(Impl::ViewCtorProp<ViewCtorArgs...>
const&) {
1151 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1153 if constexpr (alloc_prop_input::initialize) {
1154 d_view = create_mirror_view(
typename t_dev::memory_space(), h_view);
1157 d_view = create_mirror_view(Kokkos::WithoutInitializing,
1158 typename t_dev::memory_space(), h_view);
1163 void resize(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1164 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1165 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1166 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1167 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1168 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1169 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1170 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1171 impl_resize(Impl::ViewCtorProp<>{}, n0, n1, n2, n3, n4, n5, n6, n7);
1174 template <
class... ViewCtorArgs>
1175 void resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1176 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1177 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1178 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1179 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1180 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1181 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1182 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1183 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1184 impl_resize(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
1188 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1189 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1190 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1191 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1192 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1193 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1194 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1195 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1196 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1197 impl_resize(Kokkos::view_alloc(arg_prop), n0, n1, n2, n3, n4, n5, n6, n7);
1205 KOKKOS_INLINE_FUNCTION constexpr
size_t span()
const {
return d_view.span(); }
1207 KOKKOS_INLINE_FUNCTION
bool span_is_contiguous()
const {
1208 return d_view.span_is_contiguous();
1212 template <
typename iType>
1213 void stride(iType* stride_)
const {
1214 d_view.stride(stride_);
1217 template <
typename iType>
1218 KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
1220 extent(
const iType& r)
const {
1221 return d_view.extent(r);
1224 template <
typename iType>
1225 KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
1227 extent_int(
const iType& r)
const {
1228 return static_cast<int>(d_view.extent(r));
1248 template <
class D,
class... P>
1249 struct V2DV<
View<D, P...>> {
1250 using type = DualView<D, P...>;
1254 template <
class DataType,
class... Properties,
class... Args>
1255 auto subview(
const DualView<DataType, Properties...>& src, Args&&... args) {
1257 using deduce_subview_type =
1258 decltype(subview(std::declval<View<DataType, Properties...>>(),
1259 std::forward<Args>(args)...));
1261 return typename Impl::V2DV<deduce_subview_type>::type(
1262 src, std::forward<Args>(args)...);
1276 template <
class DT,
class... DP,
class ST,
class... SP>
1277 void deep_copy(DualView<DT, DP...>& dst,
const DualView<ST, SP...>& src) {
1278 if (src.need_sync_device()) {
1279 deep_copy(dst.view_host(), src.view_host());
1282 deep_copy(dst.view_device(), src.view_device());
1283 dst.modify_device();
1287 template <
class ExecutionSpace,
class DT,
class... DP,
class ST,
class... SP>
1288 void deep_copy(
const ExecutionSpace& exec, DualView<DT, DP...>& dst,
1289 const DualView<ST, SP...>& src) {
1290 if (src.need_sync_device()) {
1291 deep_copy(exec, dst.view_host(), src.view_host());
1294 deep_copy(exec, dst.view_device(), src.view_device());
1295 dst.modify_device();
1310 template <
class... Properties,
class... Args>
1311 void resize(DualView<Properties...>& dv, Args&&... args) noexcept(
1312 noexcept(dv.resize(std::forward<Args>(args)...))) {
1313 dv.resize(std::forward<Args>(args)...);
1316 template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1318 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1319 DualView<Properties...>& dv,
1320 Args&&... args) noexcept(noexcept(dv.resize(arg_prop,
1321 std::forward<Args>(args)...))) {
1322 dv.resize(arg_prop, std::forward<Args>(args)...);
1325 template <
class I,
class... Properties,
class... Args>
1326 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1327 const I& arg_prop, DualView<Properties...>& dv,
1328 Args&&... args) noexcept(noexcept(dv.resize(arg_prop,
1329 std::forward<Args>(args)...))) {
1330 dv.resize(arg_prop, std::forward<Args>(args)...);
1333 template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1334 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1335 DualView<Properties...>& dv,
1336 Args&&... args) noexcept(noexcept(dv
1337 .realloc(std::forward<Args>(
1339 dv.realloc(arg_prop, std::forward<Args>(args)...);
1342 template <
class... Properties,
class... Args>
1343 void realloc(DualView<Properties...>& dv, Args&&... args) noexcept(
1344 noexcept(dv.realloc(std::forward<Args>(args)...))) {
1345 dv.realloc(std::forward<Args>(args)...);
1348 template <
class I,
class... Properties,
class... Args>
1349 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
1350 const I& arg_prop, DualView<Properties...>& dv,
1351 Args&&... args) noexcept(noexcept(dv.realloc(arg_prop,
1354 dv.realloc(arg_prop, std::forward<Args>(args)...);
1359 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
1360 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1361 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW