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);
|
prefix_root_.reset(root);
|
||||||
prefixes_.push_back(root);
|
prefixes_.push_back(root);
|
||||||
|
|
||||||
timestep_tree_root_=std::make_shared<TimestepTreeNode>(nullptr, 0);
|
|
||||||
|
|
||||||
if (ext_scorer && (bool)(ext_scorer_->dictionary)) {
|
if (ext_scorer && (bool)(ext_scorer_->dictionary)) {
|
||||||
// no need for std::make_shared<>() since Copy() does 'new' behind the doors
|
// 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));
|
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_);
|
prefix_root_->iterate_to_vec(prefixes_);
|
||||||
if (abs_time_step_ == 0) {
|
if (abs_time_step_ == 0) {
|
||||||
for (PathTrie* prefix:prefixes_) {
|
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::shared_ptr<Scorer> ext_scorer_;
|
||||||
std::vector<PathTrie*> prefixes_;
|
std::vector<PathTrie*> prefixes_;
|
||||||
std::unique_ptr<PathTrie> prefix_root_;
|
std::unique_ptr<PathTrie> prefix_root_;
|
||||||
std::shared_ptr<TimestepTreeNode> timestep_tree_root_;
|
TimestepTreeNode timestep_tree_root_{nullptr, 0};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DecoderState() = default;
|
DecoderState() = default;
|
||||||
|
@ -175,7 +175,7 @@ void PathTrie::iterate_to_vec(std::vector<PathTrie*>& output) {
|
|||||||
timesteps = nullptr;
|
timesteps = nullptr;
|
||||||
for (auto const& child : previous_timesteps->children) {
|
for (auto const& child : previous_timesteps->children) {
|
||||||
if (child->data == new_timestep) {
|
if (child->data == new_timestep) {
|
||||||
timesteps=child;
|
timesteps = child.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,16 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
template<class DataT>
|
template<class DataT>
|
||||||
struct TreeNode{
|
struct TreeNode{
|
||||||
std::shared_ptr<TreeNode<DataT>> parent;
|
TreeNode<DataT>* parent;
|
||||||
std::vector<std::shared_ptr<TreeNode<DataT>>> children;
|
std::vector<std::unique_ptr< TreeNode<DataT>, godefv::memory::object_pool_deleter_t<TreeNode<DataT>> >> children;
|
||||||
|
|
||||||
DataT data;
|
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>
|
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>
|
template<class DataT>
|
||||||
std::vector<DataT> get_history(TreeNode<DataT>*);
|
std::vector<DataT> get_history(TreeNode<DataT>*);
|
||||||
@ -85,10 +85,10 @@ public:
|
|||||||
float score;
|
float score;
|
||||||
float approx_ctc;
|
float approx_ctc;
|
||||||
unsigned int character;
|
unsigned int character;
|
||||||
std::shared_ptr<TimestepTreeNode> timesteps;
|
TimestepTreeNode* timesteps=nullptr;
|
||||||
|
|
||||||
// timestep temporary storage for each decoding step.
|
// timestep temporary storage for each decoding step.
|
||||||
std::shared_ptr<TimestepTreeNode> previous_timesteps=nullptr;
|
TimestepTreeNode* previous_timesteps=nullptr;
|
||||||
unsigned int new_timestep;
|
unsigned int new_timestep;
|
||||||
|
|
||||||
PathTrie* parent;
|
PathTrie* parent;
|
||||||
@ -108,21 +108,21 @@ private:
|
|||||||
|
|
||||||
// TreeNode implementation
|
// TreeNode implementation
|
||||||
template<class NodeDataT, class ChildDataT>
|
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;
|
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_)));
|
node->children.push_back(tree_node_pool.make_unique(node, std::forward<ChildDataT>(data_)));
|
||||||
return node->children.back();
|
return node->children.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class DataT>
|
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;
|
if(tree_node==nullptr) return;
|
||||||
assert(tree_node->parent != tree_node);
|
assert(tree_node->parent != tree_node);
|
||||||
get_history_helper(tree_node->parent, output);
|
get_history_helper(tree_node->parent, output);
|
||||||
output->push_back(tree_node->data);
|
output->push_back(tree_node->data);
|
||||||
}
|
}
|
||||||
template<class DataT>
|
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;
|
std::vector<DataT> output;
|
||||||
get_history_helper(tree_node, &output);
|
get_history_helper(tree_node, &output);
|
||||||
return output;
|
return output;
|
||||||
|
@ -8,9 +8,29 @@
|
|||||||
|
|
||||||
namespace godefv{ namespace memory{
|
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).
|
//! 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.
|
//! 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{
|
class object_pool_t{
|
||||||
//! An object slot is an uninitialized memory space of the same size as Object.
|
//! 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.
|
//! 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_begin;
|
||||||
object_slot_t* free_object_slots_end;
|
object_slot_t* free_object_slots_end;
|
||||||
|
|
||||||
//! Custom deleter to recycle the deleted pointers.
|
void delete_object(Object* object_ptr){
|
||||||
struct deleter_t{
|
object_ptr->~Object();
|
||||||
private:
|
recycled_object_slots.push_back(reinterpret_cast<object_slot_t*>(object_ptr));
|
||||||
object_pool_t<Object, Allocator, ChunkSize>* object_pool_ptr;
|
}
|
||||||
public:
|
friend object_pool_deleter_t<Object, Allocator, ChunkSize>;
|
||||||
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));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using object_t = Object;
|
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.
|
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>{}) :
|
object_pool_t(Allocator<chunk_t> const& allocator = Allocator<chunk_t>{}) :
|
||||||
|
Loading…
Reference in New Issue
Block a user