Merge pull request #823 from acxz/revert-800-fix/tbb-deprecation
Revert "replace deprecated tbb functionality"release/4.3a0
commit
fda659674e
|
@ -158,8 +158,9 @@ void DepthFirstForestParallel(FOREST& forest, DATA& rootData,
|
||||||
// Typedefs
|
// Typedefs
|
||||||
typedef typename FOREST::Node Node;
|
typedef typename FOREST::Node Node;
|
||||||
|
|
||||||
internal::CreateRootTask<Node>(forest.roots(), rootData, visitorPre,
|
tbb::task::spawn_root_and_wait(
|
||||||
visitorPost, problemSizeThreshold);
|
internal::CreateRootTask<Node>(forest.roots(), rootData, visitorPre,
|
||||||
|
visitorPost, problemSizeThreshold));
|
||||||
#else
|
#else
|
||||||
DepthFirstForest(forest, rootData, visitorPre, visitorPost);
|
DepthFirstForest(forest, rootData, visitorPre, visitorPost);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
#ifdef GTSAM_USE_TBB
|
#ifdef GTSAM_USE_TBB
|
||||||
#include <tbb/task_group.h> // tbb::task_group
|
#include <tbb/task.h> // tbb::task, tbb::task_list
|
||||||
#include <tbb/scalable_allocator.h> // tbb::scalable_allocator
|
#include <tbb/scalable_allocator.h> // tbb::scalable_allocator
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
@ -34,7 +34,7 @@ namespace gtsam {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<typename NODE, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
template<typename NODE, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
||||||
class PreOrderTask
|
class PreOrderTask : public tbb::task
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const boost::shared_ptr<NODE>& treeNode;
|
const boost::shared_ptr<NODE>& treeNode;
|
||||||
|
@ -42,30 +42,28 @@ namespace gtsam {
|
||||||
VISITOR_PRE& visitorPre;
|
VISITOR_PRE& visitorPre;
|
||||||
VISITOR_POST& visitorPost;
|
VISITOR_POST& visitorPost;
|
||||||
int problemSizeThreshold;
|
int problemSizeThreshold;
|
||||||
tbb::task_group& tg;
|
|
||||||
bool makeNewTasks;
|
bool makeNewTasks;
|
||||||
|
|
||||||
// Keep track of order phase across multiple calls to the same functor
|
bool isPostOrderPhase;
|
||||||
mutable bool isPostOrderPhase;
|
|
||||||
|
|
||||||
PreOrderTask(const boost::shared_ptr<NODE>& treeNode, const boost::shared_ptr<DATA>& myData,
|
PreOrderTask(const boost::shared_ptr<NODE>& treeNode, const boost::shared_ptr<DATA>& myData,
|
||||||
VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold,
|
VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold,
|
||||||
tbb::task_group& tg, bool makeNewTasks = true)
|
bool makeNewTasks = true)
|
||||||
: treeNode(treeNode),
|
: treeNode(treeNode),
|
||||||
myData(myData),
|
myData(myData),
|
||||||
visitorPre(visitorPre),
|
visitorPre(visitorPre),
|
||||||
visitorPost(visitorPost),
|
visitorPost(visitorPost),
|
||||||
problemSizeThreshold(problemSizeThreshold),
|
problemSizeThreshold(problemSizeThreshold),
|
||||||
tg(tg),
|
|
||||||
makeNewTasks(makeNewTasks),
|
makeNewTasks(makeNewTasks),
|
||||||
isPostOrderPhase(false) {}
|
isPostOrderPhase(false) {}
|
||||||
|
|
||||||
void operator()() const
|
tbb::task* execute() override
|
||||||
{
|
{
|
||||||
if(isPostOrderPhase)
|
if(isPostOrderPhase)
|
||||||
{
|
{
|
||||||
// Run the post-order visitor since this task was recycled to run the post-order visitor
|
// Run the post-order visitor since this task was recycled to run the post-order visitor
|
||||||
(void) visitorPost(treeNode, *myData);
|
(void) visitorPost(treeNode, *myData);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -73,10 +71,14 @@ namespace gtsam {
|
||||||
{
|
{
|
||||||
if(!treeNode->children.empty())
|
if(!treeNode->children.empty())
|
||||||
{
|
{
|
||||||
|
// Allocate post-order task as a continuation
|
||||||
|
isPostOrderPhase = true;
|
||||||
|
recycle_as_continuation();
|
||||||
|
|
||||||
bool overThreshold = (treeNode->problemSize() >= problemSizeThreshold);
|
bool overThreshold = (treeNode->problemSize() >= problemSizeThreshold);
|
||||||
|
|
||||||
// If we have child tasks, start subtasks and wait for them to complete
|
tbb::task* firstChild = 0;
|
||||||
tbb::task_group ctg;
|
tbb::task_list childTasks;
|
||||||
for(const boost::shared_ptr<NODE>& child: treeNode->children)
|
for(const boost::shared_ptr<NODE>& child: treeNode->children)
|
||||||
{
|
{
|
||||||
// Process child in a subtask. Important: Run visitorPre before calling
|
// Process child in a subtask. Important: Run visitorPre before calling
|
||||||
|
@ -84,30 +86,37 @@ namespace gtsam {
|
||||||
// allocated an extra child, this causes a TBB error.
|
// allocated an extra child, this causes a TBB error.
|
||||||
boost::shared_ptr<DATA> childData = boost::allocate_shared<DATA>(
|
boost::shared_ptr<DATA> childData = boost::allocate_shared<DATA>(
|
||||||
tbb::scalable_allocator<DATA>(), visitorPre(child, *myData));
|
tbb::scalable_allocator<DATA>(), visitorPre(child, *myData));
|
||||||
ctg.run(PreOrderTask(child, childData, visitorPre, visitorPost,
|
tbb::task* childTask =
|
||||||
problemSizeThreshold, ctg, overThreshold));
|
new (allocate_child()) PreOrderTask(child, childData, visitorPre, visitorPost,
|
||||||
|
problemSizeThreshold, overThreshold);
|
||||||
|
if (firstChild)
|
||||||
|
childTasks.push_back(*childTask);
|
||||||
|
else
|
||||||
|
firstChild = childTask;
|
||||||
}
|
}
|
||||||
ctg.wait();
|
|
||||||
|
|
||||||
// Allocate post-order task as a continuation
|
// If we have child tasks, start subtasks and wait for them to complete
|
||||||
isPostOrderPhase = true;
|
set_ref_count((int)treeNode->children.size());
|
||||||
tg.run(*this);
|
spawn(childTasks);
|
||||||
|
return firstChild;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Run the post-order visitor in this task if we have no children
|
// Run the post-order visitor in this task if we have no children
|
||||||
(void) visitorPost(treeNode, *myData);
|
(void) visitorPost(treeNode, *myData);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Process this node and its children in this task
|
// Process this node and its children in this task
|
||||||
processNodeRecursively(treeNode, *myData);
|
processNodeRecursively(treeNode, *myData);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void processNodeRecursively(const boost::shared_ptr<NODE>& node, DATA& myData) const
|
void processNodeRecursively(const boost::shared_ptr<NODE>& node, DATA& myData)
|
||||||
{
|
{
|
||||||
for(const boost::shared_ptr<NODE>& child: node->children)
|
for(const boost::shared_ptr<NODE>& child: node->children)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +131,7 @@ namespace gtsam {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<typename ROOTS, typename NODE, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
template<typename ROOTS, typename NODE, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
||||||
class RootTask
|
class RootTask : public tbb::task
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const ROOTS& roots;
|
const ROOTS& roots;
|
||||||
|
@ -130,31 +139,38 @@ namespace gtsam {
|
||||||
VISITOR_PRE& visitorPre;
|
VISITOR_PRE& visitorPre;
|
||||||
VISITOR_POST& visitorPost;
|
VISITOR_POST& visitorPost;
|
||||||
int problemSizeThreshold;
|
int problemSizeThreshold;
|
||||||
tbb::task_group& tg;
|
|
||||||
RootTask(const ROOTS& roots, DATA& myData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost,
|
RootTask(const ROOTS& roots, DATA& myData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost,
|
||||||
int problemSizeThreshold, tbb::task_group& tg) :
|
int problemSizeThreshold) :
|
||||||
roots(roots), myData(myData), visitorPre(visitorPre), visitorPost(visitorPost),
|
roots(roots), myData(myData), visitorPre(visitorPre), visitorPost(visitorPost),
|
||||||
problemSizeThreshold(problemSizeThreshold), tg(tg) {}
|
problemSizeThreshold(problemSizeThreshold) {}
|
||||||
|
|
||||||
void operator()() const
|
tbb::task* execute() override
|
||||||
{
|
{
|
||||||
typedef PreOrderTask<NODE, DATA, VISITOR_PRE, VISITOR_POST> PreOrderTask;
|
typedef PreOrderTask<NODE, DATA, VISITOR_PRE, VISITOR_POST> PreOrderTask;
|
||||||
// Create data and tasks for our children
|
// Create data and tasks for our children
|
||||||
|
tbb::task_list tasks;
|
||||||
for(const boost::shared_ptr<NODE>& root: roots)
|
for(const boost::shared_ptr<NODE>& root: roots)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<DATA> rootData = boost::allocate_shared<DATA>(tbb::scalable_allocator<DATA>(), visitorPre(root, myData));
|
boost::shared_ptr<DATA> rootData = boost::allocate_shared<DATA>(tbb::scalable_allocator<DATA>(), visitorPre(root, myData));
|
||||||
tg.run(PreOrderTask(root, rootData, visitorPre, visitorPost, problemSizeThreshold, tg));
|
tasks.push_back(*new(allocate_child())
|
||||||
|
PreOrderTask(root, rootData, visitorPre, visitorPost, problemSizeThreshold));
|
||||||
}
|
}
|
||||||
|
// Set TBB ref count
|
||||||
|
set_ref_count(1 + (int) roots.size());
|
||||||
|
// Spawn tasks
|
||||||
|
spawn_and_wait_for_all(tasks);
|
||||||
|
// Return nullptr
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename NODE, typename ROOTS, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
template<typename NODE, typename ROOTS, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
||||||
void CreateRootTask(const ROOTS& roots, DATA& rootData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold)
|
RootTask<ROOTS, NODE, DATA, VISITOR_PRE, VISITOR_POST>&
|
||||||
|
CreateRootTask(const ROOTS& roots, DATA& rootData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold)
|
||||||
{
|
{
|
||||||
typedef RootTask<ROOTS, NODE, DATA, VISITOR_PRE, VISITOR_POST> RootTask;
|
typedef RootTask<ROOTS, NODE, DATA, VISITOR_PRE, VISITOR_POST> RootTask;
|
||||||
tbb::task_group tg;
|
return *new(tbb::task::allocate_root()) RootTask(roots, rootData, visitorPre, visitorPost, problemSizeThreshold);
|
||||||
tg.run_and_wait(RootTask(roots, rootData, visitorPre, visitorPost, problemSizeThreshold, tg));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue