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
78 return *Kokkos::Impl::cuda_get_deep_copy_space();
81template <
typename NonCudaExecSpace>
82inline const Kokkos::Cuda& get_cuda_space(
const NonCudaExecSpace&) {
83 return get_cuda_space();
89template <
class DataType,
class Arg1Type = void,
class Arg2Type = void,
90 class Arg3Type =
void>
91class DualView :
public ViewTraits<DataType, Arg1Type, Arg2Type, Arg3Type> {
92 template <
class,
class,
class,
class>
93 friend class DualView;
98 using traits = ViewTraits<DataType, Arg1Type, Arg2Type, Arg3Type>;
101 using host_mirror_space =
typename traits::host_mirror_space;
104 using t_dev = View<typename traits::data_type, Arg1Type, Arg2Type, Arg3Type>;
108 using t_host =
typename t_dev::HostMirror;
113 View<typename traits::const_data_type, Arg1Type, Arg2Type, Arg3Type>;
117 using t_host_const =
typename t_dev_const::HostMirror;
120 using t_dev_const_randomread =
121 View<
typename traits::const_data_type,
typename traits::array_layout,
122 typename traits::device_type,
128 using t_host_const_randomread =
typename t_dev_const_randomread::HostMirror;
132 View<
typename traits::data_type,
typename traits::array_layout,
133 typename traits::device_type, MemoryUnmanaged>;
137 View<
typename t_host::data_type,
typename t_host::array_layout,
138 typename t_host::device_type, MemoryUnmanaged>;
141 using t_dev_const_um =
142 View<
typename traits::const_data_type,
typename traits::array_layout,
143 typename traits::device_type, MemoryUnmanaged>;
146 using t_host_const_um =
147 View<
typename t_host::const_data_type,
typename t_host::array_layout,
148 typename t_host::device_type, MemoryUnmanaged>;
151 using t_dev_const_randomread_um =
152 View<
typename t_host::const_data_type,
typename t_host::array_layout,
153 typename t_host::device_type,
159 using t_host_const_randomread_um =
160 typename t_dev_const_randomread_um::HostMirror;
169 using t_modified_flags = View<unsigned int[2], LayoutLeft, Kokkos::HostSpace>;
170 t_modified_flags modified_flags;
191 DualView() =
default;
202 DualView(
const std::string& label,
203 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
204 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
205 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
206 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
207 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
208 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
209 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
210 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
212 Kokkos::view_alloc(typename t_modified_flags::execution_space{},
213 "DualView::modified_flags")),
214 d_view(label, n0, n1, n2, n3, n4, n5, n6, n7),
215 h_view(create_mirror_view(d_view))
228 template <
class... P>
229 DualView(
const Impl::ViewCtorProp<P...>& arg_prop,
230 std::enable_if_t<!Impl::ViewCtorProp<P...>::has_pointer,
231 size_t>
const n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
232 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
233 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
234 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
235 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
236 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
237 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
238 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
239 : modified_flags(t_modified_flags(
"DualView::modified_flags")),
240 d_view(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7) {
242 if (Kokkos::Impl::has_type<Impl::WithoutInitializing_t, P...>::value)
245 h_view = Kokkos::create_mirror_view(d_view);
249 template <
class SS,
class LS,
class DS,
class MS>
250 DualView(
const DualView<SS, LS, DS, MS>& src)
251 : modified_flags(src.modified_flags),
253 h_view(src.h_view) {}
256 template <
class SD,
class S1,
class S2,
class S3,
class Arg0,
class... Args>
257 DualView(
const DualView<SD, S1, S2, S3>& src,
const Arg0& arg0, Args... args)
258 : modified_flags(src.modified_flags),
259 d_view(Kokkos::subview(src.d_view, arg0, args...)),
260 h_view(Kokkos::subview(src.h_view, arg0, args...)) {}
272 DualView(
const t_dev& d_view_,
const t_host& h_view_)
273 : modified_flags(t_modified_flags(
"DualView::modified_flags")),
276 if (
int(d_view.rank) !=
int(h_view.rank) ||
277 d_view.extent(0) != h_view.extent(0) ||
278 d_view.extent(1) != h_view.extent(1) ||
279 d_view.extent(2) != h_view.extent(2) ||
280 d_view.extent(3) != h_view.extent(3) ||
281 d_view.extent(4) != h_view.extent(4) ||
282 d_view.extent(5) != h_view.extent(5) ||
283 d_view.extent(6) != h_view.extent(6) ||
284 d_view.extent(7) != h_view.extent(7) ||
285 d_view.stride_0() != h_view.stride_0() ||
286 d_view.stride_1() != h_view.stride_1() ||
287 d_view.stride_2() != h_view.stride_2() ||
288 d_view.stride_3() != h_view.stride_3() ||
289 d_view.stride_4() != h_view.stride_4() ||
290 d_view.stride_5() != h_view.stride_5() ||
291 d_view.stride_6() != h_view.stride_6() ||
292 d_view.stride_7() != h_view.stride_7() ||
293 d_view.span() != h_view.span()) {
294 Kokkos::Impl::throw_runtime_exception(
295 "DualView constructed with incompatible views");
299 struct impl_dualview_is_single_device {
301 value = std::is_same<
typename t_dev::device_type,
302 typename t_host::device_type>::value
307 template <
typename Device>
308 struct impl_device_matches_tdev_device {
310 value = std::is_same<typename t_dev::device_type, Device>::value
314 template <
typename Device>
315 struct impl_device_matches_thost_device {
317 value = std::is_same<typename t_host::device_type, Device>::value
322 template <
typename Device>
323 struct impl_device_matches_thost_exec {
325 value = std::is_same<typename t_host::execution_space, Device>::value
330 template <
typename Device>
331 struct impl_device_matches_tdev_exec {
333 value = std::is_same<typename t_dev::execution_space, Device>::value
338 template <
typename Device>
339 struct impl_device_matches_tdev_memory_space {
341 value = std::is_same<
typename t_dev::memory_space,
342 typename Device::memory_space>::value
372 template <
class Device>
373 KOKKOS_INLINE_FUNCTION
const typename std::conditional_t<
374 impl_device_matches_tdev_device<Device>::value, t_dev,
375 typename std::conditional_t<
376 impl_device_matches_thost_device<Device>::value, t_host,
377 typename std::conditional_t<
378 impl_device_matches_thost_exec<Device>::value, t_host,
379 typename std::conditional_t<
380 impl_device_matches_tdev_exec<Device>::value, t_dev,
381 typename std::conditional_t<
382 impl_device_matches_tdev_memory_space<Device>::value,
385 constexpr bool device_is_memspace =
386 std::is_same<Device, typename Device::memory_space>::value;
387 constexpr bool device_is_execspace =
388 std::is_same<Device, typename Device::execution_space>::value;
389 constexpr bool device_exec_is_t_dev_exec =
390 std::is_same<
typename Device::execution_space,
391 typename t_dev::execution_space>::value;
392 constexpr bool device_mem_is_t_dev_mem =
393 std::is_same<
typename Device::memory_space,
394 typename t_dev::memory_space>::value;
395 constexpr bool device_exec_is_t_host_exec =
396 std::is_same<
typename Device::execution_space,
397 typename t_host::execution_space>::value;
398 constexpr bool device_mem_is_t_host_mem =
399 std::is_same<
typename Device::memory_space,
400 typename t_host::memory_space>::value;
401 constexpr bool device_is_t_host_device =
402 std::is_same<
typename Device::execution_space,
403 typename t_host::device_type>::value;
404 constexpr bool device_is_t_dev_device =
405 std::is_same<
typename Device::memory_space,
406 typename t_host::device_type>::value;
409 device_is_t_dev_device || device_is_t_host_device ||
410 (device_is_memspace &&
411 (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
412 (device_is_execspace &&
413 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
414 ((!device_is_execspace && !device_is_memspace) &&
415 ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
416 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
417 "Template parameter to .view() must exactly match one of the "
418 "DualView's device types or one of the execution or memory spaces");
420 return Impl::if_c<std::is_same<
typename t_dev::memory_space,
421 typename Device::memory_space>::value,
422 t_dev, t_host>::select(d_view, h_view);
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
constexpr bool is_allocated()
const {
432 return (d_view.is_allocated() && h_view.is_allocated());
435 template <
class Device>
436 static int get_device_side() {
437 constexpr bool device_is_memspace =
438 std::is_same<Device, typename Device::memory_space>::value;
439 constexpr bool device_is_execspace =
440 std::is_same<Device, typename Device::execution_space>::value;
441 constexpr bool device_exec_is_t_dev_exec =
442 std::is_same<
typename Device::execution_space,
443 typename t_dev::execution_space>::value;
444 constexpr bool device_mem_is_t_dev_mem =
445 std::is_same<
typename Device::memory_space,
446 typename t_dev::memory_space>::value;
447 constexpr bool device_exec_is_t_host_exec =
448 std::is_same<
typename Device::execution_space,
449 typename t_host::execution_space>::value;
450 constexpr bool device_mem_is_t_host_mem =
451 std::is_same<
typename Device::memory_space,
452 typename t_host::memory_space>::value;
453 constexpr bool device_is_t_host_device =
454 std::is_same<
typename Device::execution_space,
455 typename t_host::device_type>::value;
456 constexpr bool device_is_t_dev_device =
457 std::is_same<
typename Device::memory_space,
458 typename t_host::device_type>::value;
461 device_is_t_dev_device || device_is_t_host_device ||
462 (device_is_memspace &&
463 (device_mem_is_t_dev_mem || device_mem_is_t_host_mem)) ||
464 (device_is_execspace &&
465 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec)) ||
466 ((!device_is_execspace && !device_is_memspace) &&
467 ((device_mem_is_t_dev_mem || device_mem_is_t_host_mem) ||
468 (device_exec_is_t_dev_exec || device_exec_is_t_host_exec))),
469 "Template parameter to .sync() must exactly match one of the "
470 "DualView's device types or one of the execution or memory spaces");
473 if (device_is_t_dev_device)
475 else if (device_is_t_host_device)
478 if (device_is_memspace) {
479 if (device_mem_is_t_dev_mem) dev = 1;
480 if (device_mem_is_t_host_mem) dev = 0;
481 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
483 if (device_is_execspace) {
484 if (device_exec_is_t_dev_exec) dev = 1;
485 if (device_exec_is_t_host_exec) dev = 0;
486 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
488 if (!device_is_execspace && !device_is_memspace) {
489 if (device_mem_is_t_dev_mem) dev = 1;
490 if (device_mem_is_t_host_mem) dev = 0;
491 if (device_mem_is_t_host_mem && device_mem_is_t_dev_mem) dev = -1;
492 if (device_exec_is_t_dev_exec) dev = 1;
493 if (device_exec_is_t_host_exec) dev = 0;
494 if (device_exec_is_t_host_exec && device_exec_is_t_dev_exec) dev = -1;
499 static constexpr const int view_header_size = 128;
500 void impl_report_host_sync() const noexcept {
501 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
503 Kokkos::Tools::syncDualView(
505 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
510 void impl_report_device_sync() const noexcept {
511 if (Kokkos::Tools::Experimental::get_callbacks().sync_dual_view !=
513 Kokkos::Tools::syncDualView(
515 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
539 template <
class Device,
class... Args>
540 void sync_impl(std::true_type, Args
const&... args) {
541 if (modified_flags.data() ==
nullptr)
return;
543 int dev = get_device_side<Device>();
546 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
547#ifdef KOKKOS_ENABLE_CUDA
548 if (std::is_same<
typename t_dev::memory_space,
550 if (d_view.data() == h_view.data())
551 Kokkos::Impl::cuda_prefetch_pointer(
552 Impl::get_cuda_space(args...), d_view.data(),
553 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
557 deep_copy(args..., d_view, h_view);
558 modified_flags(0) = modified_flags(1) = 0;
559 impl_report_device_sync();
563 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
564#ifdef KOKKOS_ENABLE_CUDA
565 if (std::is_same<
typename t_dev::memory_space,
567 if (d_view.data() == h_view.data())
568 Kokkos::Impl::cuda_prefetch_pointer(
569 Impl::get_cuda_space(args...), d_view.data(),
570 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
574 deep_copy(args..., h_view, d_view);
575 modified_flags(0) = modified_flags(1) = 0;
576 impl_report_host_sync();
579 if (std::is_same<
typename t_host::memory_space,
580 typename t_dev::memory_space>::value) {
581 typename t_dev::execution_space().fence(
582 "Kokkos::DualView<>::sync: fence after syncing DualView");
583 typename t_host::execution_space().fence(
584 "Kokkos::DualView<>::sync: fence after syncing DualView");
588 template <
class Device>
589 void sync(
const std::enable_if_t<
590 (std::is_same<
typename traits::data_type,
591 typename traits::non_const_data_type>::value) ||
592 (std::is_same<Device, int>::value),
594 sync_impl<Device>(std::true_type{});
597 template <
class Device,
class ExecutionSpace>
598 void sync(
const ExecutionSpace& exec,
599 const std::enable_if_t<
600 (std::is_same<
typename traits::data_type,
601 typename traits::non_const_data_type>::value) ||
602 (std::is_same<Device, int>::value),
604 sync_impl<Device>(std::true_type{}, exec);
608 template <
class Device,
class... Args>
609 void sync_impl(std::false_type, Args
const&...) {
610 if (modified_flags.data() ==
nullptr)
return;
612 int dev = get_device_side<Device>();
615 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
616 Impl::throw_runtime_exception(
617 "Calling sync on a DualView with a const datatype.");
619 impl_report_device_sync();
622 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
623 Impl::throw_runtime_exception(
624 "Calling sync on a DualView with a const datatype.");
626 impl_report_host_sync();
630 template <
class Device>
631 void sync(
const std::enable_if_t<
632 (!std::is_same<
typename traits::data_type,
633 typename traits::non_const_data_type>::value) ||
634 (std::is_same<Device, int>::value),
636 sync_impl<Device>(std::false_type{});
638 template <
class Device,
class ExecutionSpace>
639 void sync(
const ExecutionSpace& exec,
640 const std::enable_if_t<
641 (!std::is_same<
typename traits::data_type,
642 typename traits::non_const_data_type>::value) ||
643 (std::is_same<Device, int>::value),
645 sync_impl<Device>(std::false_type{}, exec);
649 template <
typename... Args>
650 void sync_host_impl(Args
const&... args) {
651 if (!std::is_same<
typename traits::data_type,
652 typename traits::non_const_data_type>::value)
653 Impl::throw_runtime_exception(
654 "Calling sync_host on a DualView with a const datatype.");
655 if (modified_flags.data() ==
nullptr)
return;
656 if (modified_flags(1) > modified_flags(0)) {
657#ifdef KOKKOS_ENABLE_CUDA
658 if (std::is_same<
typename t_dev::memory_space,
660 if (d_view.data() == h_view.data())
661 Kokkos::Impl::cuda_prefetch_pointer(
662 Impl::get_cuda_space(args...), d_view.data(),
663 sizeof(
typename t_dev::value_type) * d_view.span(),
false);
667 deep_copy(args..., h_view, d_view);
668 modified_flags(1) = modified_flags(0) = 0;
669 impl_report_host_sync();
673 template <
class ExecSpace>
674 void sync_host(
const ExecSpace& exec) {
675 sync_host_impl(exec);
677 void sync_host() { sync_host_impl(); }
680 template <
typename... Args>
681 void sync_device_impl(Args
const&... args) {
682 if (!std::is_same<
typename traits::data_type,
683 typename traits::non_const_data_type>::value)
684 Impl::throw_runtime_exception(
685 "Calling sync_device on a DualView with a const datatype.");
686 if (modified_flags.data() ==
nullptr)
return;
687 if (modified_flags(0) > modified_flags(1)) {
688#ifdef KOKKOS_ENABLE_CUDA
689 if (std::is_same<
typename t_dev::memory_space,
691 if (d_view.data() == h_view.data())
692 Kokkos::Impl::cuda_prefetch_pointer(
693 Impl::get_cuda_space(args...), d_view.data(),
694 sizeof(
typename t_dev::value_type) * d_view.span(),
true);
698 deep_copy(args..., d_view, h_view);
699 modified_flags(1) = modified_flags(0) = 0;
700 impl_report_device_sync();
704 template <
class ExecSpace>
705 void sync_device(
const ExecSpace& exec) {
706 sync_device_impl(exec);
708 void sync_device() { sync_device_impl(); }
710 template <
class Device>
711 bool need_sync()
const {
712 if (modified_flags.data() ==
nullptr)
return false;
713 int dev = get_device_side<Device>();
716 if ((modified_flags(0) > 0) && (modified_flags(0) >= modified_flags(1))) {
721 if ((modified_flags(1) > 0) && (modified_flags(1) >= modified_flags(0))) {
728 inline bool need_sync_host()
const {
729 if (modified_flags.data() ==
nullptr)
return false;
730 return modified_flags(0) < modified_flags(1);
733 inline bool need_sync_device()
const {
734 if (modified_flags.data() ==
nullptr)
return false;
735 return modified_flags(1) < modified_flags(0);
737 void impl_report_device_modification() {
738 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
740 Kokkos::Tools::modifyDualView(
742 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(d_view.data()) -
747 void impl_report_host_modification() {
748 if (Kokkos::Tools::Experimental::get_callbacks().modify_dual_view !=
750 Kokkos::Tools::modifyDualView(
752 reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(h_view.data()) -
762 template <
class Device,
class Dummy = DualView,
763 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
766 if (modified_flags.data() ==
nullptr) {
767 modified_flags = t_modified_flags(
"DualView::modified_flags");
770 int dev = get_device_side<Device>();
775 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
776 : modified_flags(0)) +
778 impl_report_device_modification();
783 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
784 : modified_flags(0)) +
786 impl_report_host_modification();
789#ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
790 if (modified_flags(0) && modified_flags(1)) {
791 std::string msg =
"Kokkos::DualView::modify ERROR: ";
792 msg +=
"Concurrent modification of host and device views ";
793 msg +=
"in DualView \"";
794 msg += d_view.label();
802 class Device,
class Dummy = DualView,
803 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
808 template <
class Dummy = DualView,
809 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
811 inline void modify_host() {
812 if (modified_flags.data() !=
nullptr) {
814 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
815 : modified_flags(0)) +
817 impl_report_host_modification();
818#ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
819 if (modified_flags(0) && modified_flags(1)) {
820 std::string msg =
"Kokkos::DualView::modify_host ERROR: ";
821 msg +=
"Concurrent modification of host and device views ";
822 msg +=
"in DualView \"";
823 msg += d_view.label();
832 class Dummy = DualView,
833 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
834 inline void modify_host() {
838 template <
class Dummy = DualView,
839 std::enable_if_t<!Dummy::impl_dualview_is_single_device::value>* =
841 inline void modify_device() {
842 if (modified_flags.data() !=
nullptr) {
844 (modified_flags(1) > modified_flags(0) ? modified_flags(1)
845 : modified_flags(0)) +
847 impl_report_device_modification();
848#ifdef KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
849 if (modified_flags(0) && modified_flags(1)) {
850 std::string msg =
"Kokkos::DualView::modify_device ERROR: ";
851 msg +=
"Concurrent modification of host and device views ";
852 msg +=
"in DualView \"";
853 msg += d_view.label();
862 class Dummy = DualView,
863 std::enable_if_t<Dummy::impl_dualview_is_single_device::value>* =
nullptr>
864 inline void modify_device() {
868 inline void clear_sync_state() {
869 if (modified_flags.data() !=
nullptr)
870 modified_flags(1) = modified_flags(0) = 0;
882 template <
class... ViewCtorArgs>
883 void impl_realloc(
const size_t n0,
const size_t n1,
const size_t n2,
884 const size_t n3,
const size_t n4,
const size_t n5,
885 const size_t n6,
const size_t n7,
886 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
887 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
889 static_assert(!alloc_prop_input::has_label,
890 "The view constructor arguments passed to Kokkos::realloc "
891 "must not include a label!");
893 !alloc_prop_input::has_pointer,
894 "The view constructor arguments passed to Kokkos::realloc must "
895 "not include a pointer!");
897 !alloc_prop_input::has_memory_space,
898 "The view constructor arguments passed to Kokkos::realloc must "
899 "not include a memory space instance!");
901 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
902 const bool sizeMismatch =
903 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
906 ::Kokkos::realloc(arg_prop, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
907 if (alloc_prop_input::initialize) {
908 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
911 typename t_host::memory_space(), d_view);
913 }
else if (alloc_prop_input::initialize) {
914 if constexpr (alloc_prop_input::has_execution_space) {
915 const auto& exec_space =
916 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
917 ::Kokkos::deep_copy(exec_space, d_view,
typename t_dev::value_type{});
919 ::Kokkos::deep_copy(d_view,
typename t_dev::value_type{});
923 if (modified_flags.data() ==
nullptr) {
924 modified_flags = t_modified_flags(
"DualView::modified_flags");
926 modified_flags(1) = modified_flags(0) = 0;
929 template <
class... ViewCtorArgs>
930 void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
931 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
932 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
933 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
934 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
935 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
936 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
937 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
938 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
939 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, arg_prop);
942 void realloc(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
943 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
944 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
945 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
946 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
947 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
948 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
949 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
950 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Impl::ViewCtorProp<>{});
953 template <
typename I>
954 std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
955 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
956 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
957 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
958 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
959 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
960 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
961 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
962 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
963 impl_realloc(n0, n1, n2, n3, n4, n5, n6, n7, Kokkos::view_alloc(arg_prop));
970 template <
class... ViewCtorArgs>
971 void impl_resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
972 const size_t n0,
const size_t n1,
const size_t n2,
973 const size_t n3,
const size_t n4,
const size_t n5,
974 const size_t n6,
const size_t n7) {
975 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
977 static_assert(!alloc_prop_input::has_label,
978 "The view constructor arguments passed to Kokkos::resize "
979 "must not include a label!");
981 !alloc_prop_input::has_pointer,
982 "The view constructor arguments passed to Kokkos::resize must "
983 "not include a pointer!");
985 !alloc_prop_input::has_memory_space,
986 "The view constructor arguments passed to Kokkos::resize must "
987 "not include a memory space instance!");
989 const size_t new_extents[8] = {n0, n1, n2, n3, n4, n5, n6, n7};
990 const bool sizeMismatch =
991 Impl::size_mismatch(h_view, h_view.rank_dynamic, new_extents);
993 if (modified_flags.data() ==
nullptr) {
994 modified_flags = t_modified_flags(
"DualView::modified_flags");
997 [[maybe_unused]]
auto resize_on_device = [&](
const auto& properties) {
1000 ::Kokkos::resize(properties, d_view, n0, n1, n2, n3, n4, n5, n6, n7);
1001 if (alloc_prop_input::initialize) {
1002 h_view = create_mirror_view(
typename t_host::memory_space(), d_view);
1005 typename t_host::memory_space(), d_view);
1009 ++modified_flags(1);
1013 [[maybe_unused]]
auto resize_on_host = [&](
const auto& properties) {
1016 ::Kokkos::resize(properties, h_view, n0, n1, n2, n3, n4, n5, n6, n7);
1017 if (alloc_prop_input::initialize) {
1018 d_view = create_mirror_view(
typename t_dev::memory_space(), h_view);
1022 typename t_dev::memory_space(), h_view);
1026 ++modified_flags(0);
1030 constexpr bool has_execution_space = alloc_prop_input::has_execution_space;
1032 if constexpr (has_execution_space) {
1033 using ExecSpace =
typename alloc_prop_input::execution_space;
1034 const auto& exec_space =
1035 Impl::get_property<Impl::ExecutionSpaceTag>(arg_prop);
1036 constexpr bool exec_space_can_access_device =
1037 SpaceAccessibility<ExecSpace,
1038 typename t_dev::memory_space>::accessible;
1039 constexpr bool exec_space_can_access_host =
1040 SpaceAccessibility<ExecSpace,
1041 typename t_host::memory_space>::accessible;
1042 static_assert(exec_space_can_access_device || exec_space_can_access_host);
1043 if constexpr (exec_space_can_access_device) {
1044 sync<typename t_dev::memory_space>(exec_space);
1045 resize_on_device(arg_prop);
1048 if constexpr (exec_space_can_access_host) {
1049 sync<typename t_host::memory_space>(exec_space);
1050 resize_on_host(arg_prop);
1054 if (modified_flags(1) >= modified_flags(0)) {
1055 resize_on_device(arg_prop);
1057 resize_on_host(arg_prop);
1062 void resize(
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1063 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1064 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1065 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1066 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1067 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1068 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1069 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1070 impl_resize(Impl::ViewCtorProp<>{}, n0, n1, n2, n3, n4, n5, n6, n7);
1073 template <
class... ViewCtorArgs>
1074 void resize(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1075 const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1076 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1077 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1078 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1079 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1080 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1081 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1082 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1083 impl_resize(arg_prop, n0, n1, n2, n3, n4, n5, n6, n7);
1087 std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1088 const I& arg_prop,
const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1089 const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1090 const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1091 const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1092 const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1093 const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1094 const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1095 const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1096 impl_resize(Kokkos::view_alloc(arg_prop), n0, n1, n2, n3, n4, n5, n6, n7);
1104 KOKKOS_INLINE_FUNCTION
constexpr size_t span()
const {
return d_view.span(); }
1106 KOKKOS_INLINE_FUNCTION
bool span_is_contiguous()
const {
1107 return d_view.span_is_contiguous();
1111 template <
typename iType>
1112 void stride(iType* stride_)
const {
1113 d_view.stride(stride_);
1116 template <
typename iType>
1117 KOKKOS_INLINE_FUNCTION
constexpr std::enable_if_t<
1118 std::is_integral<iType>::value,
size_t>
1119 extent(
const iType& r)
const {
1120 return d_view.extent(r);
1123 template <
typename iType>
1124 KOKKOS_INLINE_FUNCTION
constexpr std::enable_if_t<
1125 std::is_integral<iType>::value,
int>
1126 extent_int(
const iType& r)
const {
1127 return static_cast<int>(d_view.extent(r));
1144template <
class D,
class A1,
class A2,
class A3,
class... Args>
1145struct DualViewSubview {
1146 using dst_traits =
typename Kokkos::Impl::ViewMapping<
1149 using type = Kokkos::DualView<
1150 typename dst_traits::data_type,
typename dst_traits::array_layout,
1151 typename dst_traits::device_type,
typename dst_traits::memory_traits>;
1156template <
class D,
class A1,
class A2,
class A3,
class... Args>
1157typename Impl::DualViewSubview<D, A1, A2, A3, Args...>::type subview(
1158 const DualView<D, A1, A2, A3>& src, Args... args) {
1159 return typename Impl::DualViewSubview<D, A1, A2, A3, Args...>::type(src,
1174template <
class DT,
class DL,
class DD,
class DM,
class ST,
class SL,
class SD,
1177 DualView<DT, DL, DD, DM> dst,
1178 const DualView<ST, SL, SD, SM>& src) {
1179 if (src.need_sync_device()) {
1180 deep_copy(dst.h_view, src.h_view);
1183 deep_copy(dst.d_view, src.d_view);
1184 dst.modify_device();
1188template <
class ExecutionSpace,
class DT,
class DL,
class DD,
class DM,
1189 class ST,
class SL,
class SD,
class SM>
1191 const ExecutionSpace& exec,
1192 DualView<DT, DL, DD, DM> dst,
1193 const DualView<ST, SL, SD, SM>& src) {
1194 if (src.need_sync_device()) {
1195 deep_copy(exec, dst.h_view, src.h_view);
1198 deep_copy(exec, dst.d_view, src.d_view);
1199 dst.modify_device();
1214template <
class... Properties,
class... Args>
1215void resize(DualView<Properties...>& dv, Args&&... args)
noexcept(
1216 noexcept(dv.resize(std::forward<Args>(args)...))) {
1217 dv.resize(std::forward<Args>(args)...);
1220template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1222 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1223 DualView<Properties...>& dv,
1224 Args&&... args)
noexcept(
noexcept(dv.resize(arg_prop,
1225 std::forward<Args>(args)...))) {
1226 dv.resize(arg_prop, std::forward<Args>(args)...);
1229template <
class I,
class... Properties,
class... Args>
1230std::enable_if_t<Impl::is_view_ctor_property<I>::value> resize(
1231 const I& arg_prop, DualView<Properties...>& dv,
1232 Args&&... args)
noexcept(
noexcept(dv.resize(arg_prop,
1233 std::forward<Args>(args)...))) {
1234 dv.resize(arg_prop, std::forward<Args>(args)...);
1237template <
class... ViewCtorArgs,
class... Properties,
class... Args>
1238void realloc(
const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1239 DualView<Properties...>& dv,
1240 Args&&... args)
noexcept(
noexcept(dv
1241 .realloc(std::forward<Args>(
1243 dv.realloc(arg_prop, std::forward<Args>(args)...);
1246template <
class... Properties,
class... Args>
1247void realloc(DualView<Properties...>& dv, Args&&... args)
noexcept(
1248 noexcept(dv.realloc(std::forward<Args>(args)...))) {
1249 dv.realloc(std::forward<Args>(args)...);
1252template <
class I,
class... Properties,
class... Args>
1253std::enable_if_t<Impl::is_view_ctor_property<I>::value> realloc(
1254 const I& arg_prop, DualView<Properties...>& dv,
1255 Args&&... args)
noexcept(
noexcept(dv.realloc(arg_prop,
1258 dv.realloc(arg_prop, std::forward<Args>(args)...);
1263#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
1264#undef KOKKOS_IMPL_PUBLIC_INCLUDE
1265#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DUALVIEW
A thread safe view to a bitset.