diff --git a/native_client/ctcdecode/ctc_beam_search_decoder.cpp b/native_client/ctcdecode/ctc_beam_search_decoder.cpp index f317b0ec..7efaaaa1 100644 --- a/native_client/ctcdecode/ctc_beam_search_decoder.cpp +++ b/native_client/ctcdecode/ctc_beam_search_decoder.cpp @@ -37,8 +37,6 @@ DecoderState::init(const Alphabet& alphabet, prefix_root_.reset(root); prefixes_.push_back(root); - timestep_tree_root_=std::make_shared(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(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_; } } diff --git a/native_client/ctcdecode/ctc_beam_search_decoder.h b/native_client/ctcdecode/ctc_beam_search_decoder.h index e8324f5e..65e7497d 100644 --- a/native_client/ctcdecode/ctc_beam_search_decoder.h +++ b/native_client/ctcdecode/ctc_beam_search_decoder.h @@ -21,7 +21,7 @@ class DecoderState { std::shared_ptr ext_scorer_; std::vector prefixes_; std::unique_ptr prefix_root_; - std::shared_ptr timestep_tree_root_; + TimestepTreeNode timestep_tree_root_{nullptr, 0}; public: DecoderState() = default; diff --git a/native_client/ctcdecode/path_trie.cpp b/native_client/ctcdecode/path_trie.cpp index 3f9ab91f..2b572fa8 100644 --- a/native_client/ctcdecode/path_trie.cpp +++ b/native_client/ctcdecode/path_trie.cpp @@ -175,7 +175,7 @@ void PathTrie::iterate_to_vec(std::vector& output) { timesteps = nullptr; for (auto const& child : previous_timesteps->children) { if (child->data == new_timestep) { - timesteps=child; + timesteps = child.get(); break; } } diff --git a/native_client/ctcdecode/path_trie.h b/native_client/ctcdecode/path_trie.h index 20060a3e..4c8c82b3 100644 --- a/native_client/ctcdecode/path_trie.h +++ b/native_client/ctcdecode/path_trie.h @@ -16,16 +16,16 @@ */ template struct TreeNode{ - std::shared_ptr> parent; - std::vector>> children; + TreeNode* parent; + std::vector, godefv::memory::object_pool_deleter_t> >> children; DataT data; - TreeNode(std::shared_ptr> const& parent_, DataT const& data_): parent{parent_}, data{data_} {} + TreeNode(TreeNode* parent_, DataT const& data_): parent{parent_}, data{data_} {} }; template -std::shared_ptr> add_child(std::shared_ptr> const& node, ChildDataT&& data_); +TreeNode* add_child(TreeNode* node, ChildDataT&& data_); template std::vector get_history(TreeNode*); @@ -85,10 +85,10 @@ public: float score; float approx_ctc; unsigned int character; - std::shared_ptr timesteps; + TimestepTreeNode* timesteps=nullptr; // timestep temporary storage for each decoding step. - std::shared_ptr previous_timesteps=nullptr; + TimestepTreeNode* previous_timesteps=nullptr; unsigned int new_timestep; PathTrie* parent; @@ -108,21 +108,21 @@ private: // TreeNode implementation template -std::shared_ptr> add_child(std::shared_ptr> const& node, ChildDataT&& data_){ +TreeNode* add_child(TreeNode* node, ChildDataT&& data_){ static godefv::memory::object_pool_t> tree_node_pool; - node->children.emplace_back(tree_node_pool.make_unique(node, std::forward(data_))); - return node->children.back(); + node->children.push_back(tree_node_pool.make_unique(node, std::forward(data_))); + return node->children.back().get(); } template -void get_history_helper(std::shared_ptr> const& tree_node, std::vector* output){ +void get_history_helper(TreeNode* tree_node, std::vector* 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 -std::vector get_history(std::shared_ptr> const& tree_node){ +std::vector get_history(TreeNode* tree_node){ std::vector output; get_history_helper(tree_node, &output); return output; diff --git a/native_client/ctcdecode/third_party/object_pool/object_pool.h b/native_client/ctcdecode/third_party/object_pool/object_pool.h index 0c0a3287..e91a4f51 100755 --- a/native_client/ctcdecode/third_party/object_pool/object_pool.h +++ b/native_client/ctcdecode/third_party/object_pool/object_pool.h @@ -8,9 +8,29 @@ namespace godefv{ namespace memory{ +template class Allocator = std::allocator, std::size_t ChunkSize = 1024> +class object_pool_t; + +//! Custom deleter to recycle the deleted pointers. +template class Allocator = std::allocator, std::size_t ChunkSize = 1024> +struct object_pool_deleter_t{ +private: + object_pool_t* 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 Allocator = std::allocator, std::size_t ChunkSize = 1024> +template 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_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_ptr)); - } - }; + void delete_object(Object* object_ptr){ + object_ptr->~Object(); + recycled_object_slots.push_back(reinterpret_cast(object_ptr)); + } + friend object_pool_deleter_t; public: using object_t = Object; + using deleter_t = object_pool_deleter_t; using object_unique_ptr_t = std::unique_ptr; //!< The type returned by the object pool. object_pool_t(Allocator const& allocator = Allocator{}) :