VTK-m  2.0
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 
80 template <typename T>
82 {
83  // Checks if PortalType has a GetIteratorBegin() method that returns a
84  // pointer.
85  template <typename PortalType,
86  typename PointerType = decltype(std::declval<PortalType>().GetIteratorBegin())>
87  struct HasPointerAccess : public std::is_pointer<PointerType>
88  {
89  };
90 
91 public:
92  using ValueType = T;
93 
94  AtomicArrayExecutionObject() = default;
95 
98  vtkm::cont::Token& token)
99  : Data{ handle.PrepareForInPlace(device, token).GetIteratorBegin() }
100  , NumberOfValues{ handle.GetNumberOfValues() }
101  {
102  using PortalType = decltype(handle.PrepareForInPlace(device, token));
103  VTKM_STATIC_ASSERT_MSG(HasPointerAccess<PortalType>::value,
104  "Source portal must return a pointer from "
105  "GetIteratorBegin().");
106  }
107 
109  VTKM_EXEC
110  vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
111 
118  VTKM_EXEC
119  ValueType Get(vtkm::Id index) const
120  {
121  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
122  // currently only provides API for unsigned types.
123  // We'll cast the signed types to unsigned to work around this.
124  using APIType = typename detail::MakeUnsigned<ValueType>::type;
125 
126  return static_cast<T>(vtkm::AtomicLoad(reinterpret_cast<APIType*>(this->Data + index)));
127  }
128 
137  VTKM_EXEC
138  ValueType Add(vtkm::Id index, const ValueType& value) const
139  {
140  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
141  // currently only provides API for unsigned types.
142  // We'll cast the signed types to unsigned to work around this.
143  // This is safe, since the only difference between signed/unsigned types
144  // is how overflow works, and signed overflow is already undefined. We also
145  // document that overflow is undefined for this operation.
146  using APIType = typename detail::ArithType<ValueType>::type;
147 
148  return static_cast<T>(
149  vtkm::AtomicAdd(reinterpret_cast<APIType*>(this->Data + index), static_cast<APIType>(value)));
150  }
151 
164  VTKM_EXEC
165  void Set(vtkm::Id index, const ValueType& value) const
166  {
167  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
168  // currently only provides API for unsigned types.
169  // We'll cast the signed types to unsigned to work around this.
170  // This is safe, since the only difference between signed/unsigned types
171  // is how overflow works, and signed overflow is already undefined. We also
172  // document that overflow is undefined for this operation.
173  using APIType = typename detail::MakeUnsigned<ValueType>::type;
174 
175  vtkm::AtomicStore(reinterpret_cast<APIType*>(this->Data + index), static_cast<APIType>(value));
176  }
177 
222  VTKM_EXEC
223  bool CompareExchange(vtkm::Id index, ValueType* oldValue, const ValueType& newValue) const
224  {
225  // We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
226  // currently only provides API for unsigned types.
227  // We'll cast the signed types to unsigned to work around this.
228  // This is safe, since the only difference between signed/unsigned types
229  // is how overflow works, and signed overflow is already undefined.
230  using APIType = typename detail::MakeUnsigned<ValueType>::type;
231 
232  return vtkm::AtomicCompareExchange(reinterpret_cast<APIType*>(this->Data + index),
233  reinterpret_cast<APIType*>(oldValue),
234  static_cast<APIType>(newValue));
235  }
236 
237 private:
238  ValueType* Data{ nullptr };
240 };
241 }
242 } // namespace vtkm::exec
243 
244 #endif //vtk_m_exec_AtomicArrayExecutionObject_h
vtkm::AtomicAdd
VTKM_EXEC_CONT 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:824
Atomic.h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:283
ArrayHandle.h
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::AtomicStore
VTKM_EXEC_CONT 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:795
vtkm::exec::AtomicArrayExecutionObject::CompareExchange
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC bool CompareExchange(vtkm::Id index, ValueType *oldValue, const ValueType &newValue) const
Perform an atomic compare and exchange operation with sequentially consistent memory ordering.
Definition: AtomicArrayExecutionObject.h:223
vtkm::exec::AtomicArrayExecutionObject::GetNumberOfValues
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC vtkm::Id GetNumberOfValues() const
Definition: AtomicArrayExecutionObject.h:110
vtkm::exec::AtomicArrayExecutionObject::NumberOfValues
vtkm::Id NumberOfValues
Definition: AtomicArrayExecutionObject.h:239
vtkm::exec::AtomicArrayExecutionObject::Data
ValueType * Data
Definition: AtomicArrayExecutionObject.h:238
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::AtomicLoad
VTKM_EXEC_CONT 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:781
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::AtomicCompareExchange
VTKM_EXEC_CONT 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:971
DeviceAdapter.h
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
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::exec::AtomicArrayExecutionObject::ValueType
T ValueType
Definition: AtomicArrayExecutionObject.h:92
vtkm::exec::AtomicArrayExecutionObject::Get
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC ValueType Get(vtkm::Id index) const
Perform an atomic load of the indexed element with acquire memory ordering.
Definition: AtomicArrayExecutionObject.h:119
vtkm::exec::AtomicArrayExecutionObject::AtomicArrayExecutionObject
AtomicArrayExecutionObject()=default
vtkm::cont::DeviceAdapterId
Definition: DeviceAdapterTag.h:52
vtkm::exec::AtomicArrayExecutionObject::Add
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC ValueType Add(vtkm::Id index, const ValueType &value) const
Peform an atomic addition with sequentially consistent memory ordering.
Definition: AtomicArrayExecutionObject.h:138
vtkm::UInt32
uint32_t UInt32
Definition: Types.h:161
vtkm::exec::AtomicArrayExecutionObject::HasPointerAccess
Definition: AtomicArrayExecutionObject.h:87
vtkm::Float32
float Float32
Definition: Types.h:154
vtkm::Int32
int32_t Int32
Definition: Types.h:160
vtkm::Float64
double Float64
Definition: Types.h:155
vtkm::exec::AtomicArrayExecutionObject::AtomicArrayExecutionObject
VTKM_CONT AtomicArrayExecutionObject(vtkm::cont::ArrayHandle< T > handle, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token)
Definition: AtomicArrayExecutionObject.h:96
vtkm::exec::AtomicArrayExecutionObject
Definition: AtomicArrayExecutionObject.h:81
VTKM_SUPPRESS_EXEC_WARNINGS
#define VTKM_SUPPRESS_EXEC_WARNINGS
Definition: ExportMacros.h:53
vtkm::exec::AtomicArrayExecutionObject::Set
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC void Set(vtkm::Id index, const ValueType &value) const
Peform an atomic store to memory while enforcing, at minimum, "release" memory ordering.
Definition: AtomicArrayExecutionObject.h:165
List.h