VTK-m  2.0
ParallelScanOpenMP.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 
14 
16 
17 #include <vtkm/Types.h>
18 #include <vtkm/cont/ArrayHandle.h>
19 
20 #include <omp.h>
21 
22 namespace vtkm
23 {
24 namespace cont
25 {
26 namespace openmp
27 {
28 namespace scan
29 {
30 
31 enum class ChildType
32 {
33  Left,
34  Right
35 };
36 
37 // Generic implementation of modified Ladner & Fischer 1977 "adder" algorithm
38 // used for backbone of exclusive/inclusive scans. Language in comments is
39 // specific to computing a sum, but the implementation should be generic enough
40 // for any scan operation.
41 //
42 // The basic idea is that a tree structure is used to partition the input into
43 // sets of LeafSize. Each leaf of the tree is processed in two stages: First,
44 // the sum of each leaf is computed, and this information is pushed up the tree
45 // to compute the sum of each node's child leaves. Then the partial sum at the
46 // start of each node is computed and pushed down the tree (the "carry"
47 // values). In the second pass through each leaf's data, these partial sums are
48 // used to compute the final output from the carry value and the input data.
49 //
50 // The passes will likely overlap due to the "leftEdge" optimizations, which
51 // allow each leaf to start the second pass as soon as the first pass of all
52 // previous leaves is completed. Additionally, the first leaf in the data will
53 // combine both passes into one, computing the final output data while
54 // generating its sum for the communication stage.
55 template <typename ScanBody>
56 struct Adder : public ScanBody
57 {
58  template <typename NodeImpl>
59  struct NodeWrapper : public NodeImpl
60  {
61  // Range of IDs this node represents
62  vtkm::Id2 Range{ -1, -1 };
63 
64  // Connections:
65  NodeWrapper* Parent{ nullptr };
66  NodeWrapper* Left{ nullptr };
67  NodeWrapper* Right{ nullptr };
68 
69  // Special flag to mark nodes on the far left edge of the tree. This allows
70  // various optimization that start the second pass sooner on some ranges.
71  bool LeftEdge{ false };
72 
73  // Pad the node out to the size of a cache line to prevent false sharing:
74  static constexpr size_t DataSize =
75  sizeof(NodeImpl) + sizeof(vtkm::Id2) + 3 * sizeof(NodeWrapper*) + sizeof(bool);
76  static constexpr size_t NumCacheLines = CeilDivide<size_t>(DataSize, VTKM_CACHE_LINE_SIZE);
77  static constexpr size_t PaddingSize = NumCacheLines * VTKM_CACHE_LINE_SIZE - DataSize;
78  unsigned char Padding[PaddingSize];
79  };
80 
82  using ValueType = typename ScanBody::ValueType;
83 
85  std::vector<Node> Nodes;
86  size_t NextNode;
87 
88  // Use ScanBody's ctor:
89  using ScanBody::ScanBody;
90 
91  // Returns the total array sum:
92  ValueType Execute(const vtkm::Id2& range)
93  {
94  Node* rootNode = nullptr;
95 
96  VTKM_OPENMP_DIRECTIVE(parallel default(shared))
97  {
98  VTKM_OPENMP_DIRECTIVE(single)
99  {
100  // Allocate nodes, prep metadata:
101  this->Prepare(range);
102 
103  // Compute the partition and node sums:
104  rootNode = this->AllocNode();
105  rootNode->Range = range;
106  rootNode->LeftEdge = true;
107  ScanBody::InitializeRootNode(rootNode);
108 
109  this->Scan(rootNode);
110  } // end single
111  } // end parallel
112 
113  return rootNode ? ScanBody::GetFinalResult(rootNode)
115  }
116 
117 private:
118  // Returns the next available node in a thread-safe manner.
120  {
121  size_t nodeIdx;
122 
123 // GCC emits a false positive "value computed but not used" for this block:
124 #pragma GCC diagnostic push
125 #pragma GCC diagnostic ignored "-Wunused-value"
126 
127  VTKM_OPENMP_DIRECTIVE(atomic capture)
128  {
129  nodeIdx = this->NextNode;
130  ++this->NextNode;
131  }
132 
133 #pragma GCC diagnostic pop
134 
135  VTKM_ASSERT(nodeIdx < this->Nodes.size());
136 
137  return &this->Nodes[nodeIdx];
138  }
139 
140  // Does the range represent a leave node?
141  bool IsLeaf(const vtkm::Id2& range) const { return (range[1] - range[0]) <= this->LeafSize; }
142 
143  // Use to split ranges. Ensures that the first range is always a multiple of
144  // LeafSize, when possible.
145  vtkm::Id ComputeMidpoint(const vtkm::Id2& range) const
146  {
147  const vtkm::Id n = range[1] - range[0];
148  const vtkm::Id np = this->LeafSize;
149 
150  return (((n / 2) + (np - 1)) / np) * np + range[0];
151  }
152 
153  void Prepare(const vtkm::Id2& range)
154  {
155  // Figure out how many values each thread should handle:
156  vtkm::Id numVals = range[1] - range[0];
157  vtkm::Id numThreads = 0;
159  .GetRuntimeConfiguration(vtkm::cont::DeviceAdapterTagOpenMP())
160  .GetThreads(numThreads);
161  vtkm::Id chunksPerThread = 8;
162  vtkm::Id numChunks;
163  ComputeChunkSize(
164  numVals, numThreads, chunksPerThread, sizeof(ValueType), numChunks, this->LeafSize);
165 
166  // Compute an upper-bound of the number of nodes in the tree:
167  std::size_t numNodes = static_cast<std::size_t>(numChunks);
168  while (numChunks > 1)
169  {
170  numChunks = (numChunks + 1) / 2;
171  numNodes += static_cast<std::size_t>(numChunks);
172  }
173  this->Nodes.resize(numNodes);
174  this->NextNode = 0;
175  }
176 
177  // Build the tree and compute the sums:
178  void Scan(Node* node)
179  {
180  if (!this->IsLeaf(node->Range))
181  { // split range:
182  vtkm::Id midpoint = this->ComputeMidpoint(node->Range);
183 
184  Node* right = this->AllocNode();
185  right->Parent = node;
186  node->Right = right;
187  right->Range = vtkm::Id2(midpoint, node->Range[1]);
188  ScanBody::InitializeChildNode(right, node, ChildType::Right, false);
189 
190  // Intel compilers seem to have trouble following the 'this' pointer
191  // when launching tasks, resulting in a corrupt task environment.
192  // Explicitly copying the pointer into a local variable seems to fix this.
193  auto explicitThis = this;
194 
195  VTKM_OPENMP_DIRECTIVE(taskgroup)
196  {
197  VTKM_OPENMP_DIRECTIVE(task) { explicitThis->Scan(right); } // end right task
198 
199  Node* left = this->AllocNode();
200  left->Parent = node;
201  node->Left = left;
202  left->Range = vtkm::Id2(node->Range[0], midpoint);
203  left->LeftEdge = node->LeftEdge;
204  ScanBody::InitializeChildNode(left, node, ChildType::Left, left->LeftEdge);
205  this->Scan(left);
206 
207  } // end task group. Both l/r sums will be finished here.
208 
209  ScanBody::CombineSummaries(node, node->Left, node->Right);
210  if (node->LeftEdge)
211  {
212  this->UpdateOutput(node);
213  }
214  }
215  else
216  { // Compute sums:
217  ScanBody::ComputeSummary(node, node->Range, node->LeftEdge);
218  }
219  }
220 
221  void UpdateOutput(Node* node)
222  {
223  if (node->Left != nullptr)
224  {
225  assert(node->Right != nullptr);
226  ScanBody::PropagateSummaries(node, node->Left, node->Right, node->LeftEdge);
227 
228  // if this node is on the left edge, we know that the left child's
229  // output is already updated, so only descend to the right:
230  if (node->LeftEdge)
231  {
232  this->UpdateOutput(node->Right);
233  }
234  else // Otherwise descent into both:
235  {
236  // Intel compilers seem to have trouble following the 'this' pointer
237  // when launching tasks, resulting in a corrupt task environment.
238  // Explicitly copying the pointer into a local variable seems to fix
239  // this.
240  auto explicitThis = this;
241 
242  // no taskgroup/sync needed other than the final barrier of the parallel
243  // section.
244  VTKM_OPENMP_DIRECTIVE(task) { explicitThis->UpdateOutput(node->Right); } // end task
245  this->UpdateOutput(node->Left);
246  }
247  }
248  else
249  {
250  ScanBody::UpdateOutput(node, node->Range, node->LeftEdge);
251  }
252  }
253 };
254 
255 template <typename InPortalT, typename OutPortalT, typename RawFunctorT>
257 {
258  using ValueType = typename InPortalT::ValueType;
259  using FunctorType = internal::WrappedBinaryOperator<ValueType, RawFunctorT>;
260 
261  InPortalT InPortal;
262  OutPortalT OutPortal;
265 
266  struct Node
267  {
268  // Sum of all values in range
270 
271  // The sum of all elements prior to this node's range
273  };
274 
275  ScanExclusiveBody(const InPortalT& inPortal,
276  const OutPortalT& outPortal,
277  const RawFunctorT& functor,
278  const ValueType& init)
279  : InPortal(inPortal)
280  , OutPortal(outPortal)
281  , Functor(functor)
282  , InitialValue(init)
283  {
284  }
285 
286  // Initialize the root of the node tree
287  void InitializeRootNode(Node* /*root*/) {}
288 
289  void InitializeChildNode(Node* /*node*/,
290  const Node* /*parent*/,
291  ChildType /*type*/,
292  bool /*leftEdge*/)
293  {
294  }
295 
296  void ComputeSummary(Node* node, const vtkm::Id2& range, bool leftEdge)
297  {
298  auto input = vtkm::cont::ArrayPortalToIteratorBegin(this->InPortal);
299  node->Sum = input[range[0]];
300 
301  // If this block is on the left edge, we can update the output while we
302  // compute the sum:
303  if (leftEdge)
304  {
305  // Set leftEdge arg to false to force the update:
306  node->Sum = UpdateOutputImpl(node, range, false, true);
307  }
308  else // Otherwise, only compute the sum and update the output in pass 2.
309  {
310  for (vtkm::Id i = range[0] + 1; i < range[1]; ++i)
311  {
312  node->Sum = this->Functor(node->Sum, input[i]);
313  }
314  }
315  }
316 
317  void CombineSummaries(Node* parent, const Node* left, const Node* right)
318  {
319  parent->Sum = this->Functor(left->Sum, right->Sum);
320  }
321 
322  void PropagateSummaries(const Node* parent, Node* left, Node* right, bool leftEdge)
323  {
324  left->Carry = parent->Carry;
325  right->Carry = leftEdge ? left->Sum : this->Functor(parent->Carry, left->Sum);
326  }
327 
328  void UpdateOutput(const Node* node, const vtkm::Id2& range, bool leftEdge)
329  {
330  this->UpdateOutputImpl(node, range, leftEdge, false);
331  }
332 
333  ValueType UpdateOutputImpl(const Node* node, const vtkm::Id2& range, bool skip, bool useInit)
334  {
335  if (skip)
336  {
337  // Do nothing; this was already done in ComputeSummary.
339  }
340 
341  auto input = vtkm::cont::ArrayPortalToIteratorBegin(this->InPortal);
342  auto output = vtkm::cont::ArrayPortalToIteratorBegin(this->OutPortal);
343 
344  // Be careful with the order input/output are modified. They might be
345  // pointing at the same data:
346  ValueType carry = useInit ? this->InitialValue : node->Carry;
347  vtkm::Id end = range[1];
348 
349  for (vtkm::Id i = range[0]; i < end; ++i)
350  {
351  output[i] = this->Functor(carry, input[i]);
352 
353  using std::swap; // Enable ADL
354  swap(output[i], carry);
355  }
356 
357  return carry;
358  }
359 
360  // Compute the final sum from the node's metadata:
361  ValueType GetFinalResult(const Node* node) const { return this->Functor(node->Sum, node->Carry); }
362 };
363 
364 template <typename InPortalT, typename OutPortalT, typename RawFunctorT>
366 {
367  using ValueType = typename InPortalT::ValueType;
368  using FunctorType = internal::WrappedBinaryOperator<ValueType, RawFunctorT>;
369 
370  InPortalT InPortal;
371  OutPortalT OutPortal;
373 
374  struct Node
375  {
376  // Sum of all values in range
378 
379  // The sum of all elements prior to this node's range
381  };
382 
383  ScanInclusiveBody(const InPortalT& inPortal,
384  const OutPortalT& outPortal,
385  const RawFunctorT& functor)
386  : InPortal(inPortal)
387  , OutPortal(outPortal)
388  , Functor(functor)
389  {
390  }
391 
392  // Initialize the root of the node tree
394  {
395  // no-op
396  }
397 
398  void InitializeChildNode(Node*, const Node*, ChildType, bool)
399  {
400  // no-op
401  }
402 
403  void ComputeSummary(Node* node, const vtkm::Id2& range, bool leftEdge)
404  {
405  // If this block is on the left edge, we can update the output while we
406  // compute the sum:
407  if (leftEdge)
408  {
409  node->Sum = UpdateOutputImpl(node, range, false, false);
410  }
411  else // Otherwise, only compute the sum and update the output in pass 2.
412  {
413  auto input = vtkm::cont::ArrayPortalToIteratorBegin(this->InPortal);
414  node->Sum = input[range[0]];
415  for (vtkm::Id i = range[0] + 1; i < range[1]; ++i)
416  {
417  node->Sum = this->Functor(node->Sum, input[i]);
418  }
419  }
420  }
421 
422  void CombineSummaries(Node* parent, const Node* left, const Node* right)
423  {
424  parent->Sum = this->Functor(left->Sum, right->Sum);
425  }
426 
427  void PropagateSummaries(const Node* parent, Node* left, Node* right, bool leftEdge)
428  {
429  left->Carry = parent->Carry;
430  right->Carry = leftEdge ? left->Sum : this->Functor(parent->Carry, left->Sum);
431  }
432 
433  void UpdateOutput(const Node* node, const vtkm::Id2& range, bool leftEdge)
434  {
435  UpdateOutputImpl(node, range, leftEdge, true);
436  }
437 
438  ValueType UpdateOutputImpl(const Node* node, const vtkm::Id2& range, bool skip, bool useCarry)
439  {
440  if (skip)
441  {
442  // Do nothing; this was already done in ComputeSummary.
444  }
445 
446  auto input = vtkm::cont::ArrayPortalToIteratorBegin(this->InPortal);
447  auto output = vtkm::cont::ArrayPortalToIteratorBegin(this->OutPortal);
448 
449  vtkm::Id start = range[0];
450  vtkm::Id end = range[1];
451  ValueType carry = node->Carry;
452 
453  // Initialize with the first value if this is the first range:
454  if (!useCarry && start < end)
455  {
456  carry = input[start];
457  output[start] = carry;
458  ++start;
459  }
460 
461  for (vtkm::Id i = start; i < end; ++i)
462  {
463  output[i] = this->Functor(carry, input[i]);
464  carry = output[i];
465  }
466 
467  return output[end - 1];
468  }
469 
470  // Compute the final sum from the node's metadata:
471  ValueType GetFinalResult(const Node* node) const { return node->Sum; }
472 };
473 
474 } // end namespace scan
475 
476 template <typename InPortalT, typename OutPortalT, typename FunctorT>
478 
479 template <typename InPortalT, typename OutPortalT, typename FunctorT>
481 }
482 }
483 } // end namespace vtkm::cont::openmp
vtkm::cont::ArrayPortalToIteratorBegin
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT vtkm::cont::ArrayPortalToIterators< PortalType >::IteratorType ArrayPortalToIteratorBegin(const PortalType &portal)
Convenience function for converting an ArrayPortal to a begin iterator.
Definition: ArrayPortalToIterators.h:178
vtkm::cont::openmp::scan::ScanInclusiveBody::UpdateOutput
void UpdateOutput(const Node *node, const vtkm::Id2 &range, bool leftEdge)
Definition: ParallelScanOpenMP.h:433
vtkm::cont::openmp::scan::ChildType::Left
@ Left
vtkm::cont::openmp::scan::ScanExclusiveBody::CombineSummaries
void CombineSummaries(Node *parent, const Node *left, const Node *right)
Definition: ParallelScanOpenMP.h:317
ArrayHandle.h
FunctorsGeneral.h
vtkm::cont::openmp::scan::ScanExclusiveBody::ComputeSummary
void ComputeSummary(Node *node, const vtkm::Id2 &range, bool leftEdge)
Definition: ParallelScanOpenMP.h:296
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
Types.h
vtkm::cont::openmp::scan::ScanInclusiveBody
Definition: ParallelScanOpenMP.h:365
vtkm::cont::openmp::scan::ScanExclusiveBody::ValueType
typename InPortalT::ValueType ValueType
Definition: ParallelScanOpenMP.h:258
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
vtkm::cont::openmp::scan::ScanInclusiveBody::GetFinalResult
ValueType GetFinalResult(const Node *node) const
Definition: ParallelScanOpenMP.h:471
vtkm::cont::openmp::scan::ScanExclusiveBody::Node::Carry
ValueType Carry
Definition: ParallelScanOpenMP.h:272
vtkm::cont::openmp::scan::Adder::ComputeMidpoint
vtkm::Id ComputeMidpoint(const vtkm::Id2 &range) const
Definition: ParallelScanOpenMP.h:145
vtkm::cont::openmp::scan::ScanExclusiveBody::InitializeChildNode
void InitializeChildNode(Node *, const Node *, ChildType, bool)
Definition: ParallelScanOpenMP.h:289
vtkm::cont::openmp::scan::Adder::NodeWrapper::Range
vtkm::Id2 Range
Definition: ParallelScanOpenMP.h:62
vtkm::cont::openmp::scan::ScanInclusiveBody::InitializeRootNode
void InitializeRootNode(Node *)
Definition: ParallelScanOpenMP.h:393
vtkm::cont::openmp::scan::Adder::NodeWrapper::NumCacheLines
static constexpr size_t NumCacheLines
Definition: ParallelScanOpenMP.h:76
vtkm::cont::openmp::scan::Adder::NodeWrapper::Padding
unsigned char Padding[PaddingSize]
Definition: ParallelScanOpenMP.h:78
vtkm::cont::openmp::scan::ScanExclusiveBody::Functor
FunctorType Functor
Definition: ParallelScanOpenMP.h:263
vtkm::cont::openmp::scan::Adder::AllocNode
Node * AllocNode()
Definition: ParallelScanOpenMP.h:119
vtkm::cont::openmp::scan::Adder::NextNode
size_t NextNode
Definition: ParallelScanOpenMP.h:86
vtkm::cont::openmp::scan::ScanExclusiveBody::InitializeRootNode
void InitializeRootNode(Node *)
Definition: ParallelScanOpenMP.h:287
vtkm::cont::openmp::scan::Adder::NodeWrapper::Right
NodeWrapper * Right
Definition: ParallelScanOpenMP.h:67
FunctorsOpenMP.h
vtkm::cont::openmp::scan::Adder::IsLeaf
bool IsLeaf(const vtkm::Id2 &range) const
Definition: ParallelScanOpenMP.h:141
vtkm::cont::openmp::scan::Adder::NodeWrapper::LeftEdge
bool LeftEdge
Definition: ParallelScanOpenMP.h:71
vtkm::cont::openmp::scan::ScanExclusiveBody::Node
Definition: ParallelScanOpenMP.h:266
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::openmp::scan::ScanInclusiveBody::OutPortal
OutPortalT OutPortal
Definition: ParallelScanOpenMP.h:371
DeviceAdapterTagOpenMP.h
vtkm::cont::openmp::scan::ChildType::Right
@ Right
vtkm::cont::openmp::scan::Adder
Definition: ParallelScanOpenMP.h:56
vtkm::Sum
Binary Predicate that takes two arguments argument x, and y and returns sum (addition) of the two val...
Definition: BinaryOperators.h:33
vtkm::cont::openmp::scan::Adder::Scan
void Scan(Node *node)
Definition: ParallelScanOpenMP.h:178
vtkm::cont::openmp::scan::Adder::NodeWrapper::Parent
NodeWrapper * Parent
Definition: ParallelScanOpenMP.h:65
vtkm::cont::openmp::scan::ScanInclusiveBody::Node::Carry
ValueType Carry
Definition: ParallelScanOpenMP.h:380
vtkm::cont::openmp::scan::ScanExclusiveBody::Node::Sum
ValueType Sum
Definition: ParallelScanOpenMP.h:269
vtkm::cont::openmp::scan::ScanInclusiveBody::PropagateSummaries
void PropagateSummaries(const Node *parent, Node *left, Node *right, bool leftEdge)
Definition: ParallelScanOpenMP.h:427
vtkm::cont::openmp::scan::ScanInclusiveBody::ScanInclusiveBody
ScanInclusiveBody(const InPortalT &inPortal, const OutPortalT &outPortal, const RawFunctorT &functor)
Definition: ParallelScanOpenMP.h:383
vtkm::cont::openmp::scan::ScanExclusiveBody::UpdateOutputImpl
ValueType UpdateOutputImpl(const Node *node, const vtkm::Id2 &range, bool skip, bool useInit)
Definition: ParallelScanOpenMP.h:333
vtkm::cont::openmp::scan::ScanInclusiveBody::CombineSummaries
void CombineSummaries(Node *parent, const Node *left, const Node *right)
Definition: ParallelScanOpenMP.h:422
vtkm::cont::openmp::scan::Adder::NodeWrapper::Left
NodeWrapper * Left
Definition: ParallelScanOpenMP.h:66
vtkm::cont::openmp::scan::ScanExclusiveBody::UpdateOutput
void UpdateOutput(const Node *node, const vtkm::Id2 &range, bool leftEdge)
Definition: ParallelScanOpenMP.h:328
vtkm::cont::openmp::scan::ScanInclusiveBody::UpdateOutputImpl
ValueType UpdateOutputImpl(const Node *node, const vtkm::Id2 &range, bool skip, bool useCarry)
Definition: ParallelScanOpenMP.h:438
vtkm::cont::openmp::scan::Adder::NodeWrapper
Definition: ParallelScanOpenMP.h:59
vtkm::cont::openmp::scan::ScanInclusiveBody::Node
Definition: ParallelScanOpenMP.h:374
vtkm::cont::RuntimeDeviceInformation::GetRuntimeConfiguration
VTKM_CONT vtkm::cont::internal::RuntimeDeviceConfigurationBase & GetRuntimeConfiguration(DeviceAdapterId id, const vtkm::cont::internal::RuntimeDeviceConfigurationOptions &configOptions, int &argc, char *argv[]=nullptr) const
Returns a reference to a RuntimeDeviceConfiguration that will work with the given device.
VTKM_OPENMP_DIRECTIVE
#define VTKM_OPENMP_DIRECTIVE(directive)
Definition: FunctorsOpenMP.h:37
vtkm::cont::openmp::scan::ScanInclusiveBody::FunctorType
internal::WrappedBinaryOperator< ValueType, RawFunctorT > FunctorType
Definition: ParallelScanOpenMP.h:368
vtkm::cont::openmp::scan::ScanExclusiveBody::GetFinalResult
ValueType GetFinalResult(const Node *node) const
Definition: ParallelScanOpenMP.h:361
vtkm::cont::openmp::scan::Adder::Nodes
std::vector< Node > Nodes
Definition: ParallelScanOpenMP.h:85
vtkm::cont::openmp::scan::ScanInclusiveBody::ValueType
typename InPortalT::ValueType ValueType
Definition: ParallelScanOpenMP.h:367
vtkm::cont::openmp::scan::ScanExclusiveBody::InPortal
InPortalT InPortal
Definition: ParallelScanOpenMP.h:261
vtkm::cont::openmp::scan::ScanInclusiveBody::Node::Sum
ValueType Sum
Definition: ParallelScanOpenMP.h:377
vtkm::Vec< vtkm::Id, 2 >
vtkm::cont::openmp::scan::ScanExclusiveBody::PropagateSummaries
void PropagateSummaries(const Node *parent, Node *left, Node *right, bool leftEdge)
Definition: ParallelScanOpenMP.h:322
vtkm::cont::openmp::scan::ScanExclusiveBody::OutPortal
OutPortalT OutPortal
Definition: ParallelScanOpenMP.h:262
vtkm::cont::openmp::scan::Adder::NodeWrapper::PaddingSize
static constexpr size_t PaddingSize
Definition: ParallelScanOpenMP.h:77
vtkm::cont::openmp::scan::Adder::NodeWrapper::DataSize
static constexpr size_t DataSize
Definition: ParallelScanOpenMP.h:74
vtkm::cont::openmp::scan::ScanExclusiveBody::ScanExclusiveBody
ScanExclusiveBody(const InPortalT &inPortal, const OutPortalT &outPortal, const RawFunctorT &functor, const ValueType &init)
Definition: ParallelScanOpenMP.h:275
vtkm::cont::openmp::scan::ScanInclusiveBody::ComputeSummary
void ComputeSummary(Node *node, const vtkm::Id2 &range, bool leftEdge)
Definition: ParallelScanOpenMP.h:403
vtkm::cont::openmp::scan::Adder::Execute
ValueType Execute(const vtkm::Id2 &range)
Definition: ParallelScanOpenMP.h:92
vtkm::cont::openmp::scan::ScanExclusiveBody::InitialValue
ValueType InitialValue
Definition: ParallelScanOpenMP.h:264
vtkm::cont::openmp::scan::ScanInclusiveBody::InPortal
InPortalT InPortal
Definition: ParallelScanOpenMP.h:370
vtkm::cont::openmp::scan::ScanExclusiveBody
Definition: ParallelScanOpenMP.h:256
RuntimeDeviceInformation.h
vtkm::cont::openmp::scan::ScanInclusiveBody::Functor
FunctorType Functor
Definition: ParallelScanOpenMP.h:372
vtkm::cont::openmp::scan::ScanExclusiveBody::FunctorType
internal::WrappedBinaryOperator< ValueType, RawFunctorT > FunctorType
Definition: ParallelScanOpenMP.h:259
vtkm::cont::RuntimeDeviceInformation
A class that can be used to determine if a given device adapter is supported on the current machine a...
Definition: RuntimeDeviceInformation.h:29
vtkm::cont::openmp::scan::ChildType
ChildType
Definition: ParallelScanOpenMP.h:31
vtkm::cont::openmp::scan::Adder::LeafSize
vtkm::Id LeafSize
Definition: ParallelScanOpenMP.h:84
vtkm::cont::openmp::scan::Adder::Prepare
void Prepare(const vtkm::Id2 &range)
Definition: ParallelScanOpenMP.h:153
vtkm::TypeTraits::ZeroInitialization
static VTKM_EXEC_CONT T ZeroInitialization()
Definition: TypeTraits.h:75
vtkm::cont::openmp::scan::ScanInclusiveBody::InitializeChildNode
void InitializeChildNode(Node *, const Node *, ChildType, bool)
Definition: ParallelScanOpenMP.h:398
vtkm::cont::openmp::scan::Adder::UpdateOutput
void UpdateOutput(Node *node)
Definition: ParallelScanOpenMP.h:221
vtkm::Id2
vtkm::Vec< vtkm::Id, 2 > Id2
Id2 corresponds to a 2-dimensional index.
Definition: Types.h:885
vtkm::cont::openmp::scan::Adder::ValueType
typename ScanBody::ValueType ValueType
Definition: ParallelScanOpenMP.h:82
vtkm::Range
Represent a continuous scalar range of values.
Definition: Range.h:31