VTK-m  2.2
ParallelSortTBB.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 
11 #ifndef vtk_m_cont_tbb_internal_ParallelSort_h
12 #define vtk_m_cont_tbb_internal_ParallelSort_h
13 
14 #include <vtkm/BinaryPredicates.h>
15 #include <vtkm/cont/ArrayHandle.h>
18 
21 #include <vtkm/cont/tbb/internal/ParallelSortTBB.hxx>
22 
23 #include <type_traits>
24 
25 namespace vtkm
26 {
27 namespace cont
28 {
29 namespace tbb
30 {
31 namespace sort
32 {
33 
34 // Declare the compiled radix sort specializations:
36 
37 // Forward declare entry points (See stack overflow discussion 7255281 --
38 // templated overloads of template functions are not specialization, and will
39 // be resolved during the first phase of two part lookup).
40 template <typename T, typename Container, class BinaryCompare>
42 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
45  BinaryCompare);
46 
47 // Quicksort values:
48 template <typename HandleType, class BinaryCompare>
49 void parallel_sort(HandleType& values,
50  BinaryCompare binary_compare,
51  vtkm::cont::internal::radix::PSortTag)
52 {
53  vtkm::cont::Token token;
54  auto arrayPortal = values.PrepareForInPlace(vtkm::cont::DeviceAdapterTagTBB(), token);
55 
56  using IteratorsType = vtkm::cont::ArrayPortalToIterators<decltype(arrayPortal)>;
57  IteratorsType iterators(arrayPortal);
58 
59  internal::WrappedBinaryOperator<bool, BinaryCompare> wrappedCompare(binary_compare);
60  ::tbb::parallel_sort(iterators.GetBegin(), iterators.GetEnd(), wrappedCompare);
61 }
62 
63 // Radix sort values:
64 template <typename T, typename StorageT, class BinaryCompare>
66  BinaryCompare binary_compare,
67  vtkm::cont::internal::radix::RadixSortTag)
68 {
69  using namespace vtkm::cont::internal::radix;
70  auto c = get_std_compare(binary_compare, T{});
71  vtkm::cont::Token token;
72  auto valuesPortal = values.PrepareForInPlace(vtkm::cont::DeviceAdapterTagTBB{}, token);
74  valuesPortal.GetIteratorBegin(), static_cast<std::size_t>(values.GetNumberOfValues()), c);
75 }
76 
77 // Value sort -- static switch between quicksort and radix sort
78 template <typename T, typename Container, class BinaryCompare>
79 void parallel_sort(vtkm::cont::ArrayHandle<T, Container>& values, BinaryCompare binary_compare)
80 {
81  using namespace vtkm::cont::internal::radix;
82  using SortAlgorithmTag = typename sort_tag_type<T, Container, BinaryCompare>::type;
83  parallel_sort(values, binary_compare, SortAlgorithmTag{});
84 }
85 
86 
87 // Quicksort by key
88 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
91  BinaryCompare binary_compare,
92  vtkm::cont::internal::radix::PSortTag)
93 {
94  using namespace vtkm::cont::internal::radix;
96  constexpr bool larger_than_64bits = sizeof(U) > sizeof(vtkm::Int64);
97  if (larger_than_64bits)
98  {
101 
102  using ValueType = vtkm::cont::ArrayHandle<U, StorageU>;
103  using IndexType = vtkm::cont::ArrayHandle<vtkm::Id>;
105 
106  IndexType indexArray;
107  ValueType valuesScattered;
108  const vtkm::Id size = values.GetNumberOfValues();
109 
110  {
111  vtkm::cont::Token token;
112  auto handle = ArrayHandleIndex(keys.GetNumberOfValues());
113  auto inputPortal = handle.PrepareForInput(DeviceAdapterTagTBB(), token);
114  auto outputPortal =
115  indexArray.PrepareForOutput(keys.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
116  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, keys.GetNumberOfValues());
117  }
118 
119  ZipHandleType zipHandle = vtkm::cont::make_ArrayHandleZip(keys, indexArray);
120  parallel_sort(zipHandle,
121  vtkm::cont::internal::KeyCompare<T, vtkm::Id, BinaryCompare>(binary_compare),
122  PSortTag());
123 
124  {
125  vtkm::cont::Token token;
126  tbb::ScatterPortal(
128  indexArray.PrepareForInput(vtkm::cont::DeviceAdapterTagTBB(), token),
129  valuesScattered.PrepareForOutput(size, vtkm::cont::DeviceAdapterTagTBB(), token));
130  }
131 
132  {
133  vtkm::cont::Token token;
134  auto inputPortal = valuesScattered.PrepareForInput(DeviceAdapterTagTBB(), token);
135  auto outputPortal =
136  values.PrepareForOutput(valuesScattered.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
137  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, valuesScattered.GetNumberOfValues());
138  }
139  }
140  else
141  {
142  using ValueType = vtkm::cont::ArrayHandle<U, StorageU>;
144 
145  ZipHandleType zipHandle = vtkm::cont::make_ArrayHandleZip(keys, values);
147  zipHandle, vtkm::cont::internal::KeyCompare<T, U, BinaryCompare>(binary_compare), PSortTag{});
148  }
149 }
150 
151 // Radix sort by key -- Specialize for vtkm::Id values:
152 template <typename T, typename StorageT, typename StorageU, class BinaryCompare>
155  BinaryCompare binary_compare,
156  vtkm::cont::internal::radix::RadixSortTag)
157 {
158  using namespace vtkm::cont::internal::radix;
159  auto c = get_std_compare(binary_compare, T{});
160  vtkm::cont::Token token;
161  auto keysPortal = keys.PrepareForInPlace(vtkm::cont::DeviceAdapterTagTBB{}, token);
162  auto valuesPortal = values.PrepareForInPlace(vtkm::cont::DeviceAdapterTagTBB{}, token);
163  parallel_radix_sort_key_values(keysPortal.GetIteratorBegin(),
164  valuesPortal.GetIteratorBegin(),
165  static_cast<std::size_t>(keys.GetNumberOfValues()),
166  c);
167 }
168 
169 // Radix sort by key -- Generic impl:
170 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
173  BinaryCompare binary_compare,
174  vtkm::cont::internal::radix::RadixSortTag)
175 {
180 
181  IndexType indexArray;
182  ValueType valuesScattered;
183  const vtkm::Id size = values.GetNumberOfValues();
184 
185  {
186  vtkm::cont::Token token;
187  auto handle = ArrayHandleIndex(keys.GetNumberOfValues());
188  auto inputPortal = handle.PrepareForInput(DeviceAdapterTagTBB(), token);
189  auto outputPortal =
190  indexArray.PrepareForOutput(keys.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
191  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, keys.GetNumberOfValues());
192  }
193 
194  if (static_cast<vtkm::Id>(sizeof(T)) * keys.GetNumberOfValues() > 400000)
195  {
196  parallel_sort_bykey(keys, indexArray, binary_compare);
197  }
198  else
199  {
200  ZipHandleType zipHandle = vtkm::cont::make_ArrayHandleZip(keys, indexArray);
201  parallel_sort(zipHandle,
202  vtkm::cont::internal::KeyCompare<T, vtkm::Id, BinaryCompare>(binary_compare),
203  vtkm::cont::internal::radix::PSortTag{});
204  }
205 
206  {
207  vtkm::cont::Token token;
208  tbb::ScatterPortal(
210  indexArray.PrepareForInput(vtkm::cont::DeviceAdapterTagTBB(), token),
211  valuesScattered.PrepareForOutput(size, vtkm::cont::DeviceAdapterTagTBB(), token));
212  }
213 
214  {
215  vtkm::cont::Token token;
216  auto inputPortal = valuesScattered.PrepareForInput(DeviceAdapterTagTBB(), token);
217  auto outputPortal =
218  values.PrepareForOutput(valuesScattered.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
219  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, valuesScattered.GetNumberOfValues());
220  }
221 }
222 
223 // Sort by key -- static switch between radix and quick sort:
224 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
227  BinaryCompare binary_compare)
228 {
229  using namespace vtkm::cont::internal::radix;
230  using SortAlgorithmTag =
231  typename sortbykey_tag_type<T, U, StorageT, StorageU, BinaryCompare>::type;
232  parallel_sort_bykey(keys, values, binary_compare, SortAlgorithmTag{});
233 }
234 }
235 }
236 }
237 } // end namespace vtkm::cont::tbb::sort
238 
239 #endif // vtk_m_cont_tbb_internal_ParallelSort_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
ArrayHandle.h
vtkm::cont::tbb::sort::parallel_radix_sort
void parallel_radix_sort(short int *data, size_t num_elems, const std::greater< short int > &comp)
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
DeviceAdapterTagTBB.h
vtkm::cont::ArrayHandle::GetNumberOfValues
vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:468
ArrayHandleZip.h
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
vtkm::cont::make_ArrayHandleZip
vtkm::cont::ArrayHandleZip< FirstHandleType, SecondHandleType > make_ArrayHandleZip(const FirstHandleType &first, const SecondHandleType &second)
A convenience function for creating an ArrayHandleZip.
Definition: ArrayHandleZip.h:290
vtkm::cont::ArrayHandle::PrepareForInPlace
WritePortalType PrepareForInPlace(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares this array to be used in an in-place operation (both as input and output) in the execution e...
Definition: ArrayHandle.h:618
vtkm::cont::ArrayPortalToIterators
Definition: ArrayPortalToIterators.h:27
vtkm::cont::ArrayHandleZip
ArrayHandleZip is a specialization of ArrayHandle.
Definition: ArrayHandleZip.h:253
vtkm::cont::tbb::sort::parallel_sort_bykey
void parallel_sort_bykey(vtkm::cont::ArrayHandle< T, StorageT > &, vtkm::cont::ArrayHandle< U, StorageU > &, BinaryCompare)
Definition: ParallelSortTBB.h:225
FunctorsTBB.h
vtkm::cont::ArrayHandle::PrepareForOutput
WritePortalType PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares (allocates) this array to be used as an output from an operation in the execution environmen...
Definition: ArrayHandle.h:638
vtkm::cont::DeviceAdapterTagTBB
Tag for a device adapter that uses the Intel Threading Building Blocks library to run algorithms on m...
Definition: DeviceAdapterTagTBB.h:27
vtkm::Id
vtkm::Int64 Id
Base type to use to index arrays.
Definition: Types.h:227
vtkm::Int64
signed long long Int64
Base type to use for 64-bit signed integer numbers.
Definition: Types.h:204
vtkm::cont::tbb::sort::parallel_sort
void parallel_sort(vtkm::cont::ArrayHandle< T, StorageT > &values, BinaryCompare binary_compare, vtkm::cont::internal::radix::RadixSortTag)
Definition: ParallelSortTBB.h:65
vtkm::cont::tbb::sort::parallel_radix_sort_key_values
VTKM_CONT_EXPORT void parallel_radix_sort_key_values(short int *keys, vtkm::Id *vals, size_t num_elems, const std::greater< short int > &comp)
VTKM_DECLARE_RADIX_SORT
#define VTKM_DECLARE_RADIX_SORT()
Definition: ParallelRadixSortInterface.h:133
BinaryPredicates.h
vtkm::cont::ArrayHandle::PrepareForInput
ReadPortalType PrepareForInput(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares this array to be used as an input to an operation in the execution environment.
Definition: ArrayHandle.h:599
vtkm::cont::tbb::sort::parallel_sort
void parallel_sort(vtkm::cont::ArrayHandle< T, Container > &, BinaryCompare)
Definition: ParallelSortTBB.h:79
vtkm::cont::tbb::CopyPortals
void CopyPortals(const InputPortalType &inPortal, const OutputPortalType &outPortal, vtkm::Id inOffset, vtkm::Id outOffset, vtkm::Id numValues)
Definition: FunctorsTBB.h:146
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:55
ParallelRadixSortInterface.h