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