VTK-m  2.2
AtomicArrayExecutionObject.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_exec_AtomicArrayExecutionObject_h
11 #define vtk_m_exec_AtomicArrayExecutionObject_h
12 
13 #include <vtkm/Atomic.h>
14 #include <vtkm/List.h>
15 #include <vtkm/cont/ArrayHandle.h>
17 
18 #include <type_traits>
19 
20 namespace vtkm
21 {
22 namespace exec
23 {
24 
25 namespace detail
26 {
27 // Clang-7 as host compiler under nvcc returns types from std::make_unsigned
28 // that are not compatible with the vtkm::Atomic API, so we define our own
29 // mapping. This must exist for every entry in vtkm::cont::AtomicArrayTypeList.
30 template <typename>
31 struct MakeUnsigned;
32 template <>
33 struct MakeUnsigned<vtkm::UInt32>
34 {
35  using type = vtkm::UInt32;
36 };
37 template <>
38 struct MakeUnsigned<vtkm::Int32>
39 {
40  using type = vtkm::UInt32;
41 };
42 template <>
43 struct MakeUnsigned<vtkm::UInt64>
44 {
45  using type = vtkm::UInt64;
46 };
47 template <>
48 struct MakeUnsigned<vtkm::Int64>
49 {
50  using type = vtkm::UInt64;
51 };
52 template <>
53 struct MakeUnsigned<vtkm::Float32>
54 {
55  using type = vtkm::UInt32;
56 };
57 template <>
58 struct MakeUnsigned<vtkm::Float64>
59 {
60  using type = vtkm::UInt64;
61 };
62 
63 template <typename T>
64 struct ArithType
65 {
66  using type = typename MakeUnsigned<T>::type;
67 };
68 template <>
69 struct ArithType<vtkm::Float32>
70 {
71  using type = vtkm::Float32;
72 };
73 template <>
74 struct ArithType<vtkm::Float64>
75 {
76  using type = vtkm::Float64;
77 };
78 }
79 
87 template <typename T>
89 {
90  // Checks if PortalType has a GetIteratorBegin() method that returns a
91  // pointer.
92  template <typename PortalType,
93  typename PointerType = decltype(std::declval<PortalType>().GetIteratorBegin())>
94  struct HasPointerAccess : public std::is_pointer<PointerType>
95  {
96  };
97 
98 public:
99  using ValueType = T;
100 
101  AtomicArrayExecutionObject() = default;
102 
105  vtkm::cont::Token& token)
106  : Data{ handle.PrepareForInPlace(device, token).GetIteratorBegin() }
107  , NumberOfValues{ handle.GetNumberOfValues() }
108  {
109  using PortalType = decltype(handle.PrepareForInPlace(device, token));
110  VTKM_STATIC_ASSERT_MSG(HasPointerAccess<PortalType>::value,
111  "Source portal must return a pointer from "
112  "GetIteratorBegin().");
113  }
114 
117  VTKM_EXEC
118  vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
119 
127  VTKM_EXEC
129  {
130  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
131  // currently only provides API for unsigned types.
132  // We'll cast the signed types to unsigned to work around this.
133  using APIType = typename detail::MakeUnsigned<ValueType>::type;
134 
135  return static_cast<T>(vtkm::AtomicLoad(reinterpret_cast<APIType*>(this->Data + index), order));
136  }
137 
147  VTKM_EXEC
149  const ValueType& value,
151  {
152  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
153  // currently only provides API for unsigned types.
154  // We'll cast the signed types to unsigned to work around this.
155  // This is safe, since the only difference between signed/unsigned types
156  // is how overflow works, and signed overflow is already undefined. We also
157  // document that overflow is undefined for this operation.
158  using APIType = typename detail::ArithType<ValueType>::type;
159 
160  return static_cast<T>(vtkm::AtomicAdd(
161  reinterpret_cast<APIType*>(this->Data + index), static_cast<APIType>(value), order));
162  }
163 
177  VTKM_EXEC
178  void Set(vtkm::Id index,
179  const ValueType& value,
181  {
182  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
183  // currently only provides API for unsigned types.
184  // We'll cast the signed types to unsigned to work around this.
185  // This is safe, since the only difference between signed/unsigned types
186  // is how overflow works, and signed overflow is already undefined. We also
187  // document that overflow is undefined for this operation.
188  using APIType = typename detail::MakeUnsigned<ValueType>::type;
189 
191  reinterpret_cast<APIType*>(this->Data + index), static_cast<APIType>(value), order);
192  }
193 
239  VTKM_EXEC
241  ValueType* oldValue,
242  const ValueType& newValue,
244  {
245  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
246  // currently only provides API for unsigned types.
247  // We'll cast the signed types to unsigned to work around this.
248  // This is safe, since the only difference between signed/unsigned types
249  // is how overflow works, and signed overflow is already undefined.
250  using APIType = typename detail::MakeUnsigned<ValueType>::type;
251 
252  return vtkm::AtomicCompareExchange(reinterpret_cast<APIType*>(this->Data + index),
253  reinterpret_cast<APIType*>(oldValue),
254  static_cast<APIType>(newValue),
255  order);
256  }
257 
258 private:
259  ValueType* Data{ nullptr };
261 };
262 }
263 } // namespace vtkm::exec
264 
265 #endif //vtk_m_exec_AtomicArrayExecutionObject_h
vtkm::exec::AtomicArrayExecutionObject::Set
void Set(vtkm::Id index, const ValueType &value, vtkm::MemoryOrder order=vtkm::MemoryOrder::Release) const
Peform an atomic store to memory while enforcing, at minimum, "release" memory ordering.
Definition: AtomicArrayExecutionObject.h:178
Atomic.h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
ArrayHandle.h
vtkm::AtomicAdd
T AtomicAdd(T *pointer, T operand, vtkm::MemoryOrder order=vtkm::MemoryOrder::SequentiallyConsistent)
Atomic function to add a value to a shared memory location.
Definition: Atomic.h:829
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::AtomicLoad
T AtomicLoad(T *const pointer, vtkm::MemoryOrder order=vtkm::MemoryOrder::Acquire)
Atomic function to load a value from a shared memory location.
Definition: Atomic.h:786
vtkm::exec::AtomicArrayExecutionObject::Add
ValueType Add(vtkm::Id index, const ValueType &value, vtkm::MemoryOrder order=vtkm::MemoryOrder::SequentiallyConsistent) const
Peform an atomic addition with sequentially consistent memory ordering.
Definition: AtomicArrayExecutionObject.h:148
vtkm::MemoryOrder::Release
@ Release
A store operation with Release memory order will enforce that any local read or write operations list...
vtkm::exec::AtomicArrayExecutionObject::NumberOfValues
vtkm::Id NumberOfValues
Definition: AtomicArrayExecutionObject.h:260
vtkm::exec::AtomicArrayExecutionObject::Data
ValueType * Data
Definition: AtomicArrayExecutionObject.h:259
vtkm::MemoryOrder
MemoryOrder
Specifies memory order semantics for atomic operations.
Definition: Atomic.h:56
vtkm::exec::AtomicArrayExecutionObject::GetNumberOfValues
vtkm::Id GetNumberOfValues() const
Retrieve the number of values in the atomic array.
Definition: AtomicArrayExecutionObject.h:118
DeviceAdapter.h
vtkm::MemoryOrder::SequentiallyConsistent
@ SequentiallyConsistent
An atomic with SequentiallyConsistent memory order will enforce any appropriate semantics as Acquire,...
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
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_STATIC_ASSERT_MSG
#define VTKM_STATIC_ASSERT_MSG(condition, message)
Definition: StaticAssert.h:18
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
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::exec::AtomicArrayExecutionObject::ValueType
T ValueType
Definition: AtomicArrayExecutionObject.h:99
vtkm::exec::AtomicArrayExecutionObject::AtomicArrayExecutionObject
AtomicArrayExecutionObject()=default
vtkm::cont::DeviceAdapterId
An object used to specify a device.
Definition: DeviceAdapterTag.h:58
vtkm::exec::AtomicArrayExecutionObject::CompareExchange
bool CompareExchange(vtkm::Id index, ValueType *oldValue, const ValueType &newValue, vtkm::MemoryOrder order=vtkm::MemoryOrder::SequentiallyConsistent) const
Perform an atomic compare and exchange operation with sequentially consistent memory ordering.
Definition: AtomicArrayExecutionObject.h:240
vtkm::UInt32
uint32_t UInt32
Base type to use for 32-bit unsigned integer numbers.
Definition: Types.h:185
vtkm::exec::AtomicArrayExecutionObject::HasPointerAccess
Definition: AtomicArrayExecutionObject.h:94
vtkm::Float32
float Float32
Base type to use for 32-bit floating-point numbers.
Definition: Types.h:157
vtkm::UInt64
unsigned long long UInt64
Base type to use for 64-bit signed integer numbers.
Definition: Types.h:207
vtkm::Int32
int32_t Int32
Base type to use for 32-bit signed integer numbers.
Definition: Types.h:181
vtkm::Float64
double Float64
Base type to use for 64-bit floating-point numbers.
Definition: Types.h:161
vtkm::exec::AtomicArrayExecutionObject::Get
ValueType Get(vtkm::Id index, vtkm::MemoryOrder order=vtkm::MemoryOrder::Acquire) const
Perform an atomic load of the indexed element with acquire memory ordering.
Definition: AtomicArrayExecutionObject.h:128
vtkm::exec::AtomicArrayExecutionObject::AtomicArrayExecutionObject
AtomicArrayExecutionObject(vtkm::cont::ArrayHandle< T > handle, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token)
Definition: AtomicArrayExecutionObject.h:103
vtkm::AtomicCompareExchange
bool AtomicCompareExchange(T *shared, T *expected, T desired, vtkm::MemoryOrder order=vtkm::MemoryOrder::SequentiallyConsistent)
Atomic function that replaces a value given a condition.
Definition: Atomic.h:976
vtkm::MemoryOrder::Acquire
@ Acquire
A load operation with Acquire memory order will enforce that any local read or write operations liste...
vtkm::exec::AtomicArrayExecutionObject
An object passed to a worklet when accessing an atomic array.
Definition: AtomicArrayExecutionObject.h:88
VTKM_SUPPRESS_EXEC_WARNINGS
#define VTKM_SUPPRESS_EXEC_WARNINGS
Definition: ExportMacros.h:53
List.h
vtkm::AtomicStore
void AtomicStore(T *pointer, T value, vtkm::MemoryOrder order=vtkm::MemoryOrder::Release)
Atomic function to save a value to a shared memory location.
Definition: Atomic.h:800