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;
213 static constexpr
bool impl_dualview_is_single_device =
214 std::is_same_v<typename t_dev::device_type, typename t_host::device_type>;
217 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
239 DualView() =
default;
250 DualView(
const std::string& label,
251 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
252 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
253 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
254 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
255 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
256 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
257 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
258 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
260 Kokkos::view_alloc(typename t_modified_flags::execution_space{},
261 "DualView::modified_flags")),
262 d_view(label, n0, n1, n2, n3, n4, n5, n6, n7),
263 h_view(create_mirror_view(d_view))
276 template <
class... P>
277 DualView(
const Impl::ViewCtorProp<P...>& arg_prop,
278 std::enable_if_t<!Impl::ViewCtorProp<P...>::has_pointer,
279 size_t>
const n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
280 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
281 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
282 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
283 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
284 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
285 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
286 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
287 : modified_flags(t_modified_flags(
"DualView::modified_flags")) {
288 if constexpr (Impl::ViewCtorProp<P...>::sequential_host_init) {
289 h_view = t_host(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
290 static_assert(Impl::ViewCtorProp<P...>::initialize,
291 "DualView: SequentialHostInit isn't compatible with "
292 "WithoutInitializing!");
293 static_assert(!Impl::ViewCtorProp<P...>::has_execution_space,
294 "DualView: SequentialHostInit isn't compatible with "
295 "providing an execution space instance!");
297 d_view = Kokkos::create_mirror_view_and_copy(
298 typename traits::memory_space{}, h_view);
300 d_view = t_dev(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
303 if constexpr (Kokkos::Impl::has_type<Impl::WithoutInitializing_t,
306 Kokkos::create_mirror_view(Kokkos::WithoutInitializing, d_view);
308 h_view = Kokkos::create_mirror_view(d_view);
313 template <typename DT, typename... DP>
314 DualView(const DualView<DT, DP...>& src)
315 : modified_flags(src.modified_flags),
317 h_view(src.h_view) {}
320 template <
class DT,
class... DP,
class Arg0,
class... Args>
321 DualView(
const DualView<DT, DP...>& src,
const Arg0& arg0, Args... args)
322 : modified_flags(src.modified_flags),
323 d_view(Kokkos::subview(src.d_view, arg0, args...)),
324 h_view(Kokkos::subview(src.h_view, arg0, args...)) {}
336 DualView(
const t_dev& d_view_,
const t_host& h_view_)
337 : modified_flags(t_modified_flags(
"DualView::modified_flags")),
340 if (
int(d_view.rank) !=
int(h_view.rank) ||
344 for (
size_t r = 0; r < d_view.rank(); ++r) {
345 if (d_view.extent(r) != h_view.extent(r) ||
346 d_view.stride(r) != h_view.stride(r))
351 d_view.span() != h_view.span()) {
352 Kokkos::Impl::throw_runtime_exception(
353 "DualView constructed with incompatible views");
356 typename t_dev::memory_space>::accessible &&
357 (d_view.data() != h_view.data()))
359 "DualView storing one View constructed from two different Views");
383 template <
class Device>
384 KOKKOS_FUNCTION
auto view()
const {
385 if constexpr (std::is_same_v<Device, typename Device::memory_space>) {
386 if constexpr (std::is_same_v<
typename Device::memory_space,
387 typename t_dev::memory_space>) {
390 static_assert(std::is_same_v<
typename Device::memory_space,
391 typename t_host::memory_space>,
392 "The template argument is a memory space but doesn't "
393 "match either of DualView's memory spaces!");
397 if constexpr (std::is_same_v<Device, typename Device::execution_space>) {
398 if constexpr (std::is_same_v<
typename Device::execution_space,
399 typename t_dev::execution_space>) {
402 static_assert(std::is_same_v<
typename Device::execution_space,
403 typename t_host::execution_space>,
404 "The template argument is an execution space but "
405 "doesn't match either of DualView's execution spaces!");
409 static_assert(std::is_same_v<Device, typename Device::device_type>,
410 "The template argument is neither a memory space, "
411 "execution space, or device!");
412 if constexpr (std::is_same_v<Device, typename t_dev::device_type>)
415 static_assert(std::is_same_v<Device, typename t_host::device_type>,
416 "The template argument is a device but "
417 "doesn't match either of DualView's devices!");
424 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
425 KOKKOS_INLINE_FUNCTION
426 t_host view_host()
const {
return h_view; }
428 KOKKOS_INLINE_FUNCTION
429 t_dev view_device()
const {
return d_view; }
431 KOKKOS_INLINE_FUNCTION
432 const t_host& view_host()
const {
return h_view; }
434 KOKKOS_INLINE_FUNCTION
435 const t_dev& view_device()
const {
return d_view; }
438 KOKKOS_INLINE_FUNCTION constexpr
bool is_allocated()
const {
439 return (d_view.is_allocated() && h_view.is_allocated());
442 template <
class Device>
443 static int get_device_side() {
444 constexpr
bool device_is_memspace =
445 std::is_same_v<Device, typename Device::memory_space>;
446 constexpr
bool device_is_execspace =
447 std::is_same_v<Device, typename Device::execution_space>;
448 constexpr
bool device_exec_is_t_dev_exec =
449 std::is_same_v<
typename Device::execution_space,
450 typename t_dev::execution_space>;
451 constexpr
bool device_mem_is_t_dev_mem =
452 std::is_same_v<
typename Device::memory_space,
453 typename t_dev::memory_space>;
454 constexpr
bool device_exec_is_t_host_exec =
455 std::is_same_v<
typename Device::execution_space,
456 typename t_host::execution_space>;
457 constexpr
bool device_mem_is_t_host_mem =
458 std::is_same_v<
typename Device::memory_space,
459 typename t_host::memory_space>;
460 constexpr
bool device_is_t_host_device =
461 std::is_same_v<
typename Device::execution_space,
462 typename t_host::device_type>;
463 constexpr
bool device_is_t_dev_device =
464 std::is_same_v<
typename Device::memory_space,
465 typename t_host::device_type>;
468 device_is_t_dev_device || device_is_t_host_device ||
469 (device_is_memspace &&
470 (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
471 (device_is_execspace &&
472 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
473 ((!device_is_execspace && !device_is_memspace) &&
474 ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
475 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
476 "Template parameter to .sync() must exactly match one of the "
477 "DualView's device types or one of the execution or memory spaces");
480 if (device_is_t_dev_device)
482 else if (device_is_t_host_device)
485 if (device_is_memspace) {
486 if (device_mem_is_t_dev_mem) dev = 1;
487 if (device_mem_is_t_host_mem) dev = 0;
488 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
490 if (device_is_execspace) {
491 if (device_exec_is_t_dev_exec) dev = 1;
492 if (device_exec_is_t_host_exec) dev = 0;
493 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
495 if (!device_is_execspace && !device_is_memspace) {
496 if (device_mem_is_t_dev_mem) dev = 1;
497 if (device_mem_is_t_host_mem) dev = 0;
498 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
499 if (device_exec_is_t_dev_exec) dev = 1;
500 if (device_exec_is_t_host_exec) dev = 0;
501 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
506 static constexpr
const int view_header_size = 128;
507 void impl_report_host_sync() const noexcept {
508 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
510 Kokkos::Tools::syncDualView(
512 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
517 void impl_report_device_sync() const noexcept {
518 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
520 Kokkos::Tools::syncDualView(
522 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
546 template <
class Device,
class... Args>
547 void sync_impl(std::true_type, Args
const&... args) {
548 if (modified_flags.data() ==
nullptr)
return;
550 int dev = get_device_side<Device>();
553 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
554 #ifdef KOKKOS_ENABLE_CUDA
555 if (std::is_same<
typename t_dev::memory_space,
556 Kokkos::CudaUVMSpace>::value) {
557 if (d_view.data() == h_view.data())
558 Kokkos::Impl::cuda_prefetch_pointer(
559 Impl::get_cuda_space(args...), d_view.data(),
560 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
564 deep_copy(args..., d_view, h_view);
565 modified_flags(0) = modified_flags(1) = 0;
566 impl_report_device_sync();
570 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
571 #ifdef KOKKOS_ENABLE_CUDA
572 if (std::is_same<
typename t_dev::memory_space,
573 Kokkos::CudaUVMSpace>::value) {
574 if (d_view.data() == h_view.data())
575 Kokkos::Impl::cuda_prefetch_pointer(
576 Impl::get_cuda_space(args...), d_view.data(),
577 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
581 deep_copy(args..., h_view, d_view);
582 modified_flags(0) = modified_flags(1) = 0;
583 impl_report_host_sync();
586 if constexpr (std::is_same_v<
typename t_host::memory_space,
587 typename t_dev::memory_space>) {
588 typename t_dev::execution_space().fence(
589 "Kokkos::DualView<>::sync: fence after syncing DualView");
590 typename t_host::execution_space().fence(
591 "Kokkos::DualView<>::sync: fence after syncing DualView");
595 template <
class Device>
597 if constexpr (impl_dualview_is_single_device) {
605 typename std::is_same<
typename traits::data_type,
606 typename traits::non_const_data_type>::type{});
610 template <
class Device,
class ExecutionSpace>
611 void sync([[maybe_unused]]
const ExecutionSpace& exec) {
612 if constexpr (impl_dualview_is_single_device)
616 typename std::is_same<
typename traits::data_type,
617 typename traits::non_const_data_type>::type{},
623 template <
class Device,
class... Args>
624 void sync_impl(std::false_type, Args
const&...) {
625 if (modified_flags.data() ==
nullptr)
return;
627 int dev = get_device_side<Device>();
630 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
631 Impl::throw_runtime_exception(
632 "Calling sync on a DualView with a const datatype.");
634 impl_report_device_sync();
637 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
638 Impl::throw_runtime_exception(
639 "Calling sync on a DualView with a const datatype.");
641 impl_report_host_sync();
646 template <
typename... Args>
647 void sync_host_impl(Args
const&... args) {
648 if (!std::is_same_v<
typename traits::data_type,
649 typename traits::non_const_data_type>)
650 Impl::throw_runtime_exception(
651 "Calling sync_host on a DualView with a const datatype.");
652 if (modified_flags.data() ==
nullptr)
return;
653 if (modified_flags(1) > modified_flags(0)) {
654 #ifdef KOKKOS_ENABLE_CUDA
655 if (std::is_same<
typename t_dev::memory_space,
656 Kokkos::CudaUVMSpace>::value) {
657 if (d_view.data() == h_view.data())
658 Kokkos::Impl::cuda_prefetch_pointer(
659 Impl::get_cuda_space(args...), d_view.data(),
660 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
664 deep_copy(args..., h_view, d_view);
665 modified_flags(1) = modified_flags(0) = 0;
666 impl_report_host_sync();
670 template <
class ExecSpace>
671 void sync_host([[maybe_unused]]
const ExecSpace& exec) {
672 if constexpr (impl_dualview_is_single_device)
675 sync_host_impl(exec);
678 if constexpr (impl_dualview_is_single_device) {
689 template <
typename... Args>
690 void sync_device_impl(Args
const&... args) {
691 if (!std::is_same_v<
typename traits::data_type,
692 typename traits::non_const_data_type>)
693 Impl::throw_runtime_exception(
694 "Calling sync_device on a DualView with a const datatype.");
695 if (modified_flags.data() ==
nullptr)
return;
696 if (modified_flags(0) > modified_flags(1)) {
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(),
true);
707 deep_copy(args..., d_view, h_view);
708 modified_flags(1) = modified_flags(0) = 0;
709 impl_report_device_sync();
713 template <
class ExecSpace>
714 void sync_device([[maybe_unused]]
const ExecSpace& exec) {
715 if constexpr (impl_dualview_is_single_device)
718 sync_device_impl(exec);
721 if constexpr (impl_dualview_is_single_device) {
731 template <
class Device>
732 bool need_sync()
const {
733 if (modified_flags.data() ==
nullptr)
return false;
734 int dev = get_device_side<Device>();
737 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
742 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
749 inline bool need_sync_host()
const {
750 if (modified_flags.data() ==
nullptr)
return false;
751 return modified_flags(0) < modified_flags(1);
754 inline bool need_sync_device()
const {
755 if (modified_flags.data() ==
nullptr)
return false;
756 return modified_flags(1) < modified_flags(0);
758 void impl_report_device_modification() {
759 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
761 Kokkos::Tools::modifyDualView(
763 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
768 void impl_report_host_modification() {
769 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
771 Kokkos::Tools::modifyDualView(
773 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
783 template <
class Device>
785 if constexpr (impl_dualview_is_single_device) {
788 if (modified_flags.data() ==
nullptr)
return;
790 int dev = get_device_side<Device>();
795 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
796 : modified_flags(0)) +
798 impl_report_device_modification();
803 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
804 : modified_flags(0)) +
806 impl_report_host_modification();
809 if (modified_flags(0) && modified_flags(1)) {
810 std::string msg =
"Kokkos::DualView::modify ERROR: ";
811 msg +=
"Concurrent modification of host and device views ";
812 msg +=
"in DualView \"";
813 msg += d_view.label();
815 Kokkos::abort(msg.c_str());
820 inline void modify_host() {
821 if constexpr (impl_dualview_is_single_device) {
824 if (modified_flags.data() !=
nullptr) {
826 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
827 : modified_flags(0)) +
829 impl_report_host_modification();
830 if (modified_flags(0) && modified_flags(1)) {
831 std::string msg =
"Kokkos::DualView::modify_host 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 inline void modify_device() {
843 if constexpr (impl_dualview_is_single_device) {
846 if (modified_flags.data() !=
nullptr) {
848 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
849 : modified_flags(0)) +
851 impl_report_device_modification();
852 if (modified_flags(0) && modified_flags(1)) {
853 std::string msg =
"Kokkos::DualView::modify_device ERROR: ";
854 msg +=
"Concurrent modification of host and device views ";
855 msg +=
"in DualView \"";
856 msg += d_view.label();
858 Kokkos::abort(msg.c_str());
864 inline void clear_sync_state() {
865 if (modified_flags.data() !=
nullptr)
866 modified_flags(1) = modified_flags(0) = 0;
878 template <
class... ViewCtorArgs>
879 void impl_realloc(
const size_t n0,
const size_t n1,
const size_t n2,
880 const size_t n3,
const size_t n4,
const size_t n5,
881 const size_t n6,
const size_t n7,
882 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
883 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
885 static_assert(!alloc_prop_input::has_label,
886 "The view constructor arguments passed to Kokkos::realloc "
887 "must not include a label!");
889 !alloc_prop_input::has_pointer,
890 "The view constructor arguments passed to Kokkos::realloc must "
891 "not include a pointer!");
893 !alloc_prop_input::has_memory_space,
894 "The view constructor arguments passed to Kokkos::realloc must "
895 "not include a memory space instance!");
897 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
898 const bool sizeMismatch =
899 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
902 if constexpr (alloc_prop_input::sequential_host_init) {
903 static_assert(alloc_prop_input::initialize,
904 "DualView: SequentialHostInit isn't compatible with "
905 "WithoutInitializing!");
906 ::Kokkos::realloc(arg_prop, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
908 create_mirror_view_and_copy(
typename t_dev::memory_space(), h_view);
910 ::Kokkos::realloc(arg_prop, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
911 if constexpr (alloc_prop_input::initialize) {
912 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
914 h_view = create_mirror_view(Kokkos::WithoutInitializing,
915 typename t_host::memory_space(), d_view);
918 }
else if constexpr (alloc_prop_input::initialize) {
919 if constexpr (alloc_prop_input::has_execution_space) {
920 const auto& exec_space =
921 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
922 ::Kokkos::deep_copy(exec_space, d_view,
typename t_dev::value_type{});
924 ::Kokkos::deep_copy(d_view,
typename t_dev::value_type{});
928 if (modified_flags.data() ==
nullptr) {
929 modified_flags = t_modified_flags(
"DualView::modified_flags");
931 modified_flags(1) = modified_flags(0) = 0;
934 template <
class... ViewCtorArgs>
935 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
936 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
937 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
938 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
939 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
940 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
941 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
942 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
943 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
944 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, arg_prop);
947 void realloc(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
948 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
949 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
950 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
951 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
952 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
953 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
954 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
955 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Impl::ViewCtorProp<>{});
958 template <
typename I>
959 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
960 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
961 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
962 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
963 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
964 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
965 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
966 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
967 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
968 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Kokkos::view_alloc(arg_prop));
975 template <
class... ViewCtorArgs>
976 void impl_resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
977 const size_t n0,
const size_t n1,
const size_t n2,
978 const size_t n3,
const size_t n4,
const size_t n5,
979 const size_t n6,
const size_t n7) {
980 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
982 static_assert(!alloc_prop_input::has_label,
983 "The view constructor arguments passed to Kokkos::resize "
984 "must not include a label!");
986 !alloc_prop_input::has_pointer,
987 "The view constructor arguments passed to Kokkos::resize must "
988 "not include a pointer!");
990 !alloc_prop_input::has_memory_space,
991 "The view constructor arguments passed to Kokkos::resize must "
992 "not include a memory space instance!");
994 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
995 const bool sizeMismatch =
996 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
998 if (modified_flags.data() ==
nullptr) {
999 modified_flags = t_modified_flags(
"DualView::modified_flags");
1002 [[maybe_unused]]
auto resize_on_device = [&](
const auto& properties) {
1005 ::Kokkos::resize(properties, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
1009 resync_host(properties);
1012 ++modified_flags(1);
1016 [[maybe_unused]]
auto resize_on_host = [&](
const auto& properties) {
1019 ::Kokkos::resize(properties, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
1023 resync_device(properties);
1026 ++modified_flags(0);
1030 if constexpr (alloc_prop_input::sequential_host_init) {
1031 static_assert(alloc_prop_input::initialize,
1032 "DualView: SequentialHostInit isn't compatible with "
1033 "WithoutInitializing!");
1034 static_assert(!alloc_prop_input::has_execution_space,
1035 "DualView: SequentialHostInit isn't compatible with "
1036 "providing an execution space instance!");
1039 sync<typename t_host::memory_space>();
1040 ::Kokkos::resize(arg_prop, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
1042 create_mirror_view_and_copy(
typename t_dev::memory_space(), h_view);
1045 }
else if constexpr (alloc_prop_input::has_execution_space) {
1046 using ExecSpace =
typename alloc_prop_input::execution_space;
1047 const auto& exec_space =
1048 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
1049 constexpr
bool exec_space_can_access_device =
1050 SpaceAccessibility<ExecSpace,
1051 typename t_dev::memory_space>::accessible;
1052 constexpr
bool exec_space_can_access_host =
1053 SpaceAccessibility<ExecSpace,
1054 typename t_host::memory_space>::accessible;
1055 static_assert(exec_space_can_access_device || exec_space_can_access_host);
1056 if constexpr (exec_space_can_access_device) {
1057 sync<typename t_dev::memory_space>(exec_space);
1058 resize_on_device(arg_prop);
1061 if constexpr (exec_space_can_access_host) {
1062 sync<typename t_host::memory_space>(exec_space);
1063 resize_on_host(arg_prop);
1067 if (modified_flags(1) >= modified_flags(0)) {
1068 resize_on_device(arg_prop);
1070 resize_on_host(arg_prop);
1079 template <
class... ViewCtorArgs>
1080 inline void resync_host(Impl::ViewCtorProp<ViewCtorArgs...>
const&) {
1081 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1083 if constexpr (alloc_prop_input::initialize) {
1084 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
1086 h_view = create_mirror_view(Kokkos::WithoutInitializing,
1087 typename t_host::memory_space(), d_view);
1094 template <
class... ViewCtorArgs>
1095 inline void resync_device(Impl::ViewCtorProp<ViewCtorArgs...>
const&) {
1096 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1098 if constexpr (alloc_prop_input::initialize) {
1099 d_view = create_mirror_view(
typename t_dev::memory_space(), h_view);
1102 d_view = create_mirror_view(Kokkos::WithoutInitializing,
1103 typename t_dev::memory_space(), h_view);
1108 void resize(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1109 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1110 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1111 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1112 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1113 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1114 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1115 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1116 impl_resize(Impl::ViewCtorProp<>{}, n0, n1, n2, n3, n4, n5, n6, n7);
1119 template <
class... ViewCtorArgs>
1120 void resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1121 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1122 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1123 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1124 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1125 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1126 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1127 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1128 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1129 impl_resize(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
1133 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1134 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1135 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1136 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1137 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1138 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1139 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1140 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1141 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1142 impl_resize(Kokkos::view_alloc(arg_prop), n0, n1, n2, n3, n4, n5, n6, n7);
1150 KOKKOS_INLINE_FUNCTION constexpr
size_t span()
const {
return d_view.span(); }
1152 KOKKOS_INLINE_FUNCTION
bool span_is_contiguous()
const {
1153 return d_view.span_is_contiguous();
1157 template <
typename iType>
1158 void stride(iType* stride_)
const {
1159 d_view.stride(stride_);
1162 template <
typename iType>
1163 KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
1165 extent(
const iType& r)
const {
1166 return d_view.extent(r);
1169 template <
typename iType>
1170 KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
1172 extent_int(
const iType& r)
const {
1173 return static_cast<int>(d_view.extent(r));
1193 template <
class D,
class... P>
1194 struct V2DV<
View<D, P...>> {
1195 using type = DualView<D, P...>;
1199 template <
class DataType,
class... Properties,
class... Args>
1200 auto subview(
const DualView<DataType, Properties...>& src, Args&&... args) {
1202 using deduce_subview_type =
1203 decltype(subview(std::declval<View<DataType, Properties...>>(),
1204 std::forward<Args>(args)...));
1206 return typename Impl::V2DV<deduce_subview_type>::type(
1207 src, std::forward<Args>(args)...);
1221 template <
class DT,
class... DP,
class ST,
class... SP>
1222 void deep_copy(DualView<DT, DP...>& dst,
const DualView<ST, SP...>& src) {
1223 if (src.need_sync_device()) {
1224 deep_copy(dst.view_host(), src.view_host());
1227 deep_copy(dst.view_device(), src.view_device());
1228 dst.modify_device();
1232 template <
class ExecutionSpace,
class DT,
class... DP,
class ST,
class... SP>
1233 void deep_copy(
const ExecutionSpace& exec, DualView<DT, DP...>& dst,
1234 const DualView<ST, SP...>& src) {
1235 if (src.need_sync_device()) {
1236 deep_copy(exec, dst.view_host(), src.view_host());
1239 deep_copy(exec, dst.view_device(), src.view_device());
1240 dst.modify_device();
1255 template <
class... Properties,
class... Args>
1256 void resize(DualView<Properties...>& dv, Args&&... args) noexcept(
1257 noexcept(dv.resize(std::forward<Args>(args)...))) {
1258 dv.resize(std::forward<Args>(args)...);
1261 template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1263 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1264 DualView<Properties...>& dv,
1265 Args&&... args) noexcept(noexcept(dv.resize(arg_prop,
1266 std::forward<Args>(args)...))) {
1267 dv.resize(arg_prop, std::forward<Args>(args)...);
1270 template <
class I,
class... Properties,
class... Args>
1271 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1272 const I& arg_prop, DualView<Properties...>& dv,
1273 Args&&... args) noexcept(noexcept(dv.resize(arg_prop,
1274 std::forward<Args>(args)...))) {
1275 dv.resize(arg_prop, std::forward<Args>(args)...);
1278 template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1279 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1280 DualView<Properties...>& dv,
1281 Args&&... args) noexcept(noexcept(dv
1282 .realloc(std::forward<Args>(
1284 dv.realloc(arg_prop, std::forward<Args>(args)...);
1287 template <
class... Properties,
class... Args>
1288 void realloc(DualView<Properties...>& dv, Args&&... args) noexcept(
1289 noexcept(dv.realloc(std::forward<Args>(args)...))) {
1290 dv.realloc(std::forward<Args>(args)...);
1293 template <
class I,
class... Properties,
class... Args>
1294 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
1295 const I& arg_prop, DualView<Properties...>& dv,
1296 Args&&... args) noexcept(noexcept(dv.realloc(arg_prop,
1299 dv.realloc(arg_prop, std::forward<Args>(args)...);
1304 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
1305 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1306 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
Can AccessSpace access MemorySpace ?
Memory management for host memory.