Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends 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 (funcName, range, functor, total);
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  if(numOffsets == SizeType(0))
193  {
194  // Special case that is possible with zero rows
195  return 0;
196  }
197  using range_type = Kokkos::RangePolicy<ExecutionSpace, SizeType>;
198  range_type range (execSpace, 0, numOffsets);
199  using functor_type =
200  ComputeOffsetsFromConstantCount<OffsetType, CountType, SizeType>;
201  functor_type functor (offsets, count);
202  const OffsetType total = (numOffsets - 1) * count;
203  const char funcName[] =
204  "Tpetra::Details::computeOffsetsFromConstantCount";
205  Kokkos::parallel_for (funcName, range, functor);
206  return total;
207  }
208 
209 private:
211  offsets_view_type offsets_;
213  CountType count_;
214 };
215 
216 } // namespace (anonymous)
217 
243 template<class ExecutionSpace,
244  class OffsetsViewType,
245  class CountsViewType,
246  class SizeType = typename OffsetsViewType::size_type>
247 typename OffsetsViewType::non_const_value_type
248 computeOffsetsFromCounts (const ExecutionSpace& execSpace,
249  const OffsetsViewType& ptr,
250  const CountsViewType& counts)
251 {
252  static_assert (Kokkos::is_execution_space<ExecutionSpace>::value,
253  "ExecutionSpace must be a Kokkos execution space.");
254  static_assert (Kokkos::is_view<OffsetsViewType>::value,
255  "OffsetsViewType (the type of ptr) must be a Kokkos::View.");
256  static_assert (Kokkos::is_view<CountsViewType>::value,
257  "CountsViewType (the type of counts) must be a Kokkos::View.");
258  static_assert (std::is_same<typename OffsetsViewType::value_type,
259  typename OffsetsViewType::non_const_value_type>::value,
260  "OffsetsViewType (the type of ptr) must be a nonconst Kokkos::View.");
261  static_assert (static_cast<int> (OffsetsViewType::rank) == 1,
262  "OffsetsViewType (the type of ptr) must be a rank-1 Kokkos::View.");
263  static_assert (static_cast<int> (CountsViewType::rank) == 1,
264  "CountsViewType (the type of counts) must be a rank-1 Kokkos::View.");
265 
266  using offset_type = typename OffsetsViewType::non_const_value_type;
267  static_assert (std::is_integral<offset_type>::value,
268  "The entries of ptr must be built-in integers.");
269  using count_type = typename CountsViewType::non_const_value_type;
270  static_assert (std::is_integral<count_type>::value,
271  "The entries of counts must be built-in integers.");
272  static_assert (std::is_integral<SizeType>::value,
273  "SizeType must be a built-in integer type.");
274 
275  const char funcName[] = "Tpetra::Details::computeOffsetsFromCounts";
276 
277  const auto numOffsets = ptr.size ();
278  const auto numCounts = counts.size ();
279  offset_type total (0);
280 
281  if (numOffsets != 0) {
282  TEUCHOS_TEST_FOR_EXCEPTION
283  (numCounts >= numOffsets, std::invalid_argument, funcName <<
284  ": counts.size() = " << numCounts << " >= ptr.size() = " <<
285  numOffsets << ".");
286 
287  using Kokkos::AnonymousSpace;
288  using Kokkos::View;
289  View<offset_type*, AnonymousSpace> ptr_a = ptr;
290  View<const count_type*, AnonymousSpace> counts_a;
291 
292  using offsets_device_type = typename OffsetsViewType::device_type;
293  using counts_copy_type = View<count_type*, offsets_device_type>;
294  counts_copy_type counts_copy;
295 
296  using offsets_memory_space =
297  typename offsets_device_type::memory_space;
298  using counts_memory_space = typename CountsViewType::memory_space;
299  constexpr bool countsAccessibleFromOffsetsExecSpace =
300  Kokkos::SpaceAccessibility<
301  offsets_memory_space, counts_memory_space>::accessible;
302  if (countsAccessibleFromOffsetsExecSpace) {
303  // NOTE (mfh 21 Aug 2019) Some compilers have trouble deducing
304  // that operator= works if more than one template argument
305  // differ. If that should happen, introduce an intermediate
306  // type here.
307  counts_a = counts;
308  }
309  else {
310  using Kokkos::view_alloc;
311  using Kokkos::WithoutInitializing;
312  counts_copy = counts_copy_type
313  (view_alloc ("counts_copy", WithoutInitializing), numCounts);
314  Kokkos::deep_copy (execSpace, counts_copy, counts);
315  counts_a = counts_copy;
316  }
317 
318  using functor_type =
319  ComputeOffsetsFromCounts<offset_type, count_type, SizeType>;
320  total = functor_type::run (execSpace, ptr_a, counts_a);
321  }
322 
323  return total;
324 }
325 
327 template<class OffsetsViewType,
328  class CountsViewType,
329  class SizeType = typename OffsetsViewType::size_type>
330 typename OffsetsViewType::non_const_value_type
331 computeOffsetsFromCounts (const OffsetsViewType& ptr,
332  const CountsViewType& counts)
333 {
334  using execution_space = typename OffsetsViewType::execution_space;
335  return computeOffsetsFromCounts (execution_space (), ptr, counts);
336 }
337 
360 template<class OffsetsViewType,
361  class CountType,
362  class SizeType = typename OffsetsViewType::size_type>
363 typename OffsetsViewType::non_const_value_type
364 computeOffsetsFromConstantCount (const OffsetsViewType& ptr,
365  const CountType count)
366 {
367  static_assert (Kokkos::is_view<OffsetsViewType>::value,
368  "ptr must be a Kokkos::View.");
369  static_assert (std::is_same<typename OffsetsViewType::value_type,
370  typename OffsetsViewType::non_const_value_type>::value,
371  "ptr must be a nonconst Kokkos::View.");
372  static_assert (static_cast<int> (OffsetsViewType::rank) == 1,
373  "ptr must be a rank-1 Kokkos::View.");
374 
375  using offset_type = typename OffsetsViewType::non_const_value_type;
376  static_assert (std::is_integral<offset_type>::value,
377  "The type of each entry of ptr must be a "
378  "built-in integer.");
379  static_assert (std::is_integral<CountType>::value,
380  "CountType must be a built-in integer.");
381  static_assert (std::is_integral<SizeType>::value,
382  "SizeType must be a built-in integer.");
383 
384  using device_type = typename OffsetsViewType::device_type;
385  using execution_space = typename device_type::execution_space;
386 
387  offset_type total (0);
388  if (ptr.extent (0) != 0) {
389  using CT = CountType;
390  using functor_type =
391  ComputeOffsetsFromConstantCount<offset_type, CT, SizeType>;
392  execution_space execSpace;
393  total = functor_type::run (execSpace, ptr, count);
394  }
395  return total;
396 }
397 
398 } // namespace Details
399 } // namespace Tpetra
400 
401 #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.