Viskores  1.0
ParallelSortTBB.h
Go to the documentation of this file.
1 //============================================================================
2 // The contents of this file are covered by the Viskores license. See
3 // LICENSE.txt for details.
4 //
5 // By contributing to this file, all contributors agree to the Developer
6 // Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
7 //============================================================================
8 
9 //============================================================================
10 // Copyright (c) Kitware, Inc.
11 // All rights reserved.
12 // See LICENSE.txt for details.
13 //
14 // This software is distributed WITHOUT ANY WARRANTY; without even
15 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 // PURPOSE. See the above copyright notice for more information.
17 //============================================================================
18 
19 #ifndef viskores_cont_tbb_internal_ParallelSort_h
20 #define viskores_cont_tbb_internal_ParallelSort_h
21 
26 
29 #include <viskores/cont/tbb/internal/ParallelSortTBB.hxx>
30 
31 #include <type_traits>
32 
33 namespace viskores
34 {
35 namespace cont
36 {
37 namespace tbb
38 {
39 namespace sort
40 {
41 
42 // Declare the compiled radix sort specializations:
44 
45 // Forward declare entry points (See stack overflow discussion 7255281 --
46 // templated overloads of template functions are not specialization, and will
47 // be resolved during the first phase of two part lookup).
48 template <typename T, typename Container, class BinaryCompare>
50 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
53  BinaryCompare);
54 
55 // Quicksort values:
56 template <typename HandleType, class BinaryCompare>
57 void parallel_sort(HandleType& values,
58  BinaryCompare binary_compare,
59  viskores::cont::internal::radix::PSortTag)
60 {
62  auto arrayPortal = values.PrepareForInPlace(viskores::cont::DeviceAdapterTagTBB(), token);
63 
64  using IteratorsType = viskores::cont::ArrayPortalToIterators<decltype(arrayPortal)>;
65  IteratorsType iterators(arrayPortal);
66 
67  internal::WrappedBinaryOperator<bool, BinaryCompare> wrappedCompare(binary_compare);
68  ::tbb::parallel_sort(iterators.GetBegin(), iterators.GetEnd(), wrappedCompare);
69 }
70 
71 // Radix sort values:
72 template <typename T, typename StorageT, class BinaryCompare>
74  BinaryCompare binary_compare,
75  viskores::cont::internal::radix::RadixSortTag)
76 {
77  using namespace viskores::cont::internal::radix;
78  auto c = get_std_compare(binary_compare, T{});
80  auto valuesPortal = values.PrepareForInPlace(viskores::cont::DeviceAdapterTagTBB{}, token);
82  valuesPortal.GetIteratorBegin(), static_cast<std::size_t>(values.GetNumberOfValues()), c);
83 }
84 
85 // Value sort -- static switch between quicksort and radix sort
86 template <typename T, typename Container, class BinaryCompare>
87 void parallel_sort(viskores::cont::ArrayHandle<T, Container>& values, BinaryCompare binary_compare)
88 {
89  using namespace viskores::cont::internal::radix;
90  using SortAlgorithmTag = typename sort_tag_type<T, Container, BinaryCompare>::type;
91  parallel_sort(values, binary_compare, SortAlgorithmTag{});
92 }
93 
94 
95 // Quicksort by key
96 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
99  BinaryCompare binary_compare,
100  viskores::cont::internal::radix::PSortTag)
101 {
102  using namespace viskores::cont::internal::radix;
104  constexpr bool larger_than_64bits = sizeof(U) > sizeof(viskores::Int64);
105  if (larger_than_64bits)
106  {
109 
113 
114  IndexType indexArray;
115  ValueType valuesScattered;
116  const viskores::Id size = values.GetNumberOfValues();
117 
118  {
119  viskores::cont::Token token;
120  auto handle = ArrayHandleIndex(keys.GetNumberOfValues());
121  auto inputPortal = handle.PrepareForInput(DeviceAdapterTagTBB(), token);
122  auto outputPortal =
123  indexArray.PrepareForOutput(keys.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
124  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, keys.GetNumberOfValues());
125  }
126 
127  ZipHandleType zipHandle = viskores::cont::make_ArrayHandleZip(keys, indexArray);
129  zipHandle,
130  viskores::cont::internal::KeyCompare<T, viskores::Id, BinaryCompare>(binary_compare),
131  PSortTag());
132 
133  {
134  viskores::cont::Token token;
135  tbb::ScatterPortal(
137  indexArray.PrepareForInput(viskores::cont::DeviceAdapterTagTBB(), token),
138  valuesScattered.PrepareForOutput(size, viskores::cont::DeviceAdapterTagTBB(), token));
139  }
140 
141  {
142  viskores::cont::Token token;
143  auto inputPortal = valuesScattered.PrepareForInput(DeviceAdapterTagTBB(), token);
144  auto outputPortal =
145  values.PrepareForOutput(valuesScattered.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
146  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, valuesScattered.GetNumberOfValues());
147  }
148  }
149  else
150  {
153 
154  ZipHandleType zipHandle = viskores::cont::make_ArrayHandleZip(keys, values);
155  parallel_sort(zipHandle,
156  viskores::cont::internal::KeyCompare<T, U, BinaryCompare>(binary_compare),
157  PSortTag{});
158  }
159 }
160 
161 // Radix sort by key -- Specialize for viskores::Id values:
162 template <typename T, typename StorageT, typename StorageU, class BinaryCompare>
165  BinaryCompare binary_compare,
166  viskores::cont::internal::radix::RadixSortTag)
167 {
168  using namespace viskores::cont::internal::radix;
169  auto c = get_std_compare(binary_compare, T{});
170  viskores::cont::Token token;
171  auto keysPortal = keys.PrepareForInPlace(viskores::cont::DeviceAdapterTagTBB{}, token);
172  auto valuesPortal = values.PrepareForInPlace(viskores::cont::DeviceAdapterTagTBB{}, token);
173  parallel_radix_sort_key_values(keysPortal.GetIteratorBegin(),
174  valuesPortal.GetIteratorBegin(),
175  static_cast<std::size_t>(keys.GetNumberOfValues()),
176  c);
177 }
178 
179 // Radix sort by key -- Generic impl:
180 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
183  BinaryCompare binary_compare,
184  viskores::cont::internal::radix::RadixSortTag)
185 {
190 
191  IndexType indexArray;
192  ValueType valuesScattered;
193  const viskores::Id size = values.GetNumberOfValues();
194 
195  {
196  viskores::cont::Token token;
197  auto handle = ArrayHandleIndex(keys.GetNumberOfValues());
198  auto inputPortal = handle.PrepareForInput(DeviceAdapterTagTBB(), token);
199  auto outputPortal =
200  indexArray.PrepareForOutput(keys.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
201  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, keys.GetNumberOfValues());
202  }
203 
204  if (static_cast<viskores::Id>(sizeof(T)) * keys.GetNumberOfValues() > 400000)
205  {
206  parallel_sort_bykey(keys, indexArray, binary_compare);
207  }
208  else
209  {
210  ZipHandleType zipHandle = viskores::cont::make_ArrayHandleZip(keys, indexArray);
212  zipHandle,
213  viskores::cont::internal::KeyCompare<T, viskores::Id, BinaryCompare>(binary_compare),
214  viskores::cont::internal::radix::PSortTag{});
215  }
216 
217  {
218  viskores::cont::Token token;
219  tbb::ScatterPortal(
221  indexArray.PrepareForInput(viskores::cont::DeviceAdapterTagTBB(), token),
222  valuesScattered.PrepareForOutput(size, viskores::cont::DeviceAdapterTagTBB(), token));
223  }
224 
225  {
226  viskores::cont::Token token;
227  auto inputPortal = valuesScattered.PrepareForInput(DeviceAdapterTagTBB(), token);
228  auto outputPortal =
229  values.PrepareForOutput(valuesScattered.GetNumberOfValues(), DeviceAdapterTagTBB(), token);
230  tbb::CopyPortals(inputPortal, outputPortal, 0, 0, valuesScattered.GetNumberOfValues());
231  }
232 }
233 
234 // Sort by key -- static switch between radix and quick sort:
235 template <typename T, typename StorageT, typename U, typename StorageU, class BinaryCompare>
238  BinaryCompare binary_compare)
239 {
240  using namespace viskores::cont::internal::radix;
241  using SortAlgorithmTag =
242  typename sortbykey_tag_type<T, U, StorageT, StorageU, BinaryCompare>::type;
243  parallel_sort_bykey(keys, values, binary_compare, SortAlgorithmTag{});
244 }
245 }
246 }
247 }
248 } // end namespace viskores::cont::tbb::sort
249 
250 #endif // viskores_cont_tbb_internal_ParallelSort_h
ArrayHandle.h
viskores::cont::ArrayHandle::PrepareForInput
ReadPortalType PrepareForInput(viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Prepares this array to be used as an input to an operation in the execution environment.
Definition: ArrayHandle.h:615
viskores::cont::make_ArrayHandleZip
viskores::cont::ArrayHandleZip< FirstHandleType, SecondHandleType > make_ArrayHandleZip(const FirstHandleType &first, const SecondHandleType &second)
A convenience function for creating an ArrayHandleZip.
Definition: ArrayHandleZip.h:300
viskores::cont::tbb::sort::parallel_sort
void parallel_sort(viskores::cont::ArrayHandle< T, StorageT > &values, BinaryCompare binary_compare, viskores::cont::internal::radix::RadixSortTag)
Definition: ParallelSortTBB.h:73
viskores::cont::tbb::sort::parallel_radix_sort
void parallel_radix_sort(short int *data, size_t num_elems, const std::greater< short int > &comp)
DeviceAdapterTagTBB.h
viskores::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:313
viskores::cont::tbb::sort::parallel_sort
void parallel_sort(viskores::cont::ArrayHandle< T, Container > &, BinaryCompare)
Definition: ParallelSortTBB.h:87
viskores::cont::ArrayHandleZip
ArrayHandleZip is a specialization of ArrayHandle.
Definition: ArrayHandleZip.h:263
ArrayHandleZip.h
viskores::Int64
signed long long Int64
Base type to use for 64-bit signed integer numbers.
Definition: Types.h:212
viskores::Id
viskores::Int64 Id
Base type to use to index arrays.
Definition: Types.h:235
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::cont::tbb::sort::parallel_radix_sort_key_values
VISKORES_CONT_EXPORT void parallel_radix_sort_key_values(short int *keys, viskores::Id *vals, size_t num_elems, const std::greater< short int > &comp)
viskores::cont::tbb::CopyPortals
void CopyPortals(const InputPortalType &inPortal, const OutputPortalType &outPortal, viskores::Id inOffset, viskores::Id outOffset, viskores::Id numValues)
Definition: FunctorsTBB.h:154
viskores::cont::ArrayHandle::PrepareForInPlace
WritePortalType PrepareForInPlace(viskores::cont::DeviceAdapterId device, viskores::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:634
FunctorsTBB.h
viskores::cont::tbb::sort::parallel_sort_bykey
void parallel_sort_bykey(viskores::cont::ArrayHandle< T, StorageT > &, viskores::cont::ArrayHandle< U, StorageU > &, BinaryCompare)
Definition: ParallelSortTBB.h:236
viskores::cont::ArrayHandle::GetNumberOfValues
viskores::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:482
viskores::cont::ArrayHandle::PrepareForOutput
WritePortalType PrepareForOutput(viskores::Id numberOfValues, viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Prepares (allocates) this array to be used as an output from an operation in the execution environmen...
Definition: ArrayHandle.h:654
viskores::cont::ArrayPortalToIterators
Definition: ArrayPortalToIterators.h:35
VISKORES_DECLARE_RADIX_SORT
#define VISKORES_DECLARE_RADIX_SORT()
Definition: ParallelRadixSortInterface.h:141
viskores::cont::DeviceAdapterTagTBB
Tag for a device adapter that uses the Intel Threading Building Blocks library to run algorithms on m...
Definition: DeviceAdapterTagTBB.h:37
BinaryPredicates.h
viskores::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:43
viskores::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:64
ParallelRadixSortInterface.h