PR #3279 - use unique_ptr instead of shared_ptr in the timestep tree
This commit is contained in:
parent
3a49344ccb
commit
f07c10452b
@ -37,8 +37,6 @@ DecoderState::init(const Alphabet& alphabet,
|
||||
prefix_root_.reset(root);
|
||||
prefixes_.push_back(root);
|
||||
|
||||
timestep_tree_root_=std::make_shared<TimestepTreeNode>(nullptr, 0);
|
||||
|
||||
if (ext_scorer && (bool)(ext_scorer_->dictionary)) {
|
||||
// no need for std::make_shared<>() since Copy() does 'new' behind the doors
|
||||
auto dict_ptr = std::shared_ptr<PathTrie::FstType>(ext_scorer->dictionary->Copy(true));
|
||||
@ -183,7 +181,7 @@ DecoderState::next(const double *probs,
|
||||
prefix_root_->iterate_to_vec(prefixes_);
|
||||
if (abs_time_step_ == 0) {
|
||||
for (PathTrie* prefix:prefixes_) {
|
||||
prefix->timesteps = timestep_tree_root_;
|
||||
prefix->timesteps = ×tep_tree_root_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ class DecoderState {
|
||||
std::shared_ptr<Scorer> ext_scorer_;
|
||||
std::vector<PathTrie*> prefixes_;
|
||||
std::unique_ptr<PathTrie> prefix_root_;
|
||||
std::shared_ptr<TimestepTreeNode> timestep_tree_root_;
|
||||
TimestepTreeNode timestep_tree_root_{nullptr, 0};
|
||||
|
||||
public:
|
||||
DecoderState() = default;
|
||||
|
@ -175,7 +175,7 @@ void PathTrie::iterate_to_vec(std::vector<PathTrie*>& output) {
|
||||
timesteps = nullptr;
|
||||
for (auto const& child : previous_timesteps->children) {
|
||||
if (child->data == new_timestep) {
|
||||
timesteps=child;
|
||||
timesteps = child.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -16,16 +16,16 @@
|
||||
*/
|
||||
template<class DataT>
|
||||
struct TreeNode{
|
||||
std::shared_ptr<TreeNode<DataT>> parent;
|
||||
std::vector<std::shared_ptr<TreeNode<DataT>>> children;
|
||||
TreeNode<DataT>* parent;
|
||||
std::vector<std::unique_ptr< TreeNode<DataT>, godefv::memory::object_pool_deleter_t<TreeNode<DataT>> >> children;
|
||||
|
||||
DataT data;
|
||||
|
||||
TreeNode(std::shared_ptr<TreeNode<DataT>> const& parent_, DataT const& data_): parent{parent_}, data{data_} {}
|
||||
TreeNode(TreeNode<DataT>* parent_, DataT const& data_): parent{parent_}, data{data_} {}
|
||||
};
|
||||
|
||||
template<class NodeDataT, class ChildDataT>
|
||||
std::shared_ptr<TreeNode<NodeDataT>> add_child(std::shared_ptr<TreeNode<NodeDataT>> const& node, ChildDataT&& data_);
|
||||
TreeNode<NodeDataT>* add_child(TreeNode<NodeDataT>* node, ChildDataT&& data_);
|
||||
|
||||
template<class DataT>
|
||||
std::vector<DataT> get_history(TreeNode<DataT>*);
|
||||
@ -85,10 +85,10 @@ public:
|
||||
float score;
|
||||
float approx_ctc;
|
||||
unsigned int character;
|
||||
std::shared_ptr<TimestepTreeNode> timesteps;
|
||||
TimestepTreeNode* timesteps=nullptr;
|
||||
|
||||
// timestep temporary storage for each decoding step.
|
||||
std::shared_ptr<TimestepTreeNode> previous_timesteps=nullptr;
|
||||
TimestepTreeNode* previous_timesteps=nullptr;
|
||||
unsigned int new_timestep;
|
||||
|
||||
PathTrie* parent;
|
||||
@ -108,21 +108,21 @@ private:
|
||||
|
||||
// TreeNode implementation
|
||||
template<class NodeDataT, class ChildDataT>
|
||||
std::shared_ptr<TreeNode<NodeDataT>> add_child(std::shared_ptr<TreeNode<NodeDataT>> const& node, ChildDataT&& data_){
|
||||
TreeNode<NodeDataT>* add_child(TreeNode<NodeDataT>* node, ChildDataT&& data_){
|
||||
static godefv::memory::object_pool_t<TreeNode<NodeDataT>> tree_node_pool;
|
||||
node->children.emplace_back(tree_node_pool.make_unique(node, std::forward<ChildDataT>(data_)));
|
||||
return node->children.back();
|
||||
node->children.push_back(tree_node_pool.make_unique(node, std::forward<ChildDataT>(data_)));
|
||||
return node->children.back().get();
|
||||
}
|
||||
|
||||
template<class DataT>
|
||||
void get_history_helper(std::shared_ptr<TreeNode<DataT>> const& tree_node, std::vector<DataT>* output){
|
||||
void get_history_helper(TreeNode<DataT>* tree_node, std::vector<DataT>* output){
|
||||
if(tree_node==nullptr) return;
|
||||
assert(tree_node->parent != tree_node);
|
||||
get_history_helper(tree_node->parent, output);
|
||||
output->push_back(tree_node->data);
|
||||
}
|
||||
template<class DataT>
|
||||
std::vector<DataT> get_history(std::shared_ptr<TreeNode<DataT>> const& tree_node){
|
||||
std::vector<DataT> get_history(TreeNode<DataT>* tree_node){
|
||||
std::vector<DataT> output;
|
||||
get_history_helper(tree_node, &output);
|
||||
return output;
|
||||
|
@ -8,9 +8,29 @@
|
||||
|
||||
namespace godefv{ namespace memory{
|
||||
|
||||
template<class Object, template<class T> class Allocator = std::allocator, std::size_t ChunkSize = 1024>
|
||||
class object_pool_t;
|
||||
|
||||
//! Custom deleter to recycle the deleted pointers.
|
||||
template<class Object, template<class T> class Allocator = std::allocator, std::size_t ChunkSize = 1024>
|
||||
struct object_pool_deleter_t{
|
||||
private:
|
||||
object_pool_t<Object, Allocator, ChunkSize>* object_pool_ptr;
|
||||
public:
|
||||
explicit object_pool_deleter_t(decltype(object_pool_ptr) input_object_pool_ptr) :
|
||||
object_pool_ptr(input_object_pool_ptr)
|
||||
{}
|
||||
|
||||
//! When a pointer provided by the ObjectPool is deleted, its memory is converted to an object slot to be recycled.
|
||||
void operator()(Object* object_ptr)
|
||||
{
|
||||
object_pool_ptr->delete_object(object_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
//! Allocates instances of Object efficiently (constant time and log((maximum number of Objects used at the same time)/ChunkSize) calls to malloc in the whole lifetime of the object pool).
|
||||
//! When an instance returned by the object pool is destroyed, its allocated memory is recycled by the object pool. Defragmenting the object pool to free memory is not possible.
|
||||
template<class Object, template<class T> class Allocator = std::allocator, std::size_t ChunkSize = 1024>
|
||||
template<class Object, template<class T> class Allocator, std::size_t ChunkSize>
|
||||
class object_pool_t{
|
||||
//! An object slot is an uninitialized memory space of the same size as Object.
|
||||
//! It is initially "free". It can then be "used" to construct an Object in place and the pointer to it is returned by the object pool. When the pointer is destroyed, the object slot is "recycled" and can be used again but it is not "free" anymore because "free" object slots are contiguous in memory.
|
||||
@ -28,25 +48,15 @@ class object_pool_t{
|
||||
object_slot_t* free_object_slots_begin;
|
||||
object_slot_t* free_object_slots_end;
|
||||
|
||||
//! Custom deleter to recycle the deleted pointers.
|
||||
struct deleter_t{
|
||||
private:
|
||||
object_pool_t<Object, Allocator, ChunkSize>* object_pool_ptr;
|
||||
public:
|
||||
explicit deleter_t(decltype(object_pool_ptr) input_object_pool_ptr) :
|
||||
object_pool_ptr(input_object_pool_ptr)
|
||||
{}
|
||||
|
||||
//! When a pointer provided by the ObjectPool is deleted, its memory is converted to an object slot to be recycled.
|
||||
void operator()(Object* object_ptr)
|
||||
{
|
||||
object_ptr->~Object();
|
||||
object_pool_ptr->recycled_object_slots.push_back(reinterpret_cast<object_slot_t*>(object_ptr));
|
||||
}
|
||||
};
|
||||
void delete_object(Object* object_ptr){
|
||||
object_ptr->~Object();
|
||||
recycled_object_slots.push_back(reinterpret_cast<object_slot_t*>(object_ptr));
|
||||
}
|
||||
friend object_pool_deleter_t<Object, Allocator, ChunkSize>;
|
||||
|
||||
public:
|
||||
using object_t = Object;
|
||||
using deleter_t = object_pool_deleter_t<Object, Allocator, ChunkSize>;
|
||||
using object_unique_ptr_t = std::unique_ptr<object_t, deleter_t>; //!< The type returned by the object pool.
|
||||
|
||||
object_pool_t(Allocator<chunk_t> const& allocator = Allocator<chunk_t>{}) :
|
||||
|
Loading…
Reference in New Issue
Block a user