Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Details_WrappedDualView.hpp
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TPETRA_DETAILS_WRAPPEDDUALVIEW_HPP
11#define TPETRA_DETAILS_WRAPPEDDUALVIEW_HPP
12
13#include <Tpetra_Access.hpp>
14#include <Tpetra_Details_temporaryViewUtils.hpp>
15#include <Kokkos_DualView.hpp>
16#include "Teuchos_TestForException.hpp"
18#include <sstream>
19
20//#define DEBUG_UVM_REMOVAL // Works only with gcc > 4.8
21
22#ifdef DEBUG_UVM_REMOVAL
23
24#define DEBUG_UVM_REMOVAL_ARGUMENT ,const char* callerstr = __builtin_FUNCTION(),const char * filestr=__builtin_FILE(),const int linnum = __builtin_LINE()
25
26#define DEBUG_UVM_REMOVAL_PRINT_CALLER(fn) \
27 { \
28 auto envVarSet = std::getenv("TPETRA_UVM_REMOVAL"); \
29 if (envVarSet && (std::strcmp(envVarSet,"1") == 0)) \
30 std::cout << (fn) << " called from " << callerstr \
31 << " at " << filestr << ":"<<linnum \
32 << " host cnt " << getRawHostView().use_count() \
33 << " device cnt " << getRawDeviceView().use_count() \
34 << std::endl; \
35 }
36
37#else
38
39#define DEBUG_UVM_REMOVAL_ARGUMENT
40#define DEBUG_UVM_REMOVAL_PRINT_CALLER(fn)
41
42#endif
43
45namespace Tpetra {
46
47 // We really need this forward declaration here for friend to work
48 template<typename SC, typename LO, typename GO, typename NO>
49 class MultiVector;
50
51
54namespace Details {
55
56namespace impl {
57
58template <typename DualViewType>
59struct hasConstData {
60 using valueType = typename DualViewType::value_type;
61 using constValueType = typename DualViewType::const_value_type;
62 static constexpr bool value = std::is_same<valueType, constValueType>::value;
63};
64
65template <typename DualViewType>
66using enableIfConstData = std::enable_if_t<hasConstData<DualViewType>::value>;
67
68template <typename DualViewType>
69using enableIfNonConstData = std::enable_if_t<!hasConstData<DualViewType>::value>;
70
71template <typename DualViewType>
72enableIfNonConstData<DualViewType>
73sync_host(DualViewType dualView) {
74 // This will sync, but only if needed
75 dualView.sync_host();
76}
77
78template <typename DualViewType>
79enableIfConstData<DualViewType>
80sync_host(DualViewType dualView) { }
81
82template <typename DualViewType>
83enableIfNonConstData<DualViewType>
84sync_device(DualViewType dualView) {
85 // This will sync, but only if needed
86 dualView.sync_device();
87}
88
89template <typename DualViewType>
90enableIfConstData<DualViewType>
91sync_device(DualViewType dualView) { }
92
93}// end namespace Impl
94
98
99extern bool wdvTrackingEnabled;
100
105void disableWDVTracking();
106
108void enableWDVTracking();
109
112template <typename DualViewType>
113class WrappedDualView {
114public:
115
116 using DVT = DualViewType;
117 using t_host = typename DualViewType::t_host;
118 using t_dev = typename DualViewType::t_dev;
119
120 using HostType = typename t_host::device_type;
121 using DeviceType = typename t_dev::device_type;
122
123private:
124 static constexpr bool dualViewHasNonConstData = !impl::hasConstData<DualViewType>::value;
125 static constexpr bool deviceMemoryIsHostAccessible =
126 Kokkos::SpaceAccessibility<Kokkos::DefaultHostExecutionSpace, typename t_dev::memory_space>::accessible;
127
128private:
129 template <typename>
130 friend class WrappedDualView;
131
132public:
133 WrappedDualView() {}
134
135 WrappedDualView(DualViewType dualV)
136 : originalDualView(dualV),
137 dualView(originalDualView)
138 { }
139
141 template <class SrcDualViewType>
142 WrappedDualView(const WrappedDualView<SrcDualViewType>& src)
143 : originalDualView(src.originalDualView),
144 dualView(src.dualView)
145 { }
146
148 template <class SrcDualViewType>
149 WrappedDualView& operator=(const WrappedDualView<SrcDualViewType>& src) {
150 originalDualView = src.originalDualView;
151 dualView = src.dualView;
152 return *this;
153 }
154
155 // This is an expert-only constructor
156 // For WrappedDualView to manage synchronizations correctly,
157 // it must have an DualView which is not a subview to due the
158 // sync's on. This is what origDualV is for. In this case,
159 // dualV is a subview of origDualV.
160 WrappedDualView(DualViewType dualV,DualViewType origDualV)
161 : originalDualView(origDualV),
162 dualView(dualV)
163 { }
164
165
166 WrappedDualView(const t_dev deviceView) {
167 TEUCHOS_TEST_FOR_EXCEPTION(
168 deviceView.data() != nullptr && deviceView.use_count() == 0,
169 std::invalid_argument,
170 "Tpetra::Details::WrappedDualView: cannot construct with a device view that\n"
171 "does not own its memory (i.e. constructed with a raw pointer and dimensions)\n"
172 "because the WrappedDualView needs to assume ownership of the memory.");
173 //If the provided view is default-constructed (null, 0 extent, 0 use count),
174 //leave the host mirror default-constructed as well in order to have a matching use count of 0.
175 t_host hostView;
176 if(deviceView.use_count() != 0)
177 {
178 hostView = Kokkos::create_mirror_view(
179 Kokkos::WithoutInitializing,
180 typename t_host::memory_space(),
181 deviceView);
182 }
183 originalDualView = DualViewType(deviceView, hostView);
184 originalDualView.clear_sync_state();
185 originalDualView.modify_device();
186 dualView = originalDualView;
187 }
188
189 // 1D View constructors
190 WrappedDualView(const WrappedDualView parent, int offset, int numEntries) {
191 originalDualView = parent.originalDualView;
192 dualView = getSubview(parent.dualView, offset, numEntries);
193 }
194
195
196 // 2D View Constructors
197 WrappedDualView(const WrappedDualView parent,const Kokkos::pair<size_t,size_t>& rowRng, const Kokkos::ALL_t& colRng) {
198 originalDualView = parent.originalDualView;
199 dualView = getSubview2D(parent.dualView,rowRng,colRng);
200 }
201
202 WrappedDualView(const WrappedDualView parent,const Kokkos::ALL_t &rowRng, const Kokkos::pair<size_t,size_t>& colRng) {
203 originalDualView = parent.originalDualView;
204 dualView = getSubview2D(parent.dualView,rowRng,colRng);
205 }
206
207 WrappedDualView(const WrappedDualView parent,const Kokkos::pair<size_t,size_t>& rowRng, const Kokkos::pair<size_t,size_t>& colRng) {
208 originalDualView = parent.originalDualView;
209 dualView = getSubview2D(parent.dualView,rowRng,colRng);
210 }
211
212 size_t extent(const int i) const {
213 return getRawHostView().extent(i);
214 }
215
216 void stride(size_t * stride_) const {
217 dualView.stride(stride_);
218 }
219
220
221 size_t origExtent(const int i) const {
222 return getRawHostOriginalView().extent(i);
223 }
224
225 const char * label() const {
226 return getRawDeviceView().label();
227 }
228
229
230 typename t_host::const_type
231 getHostView(Access::ReadOnlyStruct
232 DEBUG_UVM_REMOVAL_ARGUMENT
233 ) const
234 {
235 DEBUG_UVM_REMOVAL_PRINT_CALLER("getHostViewReadOnly");
236
237 if(needsSyncPath()) {
238 throwIfDeviceViewAlive();
239 impl::sync_host(originalDualView);
240 }
241 return getRawHostView();
242 }
243
244 t_host
245 getHostView(Access::ReadWriteStruct
246 DEBUG_UVM_REMOVAL_ARGUMENT
247 )
248 {
249 DEBUG_UVM_REMOVAL_PRINT_CALLER("getHostViewReadWrite");
250 static_assert(dualViewHasNonConstData,
251 "ReadWrite views are not available for DualView with const data");
252 if(needsSyncPath()) {
253 throwIfDeviceViewAlive();
254 impl::sync_host(originalDualView);
255 originalDualView.modify_host();
256 }
257
258 return getRawHostView();
259 }
260
261 t_host
262 getHostView(Access::OverwriteAllStruct
263 DEBUG_UVM_REMOVAL_ARGUMENT
264 )
265 {
266 DEBUG_UVM_REMOVAL_PRINT_CALLER("getHostViewOverwriteAll");
267 static_assert(dualViewHasNonConstData,
268 "OverwriteAll views are not available for DualView with const data");
269 if (iAmASubview()) {
270 return getHostView(Access::ReadWrite);
271 }
272 if(needsSyncPath()) {
273 throwIfDeviceViewAlive();
274 if (deviceMemoryIsHostAccessible) Kokkos::fence("WrappedDualView::getHostView");
275 dualView.clear_sync_state();
276 dualView.modify_host();
277 }
278 return getRawHostView();
279 }
280
281 typename t_dev::const_type
282 getDeviceView(Access::ReadOnlyStruct
283 DEBUG_UVM_REMOVAL_ARGUMENT
284 ) const
285 {
286 DEBUG_UVM_REMOVAL_PRINT_CALLER("getDeviceViewReadOnly");
287 if(needsSyncPath()) {
288 throwIfHostViewAlive();
289 impl::sync_device(originalDualView);
290 }
291 return getRawDeviceView();
292 }
293
294 t_dev
295 getDeviceView(Access::ReadWriteStruct
296 DEBUG_UVM_REMOVAL_ARGUMENT
297 )
298 {
299 DEBUG_UVM_REMOVAL_PRINT_CALLER("getDeviceViewReadWrite");
300 static_assert(dualViewHasNonConstData,
301 "ReadWrite views are not available for DualView with const data");
302 if(needsSyncPath()) {
303 throwIfHostViewAlive();
304 impl::sync_device(originalDualView);
305 originalDualView.modify_device();
306 }
307 return getRawDeviceView();
308 }
309
310 t_dev
311 getDeviceView(Access::OverwriteAllStruct
312 DEBUG_UVM_REMOVAL_ARGUMENT
313 )
314 {
315 DEBUG_UVM_REMOVAL_PRINT_CALLER("getDeviceViewOverwriteAll");
316 static_assert(dualViewHasNonConstData,
317 "OverwriteAll views are not available for DualView with const data");
318 if (iAmASubview()) {
319 return getDeviceView(Access::ReadWrite);
320 }
321 if(needsSyncPath()) {
322 throwIfHostViewAlive();
323 if (deviceMemoryIsHostAccessible) Kokkos::fence("WrappedDualView::getDeviceView");
324 dualView.clear_sync_state();
325 dualView.modify_device();
326 }
327 return getRawDeviceView();
328 }
329
330 template<class TargetDeviceType>
331 typename std::remove_reference<decltype(std::declval<DualViewType>().template view<TargetDeviceType>())>::type::const_type
332 getView (Access::ReadOnlyStruct s DEBUG_UVM_REMOVAL_ARGUMENT) const {
333 using ReturnViewType = typename std::remove_reference<decltype(std::declval<DualViewType>().template view<TargetDeviceType>())>::type::const_type;
334 using ReturnDeviceType = typename ReturnViewType::device_type;
335 constexpr bool returnDevice = std::is_same<ReturnDeviceType, DeviceType>::value;
336 if(returnDevice) {
337 DEBUG_UVM_REMOVAL_PRINT_CALLER("getView<Device>ReadOnly");
338 if(needsSyncPath()) {
339 throwIfHostViewAlive();
340 impl::sync_device(originalDualView);
341 }
342 }
343 else {
344 DEBUG_UVM_REMOVAL_PRINT_CALLER("getView<Host>ReadOnly");
345 if(needsSyncPath()) {
346 throwIfDeviceViewAlive();
347 impl::sync_host(originalDualView);
348 }
349 }
350
351 return dualView.template view<TargetDeviceType>();
352 }
353
354
355 template<class TargetDeviceType>
356 typename std::remove_reference<decltype(std::declval<DualViewType>().template view<TargetDeviceType>())>::type
357 getView (Access::ReadWriteStruct s DEBUG_UVM_REMOVAL_ARGUMENT) const {
358 using ReturnViewType = typename std::remove_reference<decltype(std::declval<DualViewType>().template view<TargetDeviceType>())>::type;
359 using ReturnDeviceType = typename ReturnViewType::device_type;
360 constexpr bool returnDevice = std::is_same<ReturnDeviceType, DeviceType>::value;
361
362 if(returnDevice) {
363 DEBUG_UVM_REMOVAL_PRINT_CALLER("getView<Device>ReadWrite");
364 static_assert(dualViewHasNonConstData,
365 "ReadWrite views are not available for DualView with const data");
366 if(needsSyncPath()) {
367 throwIfHostViewAlive();
368 impl::sync_device(originalDualView);
369 originalDualView.modify_device();
370 }
371 }
372 else {
373 DEBUG_UVM_REMOVAL_PRINT_CALLER("getView<Host>ReadWrite");
374 static_assert(dualViewHasNonConstData,
375 "ReadWrite views are not available for DualView with const data");
376 if(needsSyncPath()) {
377 throwIfDeviceViewAlive();
378 impl::sync_host(originalDualView);
379 originalDualView.modify_host();
380 }
381 }
382
383 return dualView.template view<TargetDeviceType>();
384 }
385
386
387 template<class TargetDeviceType>
388 typename std::remove_reference<decltype(std::declval<DualViewType>().template view<TargetDeviceType>())>::type
389 getView (Access::OverwriteAllStruct s DEBUG_UVM_REMOVAL_ARGUMENT) const {
390 using ReturnViewType = typename std::remove_reference<decltype(std::declval<DualViewType>().template view<TargetDeviceType>())>::type;
391 using ReturnDeviceType = typename ReturnViewType::device_type;
392
393 if (iAmASubview())
394 return getView<TargetDeviceType>(Access::ReadWrite);
395
396 constexpr bool returnDevice = std::is_same<ReturnDeviceType, DeviceType>::value;
397
398 if(returnDevice) {
399 DEBUG_UVM_REMOVAL_PRINT_CALLER("getView<Device>OverwriteAll");
400 static_assert(dualViewHasNonConstData,
401 "OverwriteAll views are not available for DualView with const data");
402 if(needsSyncPath()) {
403 throwIfHostViewAlive();
404 dualView.clear_sync_state();
405 dualView.modify_host();
406 }
407 }
408 else {
409 DEBUG_UVM_REMOVAL_PRINT_CALLER("getView<Host>OverwriteAll");
410 static_assert(dualViewHasNonConstData,
411 "OverwriteAll views are not available for DualView with const data");
412 if(needsSyncPath()) {
413 throwIfDeviceViewAlive();
414 dualView.clear_sync_state();
415 dualView.modify_device();
416 }
417 }
418
419 return dualView.template view<TargetDeviceType>();
420 }
421
422
423 typename t_host::const_type
424 getHostSubview(int offset, int numEntries, Access::ReadOnlyStruct
425 DEBUG_UVM_REMOVAL_ARGUMENT
426 ) const
427 {
428 DEBUG_UVM_REMOVAL_PRINT_CALLER("getHostSubviewReadOnly");
429 if(needsSyncPath()) {
430 throwIfDeviceViewAlive();
431 impl::sync_host(originalDualView);
432 }
433 return getSubview(getRawHostView(), offset, numEntries);
434 }
435
436 t_host
437 getHostSubview(int offset, int numEntries, Access::ReadWriteStruct
438 DEBUG_UVM_REMOVAL_ARGUMENT
439 )
440 {
441 DEBUG_UVM_REMOVAL_PRINT_CALLER("getHostSubviewReadWrite");
442 static_assert(dualViewHasNonConstData,
443 "ReadWrite views are not available for DualView with const data");
444 if(needsSyncPath()) {
445 throwIfDeviceViewAlive();
446 impl::sync_host(originalDualView);
447 originalDualView.modify_host();
448 }
449 return getSubview(getRawHostView(), offset, numEntries);
450 }
451
452 t_host
453 getHostSubview(int offset, int numEntries, Access::OverwriteAllStruct
454 DEBUG_UVM_REMOVAL_ARGUMENT
455 )
456 {
457 DEBUG_UVM_REMOVAL_PRINT_CALLER("getHostSubviewOverwriteAll");
458 static_assert(dualViewHasNonConstData,
459 "OverwriteAll views are not available for DualView with const data");
460 return getHostSubview(offset, numEntries, Access::ReadWrite);
461 }
462
463 typename t_dev::const_type
464 getDeviceSubview(int offset, int numEntries, Access::ReadOnlyStruct
465 DEBUG_UVM_REMOVAL_ARGUMENT
466 ) const
467 {
468 DEBUG_UVM_REMOVAL_PRINT_CALLER("getDeviceSubviewReadOnly");
469 if(needsSyncPath()) {
470 throwIfHostViewAlive();
471 impl::sync_device(originalDualView);
472 }
473 return getSubview(getRawDeviceView(), offset, numEntries);
474 }
475
476 t_dev
477 getDeviceSubview(int offset, int numEntries, Access::ReadWriteStruct
478 DEBUG_UVM_REMOVAL_ARGUMENT
479 )
480 {
481 DEBUG_UVM_REMOVAL_PRINT_CALLER("getDeviceSubviewReadWrite");
482 static_assert(dualViewHasNonConstData,
483 "ReadWrite views are not available for DualView with const data");
484 if(needsSyncPath()) {
485 throwIfHostViewAlive();
486 impl::sync_device(originalDualView);
487 originalDualView.modify_device();
488 }
489 return getSubview(getRawDeviceView(), offset, numEntries);
490 }
491
492 t_dev
493 getDeviceSubview(int offset, int numEntries, Access::OverwriteAllStruct
494 DEBUG_UVM_REMOVAL_ARGUMENT
495 )
496 {
497 DEBUG_UVM_REMOVAL_PRINT_CALLER("getDeviceSubviewOverwriteAll");
498 static_assert(dualViewHasNonConstData,
499 "OverwriteAll views are not available for DualView with const data");
500 return getDeviceSubview(offset, numEntries, Access::ReadWrite);
501 }
502
503
504 // Debugging functions to get copies of the view state
505 typename t_host::HostMirror getHostCopy() const {
506 auto X_dev = getRawHostView();
507 if(X_dev.span_is_contiguous()) {
508 auto mirror = Kokkos::create_mirror_view(X_dev);
509 Kokkos::deep_copy(mirror,X_dev);
510 return mirror;
511 }
512 else {
513 auto X_contig = Tpetra::Details::TempView::toLayout<decltype(X_dev), Kokkos::LayoutLeft>(X_dev);
514 auto mirror = Kokkos::create_mirror_view(X_contig);
515 Kokkos::deep_copy(mirror,X_contig);
516 return mirror;
517 }
518 }
519
520 typename t_dev::HostMirror getDeviceCopy() const {
521 auto X_dev = getRawDeviceView();
522 if(X_dev.span_is_contiguous()) {
523 auto mirror = Kokkos::create_mirror_view(X_dev);
524 Kokkos::deep_copy(mirror,X_dev);
525 return mirror;
526 }
527 else {
528 auto X_contig = Tpetra::Details::TempView::toLayout<decltype(X_dev), Kokkos::LayoutLeft>(X_dev);
529 auto mirror = Kokkos::create_mirror_view(X_contig);
530 Kokkos::deep_copy(mirror,X_contig);
531 return mirror;
532 }
533 }
534
535 // Debugging functions for validity checks
536 bool is_valid_host() const {
537 return getRawHostView().size() == 0 || getRawHostView().data();
538 }
539
540 bool is_valid_device() const {
541 return getRawDeviceView().size() == 0 || getRawDeviceView().data();
542 }
543
544
545 bool need_sync_host() const {
546 return originalDualView.need_sync_host();
547 }
548
549 bool need_sync_device() const {
550 return originalDualView.need_sync_device();
551 }
552
553 int host_view_use_count() const {
554 return getRawHostOriginalView().use_count();
555 }
556
557 int device_view_use_count() const {
558 return getRawDeviceView().use_count();
559 }
560
561
562 // MultiVector really needs to get at the raw DualViews,
563 // but we'd very much prefer that users not.
564 template<typename SC, typename LO, typename GO, typename NO>
565 friend class ::Tpetra::MultiVector;
566
567private:
568
569 const auto& getRawHostOriginalView() const {
570#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
571 return originalDualView.h_view;
572#else
573 return originalDualView.view_host();
574#endif
575 }
576
577 const auto& getRawDeviceOriginalView() const {
578#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
579 return originalDualView.d_view;
580#else
581 return originalDualView.view_device();
582#endif
583 }
584
585 const auto& getRawHostView() const {
586#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
587 return dualView.h_view;
588#else
589 return dualView.view_host();
590#endif
591 }
592
593 const auto& getRawDeviceView() const {
594#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
595 return dualView.d_view;
596#else
597 return dualView.view_device();
598#endif
599 }
600
601 // A Kokkos implementation of WrappedDualView will have to make these
602 // functions publically accessable, but in the Tpetra version, we'd
603 // really rather not.
604 DualViewType getOriginalDualView() const {
605 return originalDualView;
606 }
607
608 DualViewType getDualView() const {
609 return dualView;
610 }
611
612 template <typename ViewType>
613 ViewType getSubview(ViewType view, int offset, int numEntries) const {
614 return Kokkos::subview(view, Kokkos::pair<int, int>(offset, offset+numEntries));
615 }
616
617 template <typename ViewType,typename int_type>
618 ViewType getSubview2D(ViewType view, Kokkos::pair<int_type,int_type> offset0, const Kokkos::ALL_t&) const {
619 return Kokkos::subview(view,offset0,Kokkos::ALL());
620 }
621
622 template <typename ViewType,typename int_type>
623 ViewType getSubview2D(ViewType view, const Kokkos::ALL_t&, Kokkos::pair<int_type,int_type> offset1) const {
624 return Kokkos::subview(view,Kokkos::ALL(),offset1);
625 }
626
627 template <typename ViewType,typename int_type>
628 ViewType getSubview2D(ViewType view, Kokkos::pair<int_type,int_type> offset0, Kokkos::pair<int_type,int_type> offset1) const {
629 return Kokkos::subview(view,offset0,offset1);
630 }
631
632 bool memoryIsAliased() const {
633 return deviceMemoryIsHostAccessible && getRawHostView().data() == getRawDeviceView().data();
634 }
635
636
654 bool needsSyncPath() const {
656 return false;
657
658 // We check to see if the memory is not aliased *or* if it is a supported
659 // (heterogeneous memory) accelerator (for shared host/device memory).
660 return !memoryIsAliased() || Spaces::is_gpu_exec_space<typename DualViewType::execution_space>();
661 }
662
663
664 void throwIfViewsAreDifferentSizes() const {
665 // Here we check *size* (the product of extents) rather than each extent individually.
666 // This is mostly designed to catch people resizing one view, but not the other.
667 if(getRawDeviceView().size() != getRawHostView().size()) {
668 std::ostringstream msg;
669 msg << "Tpetra::Details::WrappedDualView (name = " << getRawDeviceView().label()
670 << "; host and device views are different sizes: "
671 << getRawHostView().size() << " vs " <<getRawHostView().size();
672 throw std::runtime_error(msg.str());
673 }
674 }
675
676 void throwIfHostViewAlive() const {
677 throwIfViewsAreDifferentSizes();
678 if (getRawHostView().use_count() > getRawDeviceView().use_count()) {
679 std::ostringstream msg;
680 msg << "Tpetra::Details::WrappedDualView (name = " << getRawDeviceView().label()
681 << "; host use_count = " << getRawHostView().use_count()
682 << "; device use_count = " << getRawDeviceView().use_count() << "): "
683 << "Cannot access data on device while a host view is alive";
684 throw std::runtime_error(msg.str());
685 }
686 }
687
688 void throwIfDeviceViewAlive() const {
689 throwIfViewsAreDifferentSizes();
690 if (getRawDeviceView().use_count() > getRawHostView().use_count()) {
691 std::ostringstream msg;
692 msg << "Tpetra::Details::WrappedDualView (name = " << getRawDeviceView().label()
693 << "; host use_count = " << getRawHostView().use_count()
694 << "; device use_count = " << getRawDeviceView().use_count() << "): "
695 << "Cannot access data on host while a device view is alive";
696 throw std::runtime_error(msg.str());
697 }
698 }
699
700 bool iAmASubview() {
701 return getRawHostOriginalView() != getRawHostView();
702 }
703
704 mutable DualViewType originalDualView;
705 mutable DualViewType dualView;
706};
707
708} // namespace Details
709
710} // namespace Tpetra
711
712#endif
A wrapper around Kokkos::DualView to safely manage data that might be replicated between host and dev...
WrappedDualView & operator=(const WrappedDualView< SrcDualViewType > &src)
Conversion assignment operator.
WrappedDualView(const WrappedDualView< SrcDualViewType > &src)
Conversion copy constructor.
One or more distributed dense vectors.
Nonmember function that computes a residual Computes R = B - A * X.
void disableWDVTracking()
Disable WrappedDualView reference-count tracking and syncing. Call this before entering a host-parall...
bool wdvTrackingEnabled
Whether WrappedDualView reference count checking is enabled. Initially true. Since the DualView sync ...
void enableWDVTracking()
Enable WrappedDualView reference-count tracking and syncing. Call this after exiting a host-parallel ...
Namespace Tpetra contains the class and methods constituting the Tpetra library.