diff --git a/paddle/operators/recurrent_network_op.cc b/paddle/operators/recurrent_network_op.cc index b21a21c6e91466324b4bcbb980335551430ee964..dcb1ac19d2cb197bb54783e90c891fbd98c99e1a 100644 --- a/paddle/operators/recurrent_network_op.cc +++ b/paddle/operators/recurrent_network_op.cc @@ -30,11 +30,14 @@ namespace rnn { void SegmentInputs(std::vector>& step_scopes, const std::vector& inlinks, const size_t seq_len, - bool infer_shape) { + bool infer_shape_mode) { PADDLE_ENFORCE(!inlinks.empty(), "no in links are provided."); for (size_t i = 0; i < inlinks.size(); ++i) { - Tensor* input = - step_scopes[0]->GetVariable(inlinks[i].external)->GetMutable(); + auto input_var = step_scopes[0]->GetVariable(inlinks[i].external); + PADDLE_ENFORCE(input_var != nullptr, + "input link [%s] is not in scope.", + inlinks[i].external); + Tensor* input = input_var->GetMutable(); DDim dims = input->dims(); PADDLE_ENFORCE(static_cast(dims[0]) == seq_len, "all the inlinks must have same length"); @@ -43,7 +46,7 @@ void SegmentInputs(std::vector>& step_scopes, Tensor* step_input = step_scopes[j] ->CreateVariable(inlinks[i].internal) ->GetMutable(); - if (!infer_shape) { + if (!infer_shape_mode) { *step_input = input->Slice(j, j + 1); } step_input->Resize(step_dims); @@ -54,12 +57,14 @@ void SegmentInputs(std::vector>& step_scopes, void ConcatOutputs(std::vector>& step_scopes, const std::vector& outlinks, const size_t seq_len, - bool infer_shape) { + bool infer_shape_mode) { for (size_t i = 0; i < outlinks.size(); i++) { + PADDLE_ENFORCE(step_scopes[0]->HasVariable(outlinks[i].external), + "output link [%s] is not in scope.", + outlinks[i].external); Tensor* output = step_scopes[0]->GetVariable(outlinks[i].external)->GetMutable(); - - if (infer_shape) { + if (infer_shape_mode) { DDim step_dims = step_scopes[0] ->GetVariable(outlinks[i].internal) ->GetMutable() @@ -69,16 +74,15 @@ void ConcatOutputs(std::vector>& step_scopes, output->Resize(make_ddim(dims_vec)); } else { output->mutable_data(platform::CPUPlace()); - } - - for (size_t j = 0; j < seq_len; j++) { - Tensor* step_output = step_scopes[j] - ->GetVariable(outlinks[i].internal) - ->GetMutable(); - // TODO(luotao02) data type and platform::DeviceContext() should set - // correctly - (output->Slice(j, j + 1)) - .CopyFrom(*step_output, platform::CPUPlace()); + for (size_t j = 0; j < seq_len; j++) { + Tensor* step_output = step_scopes[j] + ->GetVariable(outlinks[i].internal) + ->GetMutable(); + // TODO(luotao02) data type and platform::DeviceContext() should set + // correctly + (output->Slice(j, j + 1)) + .CopyFrom(*step_output, platform::CPUPlace()); + } } } } @@ -87,7 +91,7 @@ void LinkMemories(std::vector>& scopes, const std::vector& memories, const size_t step_id, const int offset, - bool infer_shape) { + bool infer_shape_mode) { PADDLE_ENFORCE(step_id < scopes.size(), "step [%d] is out of range of step scopes' size [%d]", step_id, @@ -107,7 +111,7 @@ void LinkMemories(std::vector>& scopes, auto mem = scope->GetVariable(attr.pre_var)->GetMutable(); // maybe share variable is better? auto linked_mem = linked_scope->GetVariable(attr.var)->GetMutable(); - if (infer_shape) { + if (infer_shape_mode) { mem->Resize(linked_mem->dims()); } else { mem->ShareDataWith(*linked_mem); @@ -179,43 +183,39 @@ void RecurrentAlgorithm::InferShape(const std::shared_ptr& scope) const { ->GetMutable() ->dims()[0]; CreateScopes(scope); - auto step_scopes = GetStepScopes(scope); - rnn::SegmentInputs(step_scopes, arg_->inlinks, seq_len_, true); - - InitMemories(step_scopes[0], true); - - PADDLE_ENFORCE(scope->HasVariable(arg_->step_net), - "stepnet [%s] is not in scope.", - arg_->step_net); + rnn::SegmentInputs( + step_scopes, arg_->inlinks, seq_len_, true /*infer_shape_mode*/); + InitMemories(step_scopes[0], true /*infer_shape_mode*/); Variable* net = scope->GetVariable(arg_->step_net); PADDLE_ENFORCE(net != nullptr, "failed to get step net"); for (size_t i = 0; i < seq_len_; i++) { if (i > 0) { - rnn::LinkMemories(step_scopes, arg_->memories, i, -1, true); + rnn::LinkMemories( + step_scopes, arg_->memories, i, -1, true /*infer_shape_mode*/); } net->GetMutable()->InferShape(step_scopes[i]); } - rnn::ConcatOutputs(step_scopes, arg_->outlinks, seq_len_, true); + rnn::ConcatOutputs( + step_scopes, arg_->outlinks, seq_len_, true /*infer_shape_mode*/); } void RecurrentAlgorithm::Run(const std::shared_ptr& scope, const platform::DeviceContext& dev_ctx) const { auto step_scopes = GetStepScopes(scope); - - rnn::SegmentInputs(step_scopes, arg_->inlinks, seq_len_, false); - - InitMemories(step_scopes[0], false); - + rnn::SegmentInputs( + step_scopes, arg_->inlinks, seq_len_, false /*infer_shape_mode*/); + InitMemories(step_scopes[0], false /*infer_shape_mode*/); Variable* net = scope->GetVariable(arg_->step_net); for (size_t step_id = 0; step_id < seq_len_; step_id++) { if (step_id > 0) { - rnn::LinkMemories(step_scopes, arg_->memories, step_id, -1, false); + rnn::LinkMemories( + step_scopes, arg_->memories, step_id, -1, false /*infer_shape_mode*/); } net->GetMutable()->Run(step_scopes[step_id], dev_ctx); } - - rnn::ConcatOutputs(step_scopes, arg_->outlinks, seq_len_, false); + rnn::ConcatOutputs( + step_scopes, arg_->outlinks, seq_len_, false /*infer_shape_mode*/); } void RecurrentAlgorithm::CreateScopes(std::shared_ptr scope) const { @@ -227,7 +227,6 @@ void RecurrentAlgorithm::CreateScopes(std::shared_ptr scope) const { if (seq_len_ > step_scopes->size()) { for (size_t i = step_scopes->size(); i < seq_len_; ++i) { std::shared_ptr step_scope = std::make_shared(scope); - // Now all variables in scope must be created outside of op. auto net_op = scope->GetVariable(arg_->step_net)->GetMutable(); for (auto& input : net_op->inputs_) { @@ -237,14 +236,13 @@ void RecurrentAlgorithm::CreateScopes(std::shared_ptr scope) const { for (auto& output : net_op->outputs_) { step_scope->CreateVariable(output); } - step_scopes->push_back(std::make_shared(step_scope)); } } } void RecurrentAlgorithm::InitMemories(std::shared_ptr step_scope, - bool infer_shape) const { + bool infer_shape_mode) const { for (auto& attr : arg_->memories) { Tensor* pre_mem = step_scope->CreateVariable(attr.pre_var)->GetMutable(); @@ -254,7 +252,7 @@ void RecurrentAlgorithm::InitMemories(std::shared_ptr step_scope, attr.boot_var); Tensor* boot_mem = step_scope->GetVariable(attr.boot_var)->GetMutable(); - if (infer_shape) { + if (infer_shape_mode) { pre_mem->Resize(boot_mem->dims()); } else { pre_mem->ShareDataWith(*boot_mem); @@ -320,23 +318,23 @@ void RecurrentGradientAlgorithm::Run( const std::shared_ptr& scope, const platform::DeviceContext& dev_ctx) const { auto step_scopes = GetStepScopes(scope); - rnn::SegmentInputs(step_scopes, arg_->inlinks, seq_len_, false); - PADDLE_ENFORCE(scope->HasVariable(arg_->step_net), - "step net is not in scope."); + rnn::SegmentInputs( + step_scopes, arg_->inlinks, seq_len_, false /*infer_shape_mode*/); Variable* net = scope->GetVariable(arg_->step_net); - PADDLE_ENFORCE(net != nullptr, "failed to get step net"); for (int step_id = seq_len_ - 1; step_id >= 0; --step_id) { if (static_cast(step_id) != seq_len_ - 1) { - rnn::LinkMemories(step_scopes, arg_->memories, step_id, 1, false); + rnn::LinkMemories( + step_scopes, arg_->memories, step_id, 1, false /*infer_shape_mode*/); } net->GetMutable()->Run(step_scopes[step_id], dev_ctx); } LinkBootMemoryGradients(step_scopes[0], false); - rnn::ConcatOutputs(step_scopes, arg_->outlinks, seq_len_, false); + rnn::ConcatOutputs( + step_scopes, arg_->outlinks, seq_len_, false /*infer_shape_mode*/); } void RecurrentGradientAlgorithm::LinkBootMemoryGradients( - std::shared_ptr step_scope, bool infer_shape) const { + std::shared_ptr step_scope, bool infer_shape_mode) const { for (auto& attr : arg_->memories) { Tensor* mem_grad = step_scope->CreateVariable(attr.var)->GetMutable(); @@ -346,7 +344,7 @@ void RecurrentGradientAlgorithm::LinkBootMemoryGradients( attr.boot_var); Tensor* boot_mem_grad = step_scope->CreateVariable(attr.boot_var)->GetMutable(); - if (infer_shape) { + if (infer_shape_mode) { boot_mem_grad->Resize(mem_grad->dims()); } else { boot_mem_grad->ShareDataWith(*mem_grad); @@ -360,21 +358,20 @@ void RecurrentGradientAlgorithm::InferShape( ->GetMutable() ->dims()[0]; auto step_scopes = GetStepScopes(scope); - rnn::SegmentInputs(step_scopes, arg_->inlinks, seq_len_, true); - - PADDLE_ENFORCE(scope->HasVariable(arg_->step_net), - "step net is not in scope."); + rnn::SegmentInputs( + step_scopes, arg_->inlinks, seq_len_, true /*infer_shape_mode*/); Variable* net = scope->GetVariable(arg_->step_net); PADDLE_ENFORCE(net != nullptr, "failed to get step net"); - for (int step_id = seq_len_ - 1; step_id >= 0; --step_id) { if (static_cast(step_id) != seq_len_ - 1) { - rnn::LinkMemories(step_scopes, arg_->memories, step_id, 1, true); + rnn::LinkMemories( + step_scopes, arg_->memories, step_id, 1, true /*infer_shape_mode*/); } net->GetMutable()->InferShape(step_scopes[step_id]); } - rnn::ConcatOutputs(step_scopes, arg_->outlinks, seq_len_, true); - LinkBootMemoryGradients(step_scopes[0], true); + rnn::ConcatOutputs( + step_scopes, arg_->outlinks, seq_len_, true /*infer_shape_mode*/); + LinkBootMemoryGradients(step_scopes[0], true /*infer_shape_mode*/); } void RecurrentGradientOp::Init() { diff --git a/paddle/operators/recurrent_network_op.h b/paddle/operators/recurrent_network_op.h index 87a997b82e465c83683777e364bbbcc4652fb02d..3f722d5608962c801d271c9cca2164fa63711230 100644 --- a/paddle/operators/recurrent_network_op.h +++ b/paddle/operators/recurrent_network_op.h @@ -73,7 +73,7 @@ struct ArgumentName { void SegmentInputs(std::vector>& step_scopes, const std::vector& inlinks, const size_t seq_len, - bool infer_shape); + bool infer_shape_mode); /** * Process outputs of step nets and merge to variables. @@ -81,13 +81,13 @@ void SegmentInputs(std::vector>& step_scopes, void ConcatOutputs(std::vector>& step_scopes, const std::vector& outlinks, const size_t seq_len, - bool infer_shape); + bool infer_shape_mode); void LinkMemories(std::vector>& step_scopes, const std::vector& memories, const size_t step_id, const int offset, - bool infer_shape); + bool infer_shape_mode); void InitArgument(const ArgumentName& name, Argument* arg); @@ -128,7 +128,8 @@ protected: ->GetMutable>>(); } - void InitMemories(std::shared_ptr step_scopes, bool infer_shape) const; + void InitMemories(std::shared_ptr step_scopes, + bool infer_shape_mode) const; private: std::unique_ptr arg_; @@ -153,7 +154,7 @@ public: const platform::DeviceContext& dev_ctx) const; void LinkBootMemoryGradients(std::shared_ptr step_scopes, - bool infer_shape) const; + bool infer_shape_mode) const; /** * InferShape must be called before Run. diff --git a/paddle/operators/recurrent_network_op_test.cc b/paddle/operators/recurrent_network_op_test.cc index 86588a969c8bd223e4599fc55cd965dee5f9ebe4..635c2fe0381679bb08965317f69721909bd25157 100644 --- a/paddle/operators/recurrent_network_op_test.cc +++ b/paddle/operators/recurrent_network_op_test.cc @@ -298,7 +298,10 @@ protected: std::vector>* step_scopes = scope_->GetVariable("step_scopes") ->GetMutable>>(); - rnn::SegmentInputs(*step_scopes, std::vector{inlink}, 10, true); + rnn::SegmentInputs(*step_scopes, + std::vector{inlink}, + 10, + true /*infer_shape_mode*/); } void LinkeMemories() { @@ -313,7 +316,8 @@ protected: scope_->GetVariable("step_scopes") ->GetMutable>>(); for (int i = 1; i < 10; ++i) { - rnn::LinkMemories(*step_scopes, memories, i, -1, true); + rnn::LinkMemories( + *step_scopes, memories, i, -1, true /*infer_shape_mode*/); } } @@ -343,7 +347,7 @@ TEST(RecurrentOp, LinkMemories) { auto tensor = scope->CreateVariable("h")->GetMutable(); float* data = tensor->mutable_data(make_ddim({15, 20}), CPUPlace()); for (int j = 0; j < 15 * 20; ++j) { - data[i] = rand() * (1. / (double)RAND_MAX); + data[j] = rand() * (1. / (double)RAND_MAX); } step_scopes.push_back(scope); } @@ -357,7 +361,7 @@ TEST(RecurrentOp, LinkMemories) { memories.push_back(mem_attr); for (int i = 1; i < len; ++i) { - rnn::LinkMemories(step_scopes, memories, i, -1, false); + rnn::LinkMemories(step_scopes, memories, i, -1, false /*infer_shape_mode*/); } // check for (int i = 0; i < len - 1; ++i) { @@ -373,7 +377,7 @@ TEST(RecurrentOp, LinkMemories) { } for (int i = len - 2; i >= 0; --i) { - rnn::LinkMemories(step_scopes, memories, i, 1, false); + rnn::LinkMemories(step_scopes, memories, i, 1, false /*infer_shape_mode*/); } // check for (int i = len - 2; i >= 0; --i) {