parallelTraversalTasks.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8 * See LICENSE for the license information
9 
10 * -------------------------------------------------------------------------- */
11 
17 #pragma once
18 
19 #include <gtsam/global_includes.h>
20 
21 #include <memory>
22 
23 #ifdef GTSAM_USE_TBB
24 #include <tbb/task_group.h> // tbb::task_group
25 #include <tbb/scalable_allocator.h> // tbb::scalable_allocator
26 
27 namespace gtsam {
28 
30  namespace treeTraversal {
31 
32  namespace internal {
33 
34  /* ************************************************************************* */
35  template<typename NODE, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
36  class PreOrderTask
37  {
38  public:
39  const std::shared_ptr<NODE>& treeNode;
40  std::shared_ptr<DATA> myData;
41  VISITOR_PRE& visitorPre;
42  VISITOR_POST& visitorPost;
43  int problemSizeThreshold;
44  tbb::task_group& tg;
45  bool makeNewTasks;
46 
47  // Keep track of order phase across multiple calls to the same functor
48  mutable bool isPostOrderPhase;
49 
50  PreOrderTask(const std::shared_ptr<NODE>& treeNode, const std::shared_ptr<DATA>& myData,
51  VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold,
52  tbb::task_group& tg, bool makeNewTasks = true)
53  : treeNode(treeNode),
54  myData(myData),
55  visitorPre(visitorPre),
56  visitorPost(visitorPost),
57  problemSizeThreshold(problemSizeThreshold),
58  tg(tg),
59  makeNewTasks(makeNewTasks),
60  isPostOrderPhase(false) {}
61 
62  void operator()() const
63  {
64  if(isPostOrderPhase)
65  {
66  // Run the post-order visitor since this task was recycled to run the post-order visitor
67  (void) visitorPost(treeNode, *myData);
68  }
69  else
70  {
71  if(makeNewTasks)
72  {
73  if(!treeNode->children.empty())
74  {
75  bool overThreshold = (treeNode->problemSize() >= problemSizeThreshold);
76 
77  // If we have child tasks, start subtasks and wait for them to complete
78  tbb::task_group ctg;
79  for(const std::shared_ptr<NODE>& child: treeNode->children)
80  {
81  // Process child in a subtask. Important: Run visitorPre before calling
82  // allocate_child so that if visitorPre throws an exception, we will not have
83  // allocated an extra child, this causes a TBB error.
84  std::shared_ptr<DATA> childData = std::allocate_shared<DATA>(
85  tbb::scalable_allocator<DATA>(), visitorPre(child, *myData));
86  ctg.run(PreOrderTask(child, childData, visitorPre, visitorPost,
87  problemSizeThreshold, ctg, overThreshold));
88  }
89  ctg.wait();
90 
91  // Allocate post-order task as a continuation
92  isPostOrderPhase = true;
93  tg.run(*this);
94  }
95  else
96  {
97  // Run the post-order visitor in this task if we have no children
98  (void) visitorPost(treeNode, *myData);
99  }
100  }
101  else
102  {
103  // Process this node and its children in this task
104  processNodeRecursively(treeNode, *myData);
105  }
106  }
107  }
108 
109  void processNodeRecursively(const std::shared_ptr<NODE>& node, DATA& myData) const
110  {
111  for(const std::shared_ptr<NODE>& child: node->children)
112  {
113  DATA childData = visitorPre(child, myData);
114  processNodeRecursively(child, childData);
115  }
116 
117  // Run the post-order visitor
118  (void) visitorPost(node, myData);
119  }
120  };
121 
122  /* ************************************************************************* */
123  template<typename ROOTS, typename NODE, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
124  class RootTask
125  {
126  public:
127  const ROOTS& roots;
128  DATA& myData;
129  VISITOR_PRE& visitorPre;
130  VISITOR_POST& visitorPost;
131  int problemSizeThreshold;
132  tbb::task_group& tg;
133  RootTask(const ROOTS& roots, DATA& myData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost,
134  int problemSizeThreshold, tbb::task_group& tg) :
135  roots(roots), myData(myData), visitorPre(visitorPre), visitorPost(visitorPost),
136  problemSizeThreshold(problemSizeThreshold), tg(tg) {}
137 
138  void operator()() const
139  {
140  typedef PreOrderTask<NODE, DATA, VISITOR_PRE, VISITOR_POST> PreOrderTask;
141  // Create data and tasks for our children
142  for(const std::shared_ptr<NODE>& root: roots)
143  {
144  std::shared_ptr<DATA> rootData = std::allocate_shared<DATA>(tbb::scalable_allocator<DATA>(), visitorPre(root, myData));
145  tg.run(PreOrderTask(root, rootData, visitorPre, visitorPost, problemSizeThreshold, tg));
146  }
147  }
148  };
149 
150  template<typename NODE, typename ROOTS, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
151  void CreateRootTask(const ROOTS& roots, DATA& rootData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold)
152  {
153  typedef RootTask<ROOTS, NODE, DATA, VISITOR_PRE, VISITOR_POST> RootTask;
154  tbb::task_group tg;
155  tg.run_and_wait(RootTask(roots, rootData, visitorPre, visitorPost, problemSizeThreshold, tg));
156  }
157 
158  }
159 
160  }
161 
162 }
163 
164 #endif
Included from all GTSAM files.
traits
Definition: chartTesting.h:28
const std::shared_ptr< NODE > & treeNode
internal::enable_if< internal::valid_indexed_view_overload< RowIndices, ColIndices >::value &&internal::traits< typename EIGEN_INDEXED_VIEW_METHOD_TYPE< RowIndices, ColIndices >::type >::ReturnAsIndexedView, typename EIGEN_INDEXED_VIEW_METHOD_TYPE< RowIndices, ColIndices >::type >::type operator()(const RowIndices &rowIndices, const ColIndices &colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:35:01