Skip to content

Commit d5e3279

Browse files
authored
While op forward for sentimental analysis (#6140)
* Add DataFeeder A v2 API like data feeder for book demos. We can feed data directly from reader. * Fix CI * Add an unittest for while/rnn op forward * Add unittest for raw while op backward * Fix CI
1 parent 1fe05c4 commit d5e3279

21 files changed

+262
-61
lines changed

paddle/framework/backward.cc

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@
2727
namespace paddle {
2828
namespace framework {
2929

30+
static std::unordered_set<std::string>* g_ctrl_flow_ops_ = nullptr;
31+
// Control Flow operators's backward is significantly different from
32+
// computational operators. Hack Code here.
33+
// We should design a better way to backward CtrlFlowOps.
34+
static std::unordered_set<std::string>& CtrlFlowOps() {
35+
if (g_ctrl_flow_ops_ == nullptr) {
36+
g_ctrl_flow_ops_ =
37+
new std::unordered_set<std::string>{"increment", "lod_rank_table"};
38+
}
39+
return *g_ctrl_flow_ops_;
40+
}
41+
3042
static inline std::unique_ptr<OperatorBase> CreateGradOp(
3143
const OperatorBase& op, const std::unordered_set<std::string>& no_grad_set,
3244
std::unordered_map<std::string, std::string>* grad_to_var) {
@@ -288,12 +300,24 @@ static void CreateGradVarInBlock(
288300
for (size_t op_index = grad_op_start_index; op_index < ops.size();
289301
++op_index) {
290302
std::unordered_set<std::string> new_vars;
303+
auto& ctrl_flow_ops = CtrlFlowOps();
291304
ForEachVarName(ops[op_index]->Outputs(),
292305
[&](const std::string& grad_var_name) {
293-
if (block_desc->HasVar(grad_var_name)) {
306+
if (ctrl_flow_ops.find(ops[op_index]->Type()) !=
307+
ctrl_flow_ops.end()) {
308+
if (block_desc->HasVarRecursive(grad_var_name)) {
309+
return false;
310+
}
311+
} else {
312+
if (block_desc->HasVar(grad_var_name)) {
313+
return false;
314+
}
315+
}
316+
if (grad_var_name == framework::kEmptyVarName) {
294317
return false;
295318
}
296319
auto var = block_desc->Var(grad_var_name);
320+
VLOG(10) << "Creating Variable " << grad_var_name;
297321
new_vars.insert(var->Name());
298322
auto it = param_name_map.find(grad_var_name);
299323
if (it == param_name_map.end()) {
@@ -333,14 +357,25 @@ std::vector<std::unique_ptr<OpDescBind>> MakeOpGrad(
333357
// All input gradients of forwarding operator do not need to calculate.
334358
const std::vector<std::string>& inputs = op_desc->InputArgumentNames();
335359
if (AllGradInSet(inputs, *no_grad_vars)) {
360+
VLOG(10) << "Drop operator " << op_desc->Type();
336361
return grad_op_descs; // empty vector
337362
}
363+
338364
// All output gradients of forwarding operator do not need to calculate.
339365
const std::vector<std::string>& outputs = op_desc->OutputArgumentNames();
366+
340367
if (AllGradInSet(outputs, *no_grad_vars)) {
341-
for (const std::string& name : inputs) {
342-
no_grad_vars->insert(GradVarName(name));
368+
VLOG(10) << "Drop operator " << op_desc->Type();
369+
// FIXME: Hack code here
370+
auto& ctrl_flow_ops = CtrlFlowOps();
371+
if (ctrl_flow_ops.find(op_desc->Type()) == ctrl_flow_ops.end()) {
372+
// Only computational op need drop input's gradient.
373+
for (const std::string& name : inputs) {
374+
no_grad_vars->insert(GradVarName(name));
375+
VLOG(10) << " Also drop " << GradVarName(name);
376+
}
343377
}
378+
344379
return grad_op_descs; // empty vector
345380
}
346381

paddle/framework/block_desc.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ See the License for the specific language governing permissions and
1313
limitations under the License. */
1414

1515
#include "paddle/framework/block_desc.h"
16+
#include "paddle/framework/operator.h"
1617
#include "paddle/framework/program_desc.h"
1718

1819
namespace paddle {
@@ -42,6 +43,8 @@ bool BlockDescBind::HasVar(const std::string &name) const {
4243
}
4344

4445
VarDescBind *BlockDescBind::FindVarRecursive(const std::string &name) const {
46+
if (name == kEmptyVarName) return nullptr;
47+
4548
auto it = vars_.find(name);
4649
if (it == vars_.end()) {
4750
return Parent() == kNoneBlockIndex ? nullptr

paddle/framework/executor.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ void Executor::Run(const ProgramDescBind& pdesc, Scope* scope, int block_id,
9797
if (create_local_scope) {
9898
local_scope = &scope->NewScope();
9999
for (auto& var : block.AllVars()) {
100+
if (var->Name() == framework::kEmptyVarName) {
101+
continue;
102+
}
103+
100104
if (var->Persistable()) {
101105
auto* ptr = scope->Var(var->Name());
102106
CreateTensor(ptr, var->GetType());

paddle/framework/op_desc.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,12 @@ DDim CompileTimeInferShapeContext::GetDim(const std::string &name) const {
466466
auto var = block_.FindVarRecursive(name);
467467
PADDLE_ENFORCE(var != nullptr, "Cannot find variable %s", name);
468468
try {
469-
return framework::make_ddim(var->Shape());
469+
auto shape = var->Shape();
470+
if (shape.empty()) {
471+
return framework::make_ddim({0UL});
472+
} else {
473+
return framework::make_ddim(var->Shape());
474+
}
470475
} catch (...) {
471476
VLOG(5) << "GetDim of variable " << name << " error";
472477
std::rethrow_exception(std::current_exception());

paddle/framework/scope.cc

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,9 @@ Scope& Scope::NewScope() const {
3636
}
3737

3838
Variable* Scope::Var(const std::string& name) {
39-
auto iter = vars_.find(name);
40-
if (iter != vars_.end()) {
41-
VLOG(3) << "Get existing variable " << name;
42-
return iter->second;
43-
}
44-
Variable* v = new Variable();
39+
auto* v = FindVarLocally(name);
40+
if (v != nullptr) return v;
41+
v = new Variable();
4542
vars_[name] = v;
4643
VLOG(3) << "Create variable " << name;
4744
v->name_ = &(vars_.find(name)->first);
@@ -57,8 +54,10 @@ Variable* Scope::Var(std::string* name) {
5754
}
5855

5956
Variable* Scope::FindVar(const std::string& name) const {
60-
auto it = vars_.find(name);
61-
if (it != vars_.end()) return it->second;
57+
auto var = FindVarLocally(name);
58+
if (var != nullptr) {
59+
return var;
60+
}
6261
return (parent_ == nullptr) ? nullptr : parent_->FindVar(name);
6362
}
6463

@@ -116,6 +115,11 @@ std::string Scope::Rename(const std::string& origin_name) const {
116115
Rename(origin_name, var_name);
117116
return var_name;
118117
}
118+
Variable* Scope::FindVarLocally(const std::string& name) const {
119+
auto it = vars_.find(name);
120+
if (it != vars_.end()) return it->second;
121+
return nullptr;
122+
}
119123

120124
} // namespace framework
121125
} // namespace paddle

paddle/framework/scope.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ class Scope {
7676
std::string Rename(const std::string& origin_name) const;
7777

7878
private:
79+
Variable* FindVarLocally(const std::string& name) const;
80+
7981
// Call Scope::NewScope for a sub-scope.
8082
explicit Scope(Scope const* parent) : parent_(parent) {}
8183

paddle/framework/shape_inference.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
1414
#include "paddle/framework/shape_inference.h"
15+
#include "grad_op_desc_maker.h"
16+
#include "paddle/framework/operator.h"
1517

1618
namespace paddle {
1719
namespace framework {
@@ -49,6 +51,9 @@ void InferShapeContext::SetDims(const std::vector<std::string> &names,
4951
size_t length = names.size();
5052
PADDLE_ENFORCE_EQ(length, dims.size());
5153
for (size_t i = 0; i < length; ++i) {
54+
if (names[i] == framework::kEmptyVarName) {
55+
continue;
56+
}
5257
SetDim(names[i], dims[i]);
5358
}
5459
}

paddle/operators/increment_op.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class IncrementOp : public framework::OperatorBase {
6161
out.Resize(x.dims());
6262
out.mutable_data(x.place(), x.type());
6363
float value = Attr<float>("step");
64+
VLOG(10) << Output("Out") << " increase " << Input("X") << " with "
65+
<< value;
6466
framework::VisitDataType(framework::ToDataType(out.type()),
6567
IncrementFunctor(x, &out, value));
6668
}

paddle/operators/lod_tensor_to_array_op.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "paddle/framework/lod_rank_table.h"
1515
#include "paddle/framework/lod_tensor_array.h"
1616
#include "paddle/framework/op_registry.h"
17+
#include "paddle/operators/detail/safe_ref.h"
1718

1819
namespace paddle {
1920
namespace operators {
@@ -32,15 +33,20 @@ class LoDTensorToArrayOp : public framework::OperatorBase {
3233
: OperatorBase(type, inputs, outputs, attrs) {}
3334
void Run(const framework::Scope &scope,
3435
const platform::DeviceContext &dev_ctx) const override {
35-
auto &x = scope.FindVar(Input("X"))->Get<framework::LoDTensor>();
36-
auto &rank_table =
37-
scope.FindVar(Input("RankTable"))->Get<framework::LoDRankTable>();
38-
auto &out =
39-
*scope.FindVar(Output("Out"))->GetMutable<framework::LoDTensorArray>();
40-
36+
auto &x = detail::Ref(scope.FindVar(Input("X")), "Cannot find input %s",
37+
Input("X"))
38+
.Get<framework::LoDTensor>();
39+
auto &rank_table = detail::Ref(scope.FindVar(Input("RankTable")))
40+
.Get<framework::LoDRankTable>();
41+
auto &out = *detail::Ref(scope.FindVar(Output("Out")))
42+
.GetMutable<framework::LoDTensorArray>();
4143
auto &items = rank_table.items();
4244
auto max_seq_len = items[0].length;
4345
auto rank_level = rank_table.level();
46+
47+
PADDLE_ENFORCE_LT(rank_level, x.lod().size(),
48+
"Input should be a LOD tensor, and size is at least %d",
49+
rank_level + 1);
4450
out.resize(max_seq_len);
4551
std::vector<std::vector<CopyRange>> copy_ranges(max_seq_len);
4652

@@ -55,16 +61,13 @@ class LoDTensorToArrayOp : public framework::OperatorBase {
5561
size_t start_idx = x.lod()[rank_level][item.index] + t;
5662
auto lod_and_offset = framework::GetSubLoDAndAbsoluteOffset(
5763
x.lod(), start_idx, start_idx + 1, rank_level + 1);
58-
5964
auto &lod_length = lod_and_offset.first;
6065
framework::AppendLoD(&lod, lod_length);
61-
6266
size_t start_offset = lod_and_offset.second.first;
6367
size_t end_offset = lod_and_offset.second.second;
6468
copy_ranges[t].emplace_back(CopyRange{start_offset, end_offset});
6569
}
6670
}
67-
6871
for (size_t i = 0; i < max_seq_len; ++i) {
6972
auto &ranges = copy_ranges[i];
7073
size_t height = std::accumulate(

paddle/operators/multiplex_op.cc

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,7 @@ class MultiplexGradOp : public framework::OperatorWithKernel {
9999
"Output(X@Grad) should not be null.");
100100
PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")),
101101
"Input(Out@GRAD) should not be null.");
102-
std::vector<framework::DDim> d_ins;
103-
auto ins = ctx->GetInputsDim("X");
104-
// No need to compute gradient for Input(Ids)
105-
for (size_t i = 0; i < ins.size(); i++) {
106-
d_ins.push_back(ins[i]);
107-
}
108-
ctx->SetOutputsDim(framework::GradVarName("X"), d_ins);
102+
ctx->SetOutputsDim(framework::GradVarName("X"), ctx->GetInputsDim("X"));
109103
}
110104

111105
protected:

0 commit comments

Comments
 (0)