try fixing stack overflow issue for large tree
parent
ce7fd30da4
commit
1d06f1e766
|
@ -25,6 +25,8 @@
|
|||
#include <string>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <deque>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
@ -97,7 +99,28 @@ namespace gtsam {
|
|||
}
|
||||
|
||||
// Virtual destructor.
|
||||
virtual ~BayesTreeCliqueBase() {}
|
||||
virtual ~BayesTreeCliqueBase() {
|
||||
// default destructor will cause stack overflow for deletion of large trees
|
||||
// so we delete the tree explicitly by first BFSing the tree to determine the topological order
|
||||
// and then clearing the children of each node in topological order
|
||||
// Only work in single threaded mode
|
||||
std::queue<This*> bfs_queue;
|
||||
std::deque<This*> topological_order;
|
||||
bfs_queue.push(this);
|
||||
while (!bfs_queue.empty()) {
|
||||
auto node = bfs_queue.front();
|
||||
bfs_queue.pop();
|
||||
topological_order.push_front(node);
|
||||
for (auto& child : node->children) {
|
||||
if (child.use_count() == 1) {
|
||||
bfs_queue.push(child.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto node : topological_order) {
|
||||
node->children.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <gtsam/base/Testable.h>
|
||||
#include <gtsam/base/FastVector.h>
|
||||
#include <gtsam/inference/Ordering.h>
|
||||
|
@ -46,7 +48,8 @@ class ClusterTree {
|
|||
|
||||
Cluster() : problemSize_(0) {}
|
||||
|
||||
virtual ~Cluster() {}
|
||||
virtual ~Cluster() {
|
||||
}
|
||||
|
||||
const Cluster& operator[](size_t i) const {
|
||||
return *(children[i]);
|
||||
|
@ -164,6 +167,27 @@ class ClusterTree {
|
|||
return *(roots_[i]);
|
||||
}
|
||||
|
||||
virtual ~ClusterTree() {
|
||||
// use default destructor which recursively deletes all nodes with shared_ptr causes stack overflow.
|
||||
// so for each tree, we do a BFS to get sequence of nodes to delete, and clear their children first.
|
||||
for (auto&& root : roots_) {
|
||||
std::queue<Cluster*> q;
|
||||
std::deque<Cluster*> nodes;
|
||||
q.push(root.get());
|
||||
while (!q.empty()) {
|
||||
auto node = q.front();
|
||||
nodes.push_front(node);
|
||||
q.pop();
|
||||
for (auto&& child : node->children) {
|
||||
q.push(child.get());
|
||||
}
|
||||
}
|
||||
for (auto&& node : nodes) {
|
||||
node->children.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
|
||||
#include <gtsam/base/Testable.h>
|
||||
#include <gtsam/base/FastVector.h>
|
||||
|
@ -118,6 +120,27 @@ namespace gtsam {
|
|||
/// @}
|
||||
|
||||
public:
|
||||
~EliminationTree() {
|
||||
// default destructor will cause stack overflow for deletion of large trees
|
||||
// so we delete the tree explicitly by first BFSing the tree to determine the topological order
|
||||
// and then clearing the children of each node in topological order
|
||||
for (auto&& root : roots_) {
|
||||
std::queue<Node*> bfs_queue;
|
||||
std::deque<Node*> topological_order;
|
||||
bfs_queue.push(root.get());
|
||||
while (!bfs_queue.empty()) {
|
||||
Node* node = bfs_queue.front();
|
||||
bfs_queue.pop();
|
||||
topological_order.push_front(node);
|
||||
for (auto&& child : node->children) {
|
||||
bfs_queue.push(child.get());
|
||||
}
|
||||
}
|
||||
for (auto&& node : topological_order) {
|
||||
node->children.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
/// @name Standard Interface
|
||||
/// @{
|
||||
|
||||
|
@ -156,6 +179,7 @@ namespace gtsam {
|
|||
/** Swap the data of this tree with another one, this operation is very fast. */
|
||||
void swap(This& other);
|
||||
|
||||
|
||||
protected:
|
||||
/// Protected default constructor
|
||||
EliminationTree() {}
|
||||
|
|
Loading…
Reference in New Issue