Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tpetra_Details_computeOffsets.hpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Tpetra: Templated Linear Algebra Services Package
6 // Copyright (2008) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // ************************************************************************
39 // @HEADER
40 */
41 
42 #ifndef TPETRA_DETAILS_COMPUTEOFFSETS_HPP
43 #define TPETRA_DETAILS_COMPUTEOFFSETS_HPP
44 
51 
52 #include "TpetraCore_config.h"
54 #include <limits>
55 #include <type_traits>
56 
57 namespace Tpetra {
58 namespace Details {
59 
60 //
61 // Implementation details for computeOffsetsFromCounts (see below).
62 // Users should skip over this anonymous namespace.
63 //
64 namespace { // (anonymous)
65 
75 template<class OffsetType,
76  class CountType,
77  class SizeType>
78 class ComputeOffsetsFromCounts {
79 public:
80  static_assert (std::is_integral<OffsetType>::value,
81  "OffsetType must be a built-in integer.");
82  static_assert (std::is_integral<CountType>::value,
83  "CountType must be a built-in integer.");
84  static_assert (std::is_integral<SizeType>::value,
85  "SizeType must be a built-in integer.");
86 
87  using offsets_view_type =
88  Kokkos::View<OffsetType*, Kokkos::AnonymousSpace>;
89  using counts_view_type =
90  Kokkos::View<const CountType*, Kokkos::AnonymousSpace>;
91 
97  ComputeOffsetsFromCounts (const offsets_view_type& offsets,
98  const counts_view_type& counts) :
99  offsets_ (offsets),
100  counts_ (counts),
101  size_ (counts.extent (0))
102  {}
103 
105  KOKKOS_INLINE_FUNCTION void
106  operator () (const SizeType i, OffsetType& update,
107  const bool finalPass) const
108  {
109  const auto curVal = (i < size_) ? counts_[i] : OffsetType ();
110  if (finalPass) {
111  offsets_[i] = update;
112  }
113  update += (i < size_) ? curVal : OffsetType ();
114  }
115 
116  template<class ExecutionSpace>
117  static OffsetType
118  run (const ExecutionSpace& execSpace,
119  const offsets_view_type& offsets,
120  const counts_view_type& counts)
121  {
122  const SizeType numCounts (counts.extent (0));
123  using range_type = Kokkos::RangePolicy<ExecutionSpace, SizeType>;
124  range_type range (execSpace, 0, numCounts + SizeType (1));
125  using functor_type =
126  ComputeOffsetsFromCounts<OffsetType, CountType, SizeType>;
127  functor_type functor (offsets, counts);
128  OffsetType total (0);
129  const char funcName[] = "Tpetra::Details::computeOffsetsFromCounts";
130  Kokkos::parallel_scan (range, functor, total, funcName);
131  return total;
132  }
133 
134 private:
136  offsets_view_type offsets_;
138  counts_view_type counts_;
140  SizeType size_;
141 };
142 
152 template<class OffsetType,
153  class CountType,
154  class SizeType>
155 class ComputeOffsetsFromConstantCount {
156 public:
157  static_assert (std::is_integral<OffsetType>::value,
158  "OffsetType must be a built-in integer.");
159  static_assert (std::is_integral<CountType>::value,
160  "CountType must be a built-in integer.");
161  static_assert (std::is_integral<SizeType>::value,
162  "SizeType must be a built-in integer.");
163 
164  using offsets_view_type =
165  Kokkos::View<OffsetType*, Kokkos::AnonymousSpace>;
166 
172  ComputeOffsetsFromConstantCount (const offsets_view_type& offsets,
173  const CountType count) :
174  offsets_ (offsets),
175  count_ (count)
176  {}
177 
179  KOKKOS_INLINE_FUNCTION void
180  operator () (const SizeType i) const
181  {
182  offsets_[i] = count_*i;
183  }
184 
185  template<class ExecutionSpace>
186  static OffsetType
187  run (const ExecutionSpace& execSpace,
188  const offsets_view_type& offsets,
189  const CountType count)
190  {
191  const SizeType numOffsets (offsets.extent (0));
192  using range_type = Kokkos::RangePolicy<ExecutionSpace, SizeType>;
193  range_type range (execSpace, 0, numOffsets);
194  using functor_type =
195  ComputeOffsetsFromConstantCount<OffsetType, CountType, SizeType>;
196  functor_type functor (offsets, count);
197  const OffsetType total = numOffsets*count;
198  const char funcName[] =
199  "Tpetra::Details::computeOffsetsFromConstantCount";
200  Kokkos::parallel_for (range, functor, funcName);
201  return total;
202  }
203 
204 private:
206  offsets_view_type offsets_;
208  CountType count_;
209 };
210 
211 } // namespace (anonymous)
212 
238 template<class ExecutionSpace,
239  class OffsetsViewType,
240  class CountsViewType,
241  class SizeType = typename OffsetsViewType::size_type>
242 typename OffsetsViewType::non_const_value_type
243 computeOffsetsFromCounts (const ExecutionSpace& execSpace,
244  const OffsetsViewType& ptr,
245  const CountsViewType& counts)
246 {
247  static_assert (Kokkos::is_execution_space<ExecutionSpace>::value,
248  "ExecutionSpace must be a Kokkos execution space.");
249  static_assert (Kokkos::Impl::is_view<OffsetsViewType>::value,
250  "OffsetsViewType (the type of ptr) must be a Kokkos::View.");
251  static_assert (Kokkos::Impl::is_view<CountsViewType>::value,
252  "CountsViewType (the type of counts) must be a Kokkos::View.");
253  static_assert (std::is_same<typename OffsetsViewType::value_type,
254  typename OffsetsViewType::non_const_value_type>::value,
255  "OffsetsViewType (the type of ptr) must be a nonconst Kokkos::View.");
256  static_assert (static_cast<int> (OffsetsViewType::rank) == 1,
257  "OffsetsViewType (the type of ptr) must be a rank-1 Kokkos::View.");
258  static_assert (static_cast<int> (CountsViewType::rank) == 1,
259  "CountsViewType (the type of counts) must be a rank-1 Kokkos::View.");
260 
261  using offset_type = typename OffsetsViewType::non_const_value_type;
262  static_assert (std::is_integral<offset_type>::value,
263  "The entries of ptr must be built-in integers.");
264  using count_type = typename CountsViewType::non_const_value_type;
265  static_assert (std::is_integral<count_type>::value,
266  "The entries of counts must be built-in integers.");
267  static_assert (std::is_integral<SizeType>::value,
268  "SizeType must be a built-in integer type.");
269 
270  const char funcName[] = "Tpetra::Details::computeOffsetsFromCounts";
271 
272  const auto numOffsets = ptr.size ();
273  const auto numCounts = counts.size ();
274  offset_type total (0);
275 
276  if (numOffsets != 0) {
277  TEUCHOS_TEST_FOR_EXCEPTION
278  (numCounts >= numOffsets, std::invalid_argument, funcName <<
279  ": counts.size() = " << numCounts << " >= ptr.size() = " <<
280  numOffsets << ".");
281 
282  using Kokkos::AnonymousSpace;
283  using Kokkos::View;
284  View<offset_type*, AnonymousSpace> ptr_a = ptr;
285  View<const count_type*, AnonymousSpace> counts_a;
286 
287  using offsets_device_type = typename OffsetsViewType::device_type;
288  using counts_copy_type = View<count_type*, offsets_device_type>;
289  counts_copy_type counts_copy;
290 
291  using offsets_memory_space =
292  typename offsets_device_type::memory_space;
293  using counts_memory_space = typename CountsViewType::memory_space;
294  constexpr bool countsAccessibleFromOffsetsExecSpace =
295  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<
296  offsets_memory_space, counts_memory_space>::value;
297  if (countsAccessibleFromOffsetsExecSpace) {
298  // NOTE (mfh 21 Aug 2019) Some compilers have trouble deducing
299  // that operator= works if more than one template argument
300  // differ. If that should happen, introduce an intermediate
301  // type here.
302  counts_a = counts;
303  }
304  else {
305  using Kokkos::view_alloc;
306  using Kokkos::WithoutInitializing;
307  counts_copy = counts_copy_type
308  (view_alloc ("counts_copy", WithoutInitializing), numCounts);
309  Kokkos::deep_copy (counts_copy, counts);
310  counts_a = counts_copy;
311  }
312 
313  using functor_type =
314  ComputeOffsetsFromCounts<offset_type, count_type, SizeType>;
315  total = functor_type::run (execSpace, ptr_a, counts_a);
316  }
317 
318  return total;
319 }
320 
322 template<class OffsetsViewType,
323  class CountsViewType,
324  class SizeType = typename OffsetsViewType::size_type>
325 typename OffsetsViewType::non_const_value_type
326 computeOffsetsFromCounts (const OffsetsViewType& ptr,
327  const CountsViewType& counts)
328 {
329  using execution_space = typename OffsetsViewType::execution_space;
330  return computeOffsetsFromCounts (execution_space (), ptr, counts);
331 }
332 
355 template<class OffsetsViewType,
356  class CountType,
357  class SizeType = typename OffsetsViewType::size_type>
358 typename OffsetsViewType::non_const_value_type
359 computeOffsetsFromConstantCount (const OffsetsViewType& ptr,
360  const CountType count)
361 {
362  static_assert (Kokkos::Impl::is_view<OffsetsViewType>::value,
363  "ptr must be a Kokkos::View.");
364  static_assert (std::is_same<typename OffsetsViewType::value_type,
365  typename OffsetsViewType::non_const_value_type>::value,
366  "ptr must be a nonconst Kokkos::View.");
367  static_assert (static_cast<int> (OffsetsViewType::rank) == 1,
368  "ptr must be a rank-1 Kokkos::View.");
369 
370  using offset_type = typename OffsetsViewType::non_const_value_type;
371  static_assert (std::is_integral<offset_type>::value,
372  "The type of each entry of ptr must be a "
373  "built-in integer.");
374  static_assert (std::is_integral<CountType>::value,
375  "CountType must be a built-in integer.");
376  static_assert (std::is_integral<SizeType>::value,
377  "SizeType must be a built-in integer.");
378 
379  using device_type = typename OffsetsViewType::device_type;
380  using execution_space = typename device_type::execution_space;
381 
382  offset_type total (0);
383  if (ptr.extent (0) != 0) {
384  using CT = CountType;
385  using functor_type =
386  ComputeOffsetsFromConstantCount<offset_type, CT, SizeType>;
387  execution_space execSpace;
388  functor_type::run (execSpace, ptr, count);
389  }
390  return total;
391 }
392 
393 } // namespace Details
394 } // namespace Tpetra
395 
396 #endif // TPETRA_DETAILS_COMPUTEOFFSETS_HPP
counts_view_type counts_
Bucket counts (input argument).
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
offsets_view_type offsets_
Offsets (output argument)
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
CountType count_
&quot;Count&quot; input argument
SizeType size_
Number of entries in counts_.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
Declaration and definition of Tpetra::Details::getEntryOnHost.