Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_reallocDualViewIfNeeded.hpp
Go to the documentation of this file.
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_REALLOCDUALVIEWIFNEEDED_HPP
11 #define TPETRA_DETAILS_REALLOCDUALVIEWIFNEEDED_HPP
12 
19 
21 #include "Kokkos_DualView.hpp"
22 
23 namespace Tpetra {
24 namespace Details {
25 
49 template <class ValueType, class DeviceType>
50 bool reallocDualViewIfNeeded(Kokkos::DualView<ValueType*, DeviceType>& dv,
51  const size_t newSize,
52  const char newLabel[],
53  const size_t tooBigFactor = 2,
54  const bool needFenceBeforeRealloc = true) {
55  typedef typename DeviceType::execution_space execution_space;
56  typedef Kokkos::DualView<ValueType*, DeviceType> dual_view_type;
57  typedef Kokkos::pair<size_t, size_t> range_type;
58 
59  // Profiling this matters, because GPU allocations can be expensive.
61  ProfilingRegion region("Tpetra::Details::reallocDualViewIfNeeded");
62 
63  const size_t curSize = static_cast<size_t>(dv.extent(0));
64  if (curSize == newSize) {
65  return false; // did not reallocate
66  } else if (curSize < newSize) { // too small; need to reallocate
67  if (needFenceBeforeRealloc) {
68  execution_space().fence(); // keep this fence to respect needFenceBeforeRealloc
69  }
70  dv = dual_view_type(); // free first, in order to save memory
71  // If current size is 0, the DualView's Views likely lack a label.
72  dv = dual_view_type(curSize == 0 ? newLabel : dv.view_device().label(), newSize);
73  return true; // we did reallocate
74  } else {
75  if (newSize == 0) { // special case: realloc to 0 means always do it
76  if (needFenceBeforeRealloc) {
77  execution_space().fence(); // keep this fence to respect needFenceBeforeRealloc
78  }
79  // If current size is 0, the DualView's Views likely lack a label.
80  dv = dual_view_type(curSize == 0 ? newLabel : dv.view_device().label(), 0);
81  return true; // we did reallocate
82  }
83  // Instead of writing curSize >= tooBigFactor * newSize, express
84  // via division to avoid overflow (for very large right-hand side).
85  // We've already tested whether newSize == 0, so this is safe.
86  else if (curSize / newSize >= tooBigFactor) {
87  // The allocation is much too big, so free it and reallocate
88  // to the new, smaller size.
89  if (needFenceBeforeRealloc) {
90  execution_space().fence(); // keep this fence to respect needFenceBeforeRealloc
91  }
92  dv = dual_view_type(); // free first, in order to save memory
93  // If current size is 0, the DualView's Views likely lack a label.
94  dv = dual_view_type(curSize == 0 ? newLabel : dv.view_device().label(), newSize);
95  return true; // we did reallocate
96  } else {
97  auto d_view = Kokkos::subview(dv.view_device(), range_type(0, newSize));
98  auto h_view = Kokkos::subview(dv.view_host(), range_type(0, newSize));
99  dv = Kokkos::DualView<ValueType*, DeviceType>(d_view, h_view);
100  return false; // we did not reallocate
101  }
102  }
103 }
104 
106 template <class ValueType, class DeviceType>
107 bool reallocDualViewIfNeeded(Kokkos::DualView<ValueType*, DeviceType>& exports,
108  const size_t newSize,
109  const std::string& newLabel,
110  const size_t tooBigFactor = 2,
111  const bool needFenceBeforeRealloc = true) {
112  return reallocDualViewIfNeeded<ValueType, DeviceType>(exports, newSize,
113  newLabel.c_str(),
114  tooBigFactor,
115  needFenceBeforeRealloc);
116 }
117 
118 } // namespace Details
119 } // namespace Tpetra
120 
121 #endif // TPETRA_DETAILS_REALLOCDUALVIEWIFNEEDED_HPP
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
bool reallocDualViewIfNeeded(Kokkos::DualView< ValueType *, DeviceType > &dv, const size_t newSize, const char newLabel[], const size_t tooBigFactor=2, const bool needFenceBeforeRealloc=true)
Reallocate the DualView in/out argument, if needed.