VTK-m  2.0
Keys.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 #ifndef vtk_m_worklet_Keys_h
11 #define vtk_m_worklet_Keys_h
12 
13 #include <vtkm/cont/Algorithm.h>
14 #include <vtkm/cont/ArrayHandle.h>
20 #include <vtkm/cont/Logging.h>
21 
22 #include <vtkm/Hash.h>
23 
25 
31 
33 
35 #include <vtkm/worklet/vtkm_worklet_export.h>
36 
37 #include <vtkm/BinaryOperators.h>
38 
39 namespace vtkm
40 {
41 namespace worklet
42 {
43 
44 namespace internal
45 {
46 
47 class VTKM_WORKLET_EXPORT KeysBase
48 {
49 public:
50  KeysBase(const KeysBase&) = default;
51  KeysBase& operator=(const KeysBase&) = default;
52  ~KeysBase() = default;
53 
54  VTKM_CONT
55  vtkm::Id GetInputRange() const { return this->Counts.GetNumberOfValues(); }
56 
57  VTKM_CONT
58  vtkm::cont::ArrayHandle<vtkm::Id> GetSortedValuesMap() const { return this->SortedValuesMap; }
59 
60  VTKM_CONT
61  vtkm::cont::ArrayHandle<vtkm::Id> GetOffsets() const { return this->Offsets; }
62 
63  VTKM_CONT
64  vtkm::cont::ArrayHandle<vtkm::IdComponent> GetCounts() const { return this->Counts; }
65 
66  VTKM_CONT
67  vtkm::Id GetNumberOfValues() const { return this->SortedValuesMap.GetNumberOfValues(); }
68 
69  using ExecLookup = vtkm::exec::internal::ReduceByKeyLookupBase<
72 
73  VTKM_CONT ExecLookup PrepareForInput(vtkm::cont::DeviceAdapterId device,
74  vtkm::cont::Token& token) const
75  {
76  return ExecLookup(this->SortedValuesMap.PrepareForInput(device, token),
77  this->Offsets.PrepareForInput(device, token),
78  this->Counts.PrepareForInput(device, token));
79  }
80 
81  VTKM_CONT
82  bool operator==(const vtkm::worklet::internal::KeysBase& other) const
83  {
84  return ((this->SortedValuesMap == other.SortedValuesMap) && (this->Offsets == other.Offsets) &&
85  (this->Counts == other.Counts));
86  }
87 
88  VTKM_CONT
89  bool operator!=(const vtkm::worklet::internal::KeysBase& other) const
90  {
91  return !(*this == other);
92  }
93 
94 protected:
95  KeysBase() = default;
96 
97  vtkm::cont::ArrayHandle<vtkm::Id> SortedValuesMap;
100 };
101 
102 } // namespace internal
103 
107 enum class KeysSortType
108 {
109  Unstable = 0,
110  Stable = 1
111 };
112 
130 template <typename T>
131 class VTKM_ALWAYS_EXPORT Keys : public internal::KeysBase
132 {
133 public:
134  using KeyType = T;
136 
137  VTKM_CONT
138  Keys();
139 
149  template <typename KeyStorage>
151  vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
152  {
153  this->BuildArrays(keys, KeysSortType::Unstable, device);
154  }
155 
159  template <typename KeyArrayType>
160  VTKM_CONT void BuildArrays(
161  const KeyArrayType& keys,
162  KeysSortType sort,
163  vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny());
164 
168  template <typename KeyArrayType>
169  VTKM_CONT void BuildArraysInPlace(
170  KeyArrayType& keys,
171  KeysSortType sort,
172  vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny());
173 
174  VTKM_CONT
175  KeyArrayHandleType GetUniqueKeys() const { return this->UniqueKeys; }
176 
177  using ExecLookup = vtkm::exec::internal::ReduceByKeyLookup<
178  typename KeyArrayHandleType::ReadPortalType,
181 
183  vtkm::cont::Token& token) const
184  {
185  return ExecLookup(this->UniqueKeys.PrepareForInput(device, token),
186  this->SortedValuesMap.PrepareForInput(device, token),
187  this->Offsets.PrepareForInput(device, token),
188  this->Counts.PrepareForInput(device, token));
189  }
190 
191  VTKM_CONT
192  bool operator==(const vtkm::worklet::Keys<KeyType>& other) const
193  {
194  return ((this->UniqueKeys == other.UniqueKeys) &&
195  (this->SortedValuesMap == other.SortedValuesMap) && (this->Offsets == other.Offsets) &&
196  (this->Counts == other.Counts));
197  }
198 
199  VTKM_CONT
200  bool operator!=(const vtkm::worklet::Keys<KeyType>& other) const { return !(*this == other); }
201 
202 private:
204  KeyArrayHandleType UniqueKeys;
205 
206  template <typename KeyArrayType>
207  VTKM_CONT void BuildArraysInternal(KeyArrayType& keys, vtkm::cont::DeviceAdapterId device);
208 
209  template <typename KeyArrayType>
210  VTKM_CONT void BuildArraysInternalStable(const KeyArrayType& keys,
213 };
214 
215 template <typename T>
216 VTKM_CONT Keys<T>::Keys() = default;
217 
218 namespace internal
219 {
220 
221 template <typename KeyType>
222 inline auto SchedulingRange(const vtkm::worklet::Keys<KeyType>& inputDomain)
223  -> decltype(inputDomain.GetInputRange())
224 {
225  return inputDomain.GetInputRange();
226 }
227 
228 template <typename KeyType>
229 inline auto SchedulingRange(const vtkm::worklet::Keys<KeyType>* const inputDomain)
230  -> decltype(inputDomain->GetInputRange())
231 {
232  return inputDomain->GetInputRange();
233 }
234 
235 inline auto SchedulingRange(const vtkm::worklet::internal::KeysBase& inputDomain)
236  -> decltype(inputDomain.GetInputRange())
237 {
238  return inputDomain.GetInputRange();
239 }
240 
241 inline auto SchedulingRange(const vtkm::worklet::internal::KeysBase* const inputDomain)
242  -> decltype(inputDomain->GetInputRange())
243 {
244  return inputDomain->GetInputRange();
245 }
246 } // namespace internal
247 }
248 } // namespace vtkm::worklet
249 
250 // Here we implement the type checks and transports that rely on the Keys
251 // class. We implement them here because the Keys class is not accessible to
252 // the arg classes. (The worklet package depends on the cont and exec packages,
253 // not the other way around.)
254 
255 namespace vtkm
256 {
257 namespace cont
258 {
259 namespace arg
260 {
261 
262 template <typename KeyType>
264 {
265  static constexpr bool value =
266  std::is_base_of<vtkm::worklet::internal::KeysBase, typename std::decay<KeyType>::type>::value;
267 };
268 
269 template <typename KeyType, typename Device>
271 {
272  using ContObjectType = KeyType;
273  using ExecObjectType = typename ContObjectType::ExecLookup;
274 
275  VTKM_CONT
277  const ContObjectType& inputDomain,
278  vtkm::Id,
279  vtkm::Id,
280  vtkm::cont::Token& token) const
281  {
282  if (object != inputDomain)
283  {
284  throw vtkm::cont::ErrorBadValue("A Keys object must be the input domain.");
285  }
286 
287  return object.PrepareForInput(Device(), token);
288  }
289 
290  // If you get a compile error here, it means that you have used a KeysIn
291  // tag in your ControlSignature that was not marked as the InputDomain.
292  template <typename InputDomainType>
294  operator()(const ContObjectType&, const InputDomainType&, vtkm::Id, vtkm::Id) const = delete;
295 };
296 
297 template <typename ArrayHandleType, typename Device>
298 struct Transport<vtkm::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device>
299 {
300  VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
301 
302  using ContObjectType = ArrayHandleType;
303 
307 
309 
311  const vtkm::worklet::internal::KeysBase& keys,
312  vtkm::Id,
313  vtkm::Id,
314  vtkm::cont::Token& token) const
315  {
316  if (object.GetNumberOfValues() != keys.GetNumberOfValues())
317  {
318  throw vtkm::cont::ErrorBadValue("Input values array is wrong size.");
319  }
320 
321  PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
322  GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
323  // There is a bit of an issue here where groupedArray goes out of scope,
324  // and array portals usually rely on the associated array handle
325  // maintaining the resources it points to. However, the entire state of the
326  // portal should be self contained except for the data managed by the
327  // object argument, which should stay in scope.
328  return groupedArray.PrepareForInput(Device(), token);
329  }
330 };
331 
332 template <typename ArrayHandleType, typename Device>
333 struct Transport<vtkm::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device>
334 {
335  VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
336 
337  using ContObjectType = ArrayHandleType;
338 
342 
344 
346  const vtkm::worklet::internal::KeysBase& keys,
347  vtkm::Id,
348  vtkm::Id,
349  vtkm::cont::Token& token) const
350  {
351  if (object.GetNumberOfValues() != keys.GetNumberOfValues())
352  {
353  throw vtkm::cont::ErrorBadValue("Input/output values array is wrong size.");
354  }
355 
356  PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
357  GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
358  // There is a bit of an issue here where groupedArray goes out of scope,
359  // and array portals usually rely on the associated array handle
360  // maintaining the resources it points to. However, the entire state of the
361  // portal should be self contained except for the data managed by the
362  // object argument, which should stay in scope.
363  return groupedArray.PrepareForInPlace(Device(), token);
364  }
365 };
366 
367 template <typename ArrayHandleType, typename Device>
368 struct Transport<vtkm::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device>
369 {
370  VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
371 
372  using ContObjectType = ArrayHandleType;
373 
377 
379 
381  const vtkm::worklet::internal::KeysBase& keys,
382  vtkm::Id,
383  vtkm::Id,
384  vtkm::cont::Token& token) const
385  {
386  // The PrepareForOutput for ArrayHandleGroupVecVariable and
387  // ArrayHandlePermutation cannot determine the actual size expected for the
388  // target array (object), so we have to make sure it gets allocated here.
389  object.PrepareForOutput(keys.GetNumberOfValues(), Device(), token);
390 
391  PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
392  GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
393  // There is a bit of an issue here where groupedArray goes out of scope,
394  // and array portals usually rely on the associated array handle
395  // maintaining the resources it points to. However, the entire state of the
396  // portal should be self contained except for the data managed by the
397  // object argument, which should stay in scope.
398  return groupedArray.PrepareForOutput(keys.GetInputRange(), Device(), token);
399  }
400 };
401 }
402 }
403 } // namespace vtkm::cont::arg
404 
405 #ifndef vtk_m_worklet_Keys_cxx
406 
407 #define VTK_M_KEYS_EXPORT(T) \
408  extern template class VTKM_WORKLET_TEMPLATE_EXPORT vtkm::worklet::Keys<T>; \
409  extern template VTKM_WORKLET_TEMPLATE_EXPORT VTKM_CONT void vtkm::worklet::Keys<T>::BuildArrays( \
410  const vtkm::cont::ArrayHandle<T>& keys, \
411  vtkm::worklet::KeysSortType sort, \
412  vtkm::cont::DeviceAdapterId device)
413 
414 VTK_M_KEYS_EXPORT(vtkm::UInt8);
415 VTK_M_KEYS_EXPORT(vtkm::HashType);
416 VTK_M_KEYS_EXPORT(vtkm::Id);
417 VTK_M_KEYS_EXPORT(vtkm::Id2);
418 VTK_M_KEYS_EXPORT(vtkm::Id3);
420 VTK_M_KEYS_EXPORT(Pair_UInt8_Id2);
421 #ifdef VTKM_USE_64BIT_IDS
422 VTK_M_KEYS_EXPORT(vtkm::IdComponent);
423 #endif
424 
425 #undef VTK_M_KEYS_EXPORT
426 
427 #endif // !vtk_m_worklet_Keys_cxx
428 
429 #endif //vtk_m_worklet_Keys_h
vtkm::cont::arg::Transport::ExecObjectType
typename ContObjectType::ReadPortalType ExecObjectType
The type used in the execution environment.
Definition: Transport.h:48
TransportTagKeyedValuesInOut.h
vtkm::cont::ArrayHandle< vtkm::Id >
ArrayHandle.h
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device >::ContObjectType
ArrayHandleType ContObjectType
Definition: Keys.h:337
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device >::ContObjectType
ArrayHandleType ContObjectType
Definition: Keys.h:372
TransportTagKeyedValuesIn.h
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
StableSortIndices.h
ArrayHandleCast.h
TransportTagKeyedValuesOut.h
vtkm::cont::ArrayHandle::PrepareForInput
VTKM_CONT 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:574
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device >::operator()
VTKM_CONT ExecObjectType operator()(ContObjectType object, const vtkm::worklet::internal::KeysBase &keys, vtkm::Id, vtkm::Id, vtkm::cont::Token &token) const
Definition: Keys.h:380
vtkm::worklet::Keys::Keys
VTKM_CONT Keys()
vtkm::worklet::Keys::PrepareForInput
VTKM_CONT ExecLookup PrepareForInput(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Definition: Keys.h:182
vtkm::cont::ArrayHandleGroupVecVariable
Fancy array handle that groups values into vectors of different sizes.
Definition: ArrayHandleGroupVecVariable.h:255
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device >::ExecObjectType
typename GroupedArrayType::WritePortalType ExecObjectType
Definition: Keys.h:343
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeysIn, KeyType, Device >::ContObjectType
KeyType ContObjectType
Definition: Keys.h:272
DispatcherBase.h
vtkm::worklet::Keys::Keys
VTKM_CONT Keys(const vtkm::cont::ArrayHandle< KeyType, KeyStorage > &keys, vtkm::cont::DeviceAdapterId device=vtkm::cont::DeviceAdapterTagAny())
Construct a Keys class from an array of keys.
Definition: Keys.h:150
ArrayHandleConstant.h
vtkm::worklet::Keys::operator==
VTKM_CONT bool operator==(const vtkm::worklet::Keys< KeyType > &other) const
Definition: Keys.h:192
vtkm::cont::ArrayHandle::PrepareForInPlace
VTKM_CONT 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:593
vtkm::cont::ArrayHandle::ReadPortalType
typename StorageType::ReadPortalType ReadPortalType
Definition: ArrayHandle.h:294
vtkm::HashType
vtkm::UInt32 HashType
Definition: Hash.h:20
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeysIn, KeyType, Device >::ExecObjectType
typename ContObjectType::ExecLookup ExecObjectType
Definition: Keys.h:273
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
vtkm::cont::arg::TransportTagKeyedValuesIn
Transport tag for input values in a reduce by key.
Definition: TransportTagKeyedValuesIn.h:28
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device >::operator()
VTKM_CONT ExecObjectType operator()(const ContObjectType &object, const vtkm::worklet::internal::KeysBase &keys, vtkm::Id, vtkm::Id, vtkm::cont::Token &token) const
Definition: Keys.h:310
ArrayHandlePermutation.h
Algorithm.h
ArrayHandleIndex.h
VTKM_IS_ARRAY_HANDLE
#define VTKM_IS_ARRAY_HANDLE(T)
Definition: ArrayHandle.h:132
vtkm::cont::arg::TransportTagKeysIn
Transport tag for keys in a reduce by key.
Definition: TransportTagKeysIn.h:28
vtkm::cont::ArrayHandlePermutation
Implicitly permutes the values in an array.
Definition: ArrayHandlePermutation.h:227
vtkm::cont::arg::TypeCheck
Class for checking that a type matches the semantics for an argument.
Definition: TypeCheck.h:34
TransportTagKeysIn.h
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device >::ContObjectType
ArrayHandleType ContObjectType
Definition: Keys.h:302
vtkm::worklet::KeysSortType::Stable
@ Stable
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::worklet::KeysSortType
KeysSortType
Select the type of sort for BuildArrays calls.
Definition: Keys.h:107
vtkm::worklet::KeysSortType::Unstable
@ Unstable
vtkm::operator==
VTKM_EXEC_CONT bool operator==(const vtkm::Matrix< T, NumRow, NumCol > &a, const vtkm::Matrix< T, NumRow, NumCol > &b)
Definition: Matrix.h:615
vtkm::cont::ArrayHandle< vtkm::VecFromPortal< ComponentsArrayHandleType::WritePortalType >, vtkm::cont::StorageTagGroupVecVariable< ComponentsArrayHandleType::StorageTag, OffsetsArrayHandleType::StorageTag > >::WritePortalType
typename StorageType::WritePortalType WritePortalType
Definition: ArrayHandle.h:295
vtkm::worklet::Keys::GetUniqueKeys
VTKM_CONT KeyArrayHandleType GetUniqueKeys() const
Definition: Keys.h:175
vtkm::UInt8
uint8_t UInt8
Definition: Types.h:157
vtkm::cont::arg::TransportTagKeyedValuesOut
Transport tag for input values in a reduce by key.
Definition: TransportTagKeyedValuesOut.h:28
BinaryOperators.h
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesIn, ArrayHandleType, Device >::ExecObjectType
typename GroupedArrayType::ReadPortalType ExecObjectType
Definition: Keys.h:308
vtkm::cont::DeviceAdapterId
Definition: DeviceAdapterTag.h:52
vtkm::Vec
A short fixed-length array.
Definition: Types.h:767
vtkm::operator!=
VTKM_EXEC_CONT bool operator!=(const vtkm::Matrix< T, NumRow, NumCol > &a, const vtkm::Matrix< T, NumRow, NumCol > &b)
Definition: Matrix.h:629
vtkm::cont::ErrorBadValue
This class is thrown when a VTKm function or method encounters an invalid value that inhibits progres...
Definition: ErrorBadValue.h:25
vtkm::cont::arg::TypeCheck::value
static constexpr bool value
The static constant boolean value is set to true if the type is valid for the given check tag and fal...
Definition: TypeCheck.h:39
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesOut, ArrayHandleType, Device >::ExecObjectType
typename GroupedArrayType::WritePortalType ExecObjectType
Definition: Keys.h:378
vtkm::cont::ArrayHandle::PrepareForOutput
VTKM_CONT 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:613
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeysIn, KeyType, Device >::operator()
VTKM_CONT ExecObjectType operator()(const ContObjectType &object, const ContObjectType &inputDomain, vtkm::Id, vtkm::Id, vtkm::cont::Token &token) const
Definition: Keys.h:276
vtkm::worklet::Keys
Manage keys for a WorkletReduceByKey.
Definition: Keys.h:131
vtkm::worklet::Keys< vtkm::Id >::KeyType
vtkm::Id KeyType
Definition: Keys.h:134
vtkm::cont::arg::Transport
Class for transporting from the control to the execution environment.
Definition: Transport.h:38
ArrayHandleGroupVecVariable.h
VTKM_ALWAYS_EXPORT
#define VTKM_ALWAYS_EXPORT
Definition: ExportMacros.h:92
Logging.h
Logging utilities.
TypeCheckTagKeys.h
vtkm::cont::arg::TypeCheckTagKeys
Check for a Keys object.
Definition: TypeCheckTagKeys.h:24
Hash.h
vtkm::Pair
A vtkm::Pair is essentially the same as an STL pair object except that the methods (constructors and ...
Definition: Pair.h:29
vtkm::cont::arg::Transport::operator()
VTKM_CONT ExecObjectType operator()(const ContObjectType contData, const InputDomainType &inputDomain vtkm::Id outputSize) const
Send data to the execution environment.
vtkm::cont::arg::Transport< vtkm::cont::arg::TransportTagKeyedValuesInOut, ArrayHandleType, Device >::operator()
VTKM_CONT ExecObjectType operator()(ContObjectType object, const vtkm::worklet::internal::KeysBase &keys, vtkm::Id, vtkm::Id, vtkm::cont::Token &token) const
Definition: Keys.h:345
ReduceByKeyLookup.h
vtkm::worklet::Keys::operator!=
VTKM_CONT bool operator!=(const vtkm::worklet::Keys< KeyType > &other) const
Definition: Keys.h:200
vtkm::cont::arg::TransportTagKeyedValuesInOut
Transport tag for input values in a reduce by key.
Definition: TransportTagKeyedValuesInOut.h:28