Skip to content

Commit f659581

Browse files
author
Yibing Liu
committed
Get sequence length in sequence_pad op & fix sequence_mask op
1 parent a39eba7 commit f659581

File tree

13 files changed

+126
-30
lines changed

13 files changed

+126
-30
lines changed

paddle/fluid/framework/op_proto_maker.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ void OpProtoAndCheckerMaker::operator()(proto::OpProto* proto,
131131

132132
AddAttr<std::string>(OpNamescopeAttrName(), "Operator name with namesope.")
133133
.SetDefault("");
134-
134+
AddAttr<std::vector<std::string>>(OpCreationCallstackAttrName(),
135+
"Callstack for Op Creatation.")
136+
.SetDefault({});
135137
Validate();
136138
}
137139

paddle/fluid/framework/op_proto_maker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class OpProtoAndCheckerMaker {
4040
static const char *OpRoleAttrName() { return "op_role"; }
4141
static const char *OpRoleVarAttrName() { return "op_role_var"; }
4242
static const char *OpNamescopeAttrName() { return "op_namescope"; }
43+
static const char *OpCreationCallstackAttrName() { return "op_callstack"; }
4344

4445
void operator()(proto::OpProto *proto, OpAttrChecker *attr_checker);
4546

paddle/fluid/framework/operator.cc

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ distributed under the License is distributed on an "AS IS" BASIS,
1111
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
14-
#include <gflags/gflags.h>
15-
#include <glog/logging.h>
16-
14+
#include "paddle/fluid/framework/operator.h"
1715
#include <algorithm>
18-
16+
#include <sstream>
17+
#include <string>
18+
#include <vector>
19+
#include "gflags/gflags.h"
20+
#include "glog/logging.h"
1921
#include "paddle/fluid/framework/data_transform.h"
2022
#include "paddle/fluid/framework/executor.h"
2123
#include "paddle/fluid/framework/lod_tensor.h"
22-
#include "paddle/fluid/framework/operator.h"
24+
#include "paddle/fluid/framework/op_proto_maker.h"
2325
#include "paddle/fluid/framework/shape_inference.h"
2426
#include "paddle/fluid/framework/var_type.h"
2527
#include "paddle/fluid/platform/profiler.h"
@@ -137,19 +139,48 @@ static LoD GetLoD(const Scope& scope, const std::string& name) {
137139
}
138140

139141
void OperatorBase::Run(const Scope& scope, const platform::Place& place) {
140-
VLOG(4) << place << " " << DebugStringEx(&scope);
141-
if (platform::is_gpu_place(place)) {
142+
try {
143+
if (VLOG_IS_ON(4)) {
144+
VLOG(4) << place << " " << DebugStringEx(&scope);
145+
}
146+
if (platform::is_gpu_place(place)) {
142147
#ifndef PADDLE_WITH_CUDA
143-
PADDLE_THROW("Cannot run operator on place %s", place);
148+
PADDLE_THROW("Cannot run operator on place %s", place);
144149
#else
145-
auto dev_id = boost::get<platform::CUDAPlace>(place).device;
146-
platform::SetDeviceId(dev_id);
150+
auto dev_id = boost::get<platform::CUDAPlace>(place).device;
151+
platform::SetDeviceId(dev_id);
147152
#endif
153+
}
154+
platform::DeviceContextPool& pool = platform::DeviceContextPool::Instance();
155+
platform::RecordEvent record_event(Type(), pool.Get(place));
156+
RunImpl(scope, place);
157+
if (VLOG_IS_ON(3)) {
158+
VLOG(3) << place << " " << DebugStringEx(&scope);
159+
}
160+
} catch (platform::EnforceNotMet exception) {
161+
if (Attrs().count("sub_block") != 0) {
162+
throw exception;
163+
}
164+
165+
auto& callstack = Attr<std::vector<std::string>>(
166+
OpProtoAndCheckerMaker::OpCreationCallstackAttrName());
167+
168+
if (callstack.empty()) {
169+
throw exception;
170+
}
171+
std::ostringstream sout;
172+
sout << "Invoke operator " << Type() << " error.\n";
173+
sout << "Python Callstacks: \n";
174+
for (auto& line : callstack) {
175+
sout << line;
176+
}
177+
sout << "C++ Callstacks: \n";
178+
sout << exception.err_str_;
179+
exception.err_str_ = sout.str();
180+
throw exception;
181+
} catch (...) {
182+
std::rethrow_exception(std::current_exception());
148183
}
149-
platform::DeviceContextPool& pool = platform::DeviceContextPool::Instance();
150-
platform::RecordEvent record_event(Type(), pool.Get(place));
151-
RunImpl(scope, place);
152-
VLOG(3) << place << " " << DebugStringEx(&scope);
153184
}
154185

155186
bool OperatorBase::HasInputs(const std::string& name) const {
@@ -177,7 +208,7 @@ const std::vector<std::string>& OperatorBase::Inputs(
177208
}
178209

179210
bool OperatorBase::HasOutputs(const std::string& name) const {
180-
if (outputs_.find(name) != outputs_.end()) {
211+
if (outputs_.end() != outputs_.find(name)) {
181212
return true;
182213
} else {
183214
return false;

paddle/fluid/operators/sequence_mask_op.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ REGISTER_OP_CPU_KERNEL(
2323
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
2424
int>,
2525
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
26-
int64_t>);
26+
int64_t>,
27+
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
28+
float>,
29+
paddle::operators::SequenceMaskKernel<paddle::platform::CPUDeviceContext,
30+
double>);

paddle/fluid/operators/sequence_mask_op.cu

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ REGISTER_OP_CUDA_KERNEL(
1919
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
2020
int>,
2121
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
22-
int64_t>);
22+
int64_t>,
23+
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
24+
float>,
25+
paddle::operators::SequenceMaskKernel<paddle::platform::CUDADeviceContext,
26+
double>);

paddle/fluid/operators/sequence_pad_op.cc

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ class SequencePadOp : public framework::OperatorWithKernel {
2929
"Input(PadValue) of SequencePadOp should not be null.");
3030
PADDLE_ENFORCE(ctx->HasOutput("Out"),
3131
"Output(Out) of SequencePadOp should not be null.");
32+
PADDLE_ENFORCE(ctx->HasOutput("Length"),
33+
"Output(Length) of SequencePadOp should not be null.");
3234

3335
auto x_dims = ctx->GetInputDim("X");
3436
PADDLE_ENFORCE_GE(x_dims.size(), 2,
35-
"The rank of Input(x) can't be less than 2.");
37+
"The rank of Input(X) can't be less than 2.");
3638
auto time_step_dims = framework::slice_ddim(x_dims, 1, x_dims.size());
3739
auto pad_value_dims = ctx->GetInputDim("PadValue");
3840
PADDLE_ENFORCE(pad_value_dims == framework::make_ddim({1}) ||
@@ -41,8 +43,8 @@ class SequencePadOp : public framework::OperatorWithKernel {
4143
"shape equals to time steps in sequences");
4244

4345
int out_dim_0 = -1;
44-
int out_dim_1 = -1;
4546

47+
int padded_length = ctx->Attrs().Get<int>("padded_length");
4648
if (ctx->IsRuntime()) {
4749
// run time
4850
framework::Variable* x_var =
@@ -58,27 +60,37 @@ class SequencePadOp : public framework::OperatorWithKernel {
5860

5961
int seq_num = x_lod_0.size() - 1;
6062
int max_seq_len = math::MaximumSequenceLength(x_lod_0);
61-
int padded_length = ctx->Attrs().Get<int>("padded_length");
6263
if (padded_length == -1) {
6364
padded_length = max_seq_len;
6465
}
6566
PADDLE_ENFORCE_GE(padded_length, max_seq_len,
6667
"The Attr(padded_length) must be -1 or an int greater "
6768
"than the length of the longest original sequence.");
6869
out_dim_0 = seq_num;
69-
out_dim_1 = padded_length;
7070
} else {
7171
// compile time
72+
if (padded_length == -1) {
73+
padded_length = 1;
74+
}
7275
framework::VarDesc* x_desc =
7376
boost::get<framework::VarDesc*>(ctx->GetInputVarPtrs("X")[0]);
7477
PADDLE_ENFORCE_GE(x_desc->GetLoDLevel(), 1);
7578
}
7679

77-
std::vector<int> out_dims_vec{out_dim_0, out_dim_1};
80+
std::vector<int> out_dims_vec{out_dim_0, padded_length};
81+
std::vector<int> len_dims_vec{out_dim_0, 1};
7882
auto time_step_dims_vec = framework::vectorize2int(time_step_dims);
7983
out_dims_vec.insert(out_dims_vec.end(), time_step_dims_vec.begin(),
8084
time_step_dims_vec.end());
8185
ctx->SetOutputDim("Out", framework::make_ddim(out_dims_vec));
86+
ctx->SetOutputDim("Length", framework::make_ddim(len_dims_vec));
87+
}
88+
89+
protected:
90+
framework::OpKernelType GetExpectedKernelType(
91+
const framework::ExecutionContext& ctx) const override {
92+
auto data_type = framework::GetDataTypeOfVar(ctx.InputVar("X"));
93+
return framework::OpKernelType(data_type, ctx.device_context());
8294
}
8395
};
8496

@@ -96,6 +108,10 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
96108
AddOutput(
97109
"Out",
98110
"(LoDTensor) The output vairable, which contains padded sequences.");
111+
AddOutput(
112+
"Length",
113+
"(LoDTensor) The output vairable, which contains the actual length of "
114+
"sequences before padding.");
99115
AddAttr<int>(
100116
"padded_length",
101117
"The length of padded sequences. It can be setted to -1 or "
@@ -125,6 +141,7 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
125141
then we get LoDTensor:
126142
Out.data = [[a, b, 0, 0],
127143
[c, d, e, 0]]
144+
Length.data = [[2], [3]]
128145
129146
Case 2:
130147
@@ -138,7 +155,8 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
138155
then we get LoDTensor:
139156
Out.data = [[[a1, a2], [b1, b2], [0, 0]],
140157
[[c1, c2], [d1, d2], [e1, e2]]]
141-
158+
Length.data = [[2], [3]]
159+
142160
Case 3:
143161
144162
Given a 1-level LoDTensor input(X):
@@ -151,6 +169,7 @@ class SequencePadOpMaker : public framework::OpProtoAndCheckerMaker {
151169
then we get LoDTensor:
152170
Out.data = [[[a1, a2], [b1, b2], [p1, p2]],
153171
[[c1, c2], [d1, d2], [e1, e2]]]
172+
Length.data = [[2], [3]]
154173
155174
)DOC");
156175
}
@@ -171,6 +190,13 @@ class SequencePadGradOp : public framework::OperatorWithKernel {
171190
ctx->ShareLoD("X", /*->*/ framework::GradVarName("X"));
172191
}
173192
}
193+
194+
protected:
195+
framework::OpKernelType GetExpectedKernelType(
196+
const framework::ExecutionContext& ctx) const override {
197+
auto data_type = framework::GetDataTypeOfVar(ctx.InputVar("X"));
198+
return framework::OpKernelType(data_type, ctx.device_context());
199+
}
174200
};
175201

176202
} // namespace operators

paddle/fluid/operators/sequence_pad_op.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class SequencePadOpKernel : public framework::OpKernel<T> {
3232
void Compute(const framework::ExecutionContext& ctx) const override {
3333
const auto* x = ctx.Input<LoDTensor>("X");
3434
auto* out = ctx.Output<LoDTensor>("Out");
35+
auto* len_t = ctx.Output<LoDTensor>("Length");
3536
out->mutable_data<T>(ctx.GetPlace());
3637

3738
const auto* pad_value = ctx.Input<LoDTensor>("PadValue");
@@ -41,6 +42,15 @@ class SequencePadOpKernel : public framework::OpKernel<T> {
4142
math::PaddingLoDTensorFunctor<DeviceContext, T>()(
4243
ctx.template device_context<DeviceContext>(), *x, out, *pad_value,
4344
padded_length, 0, false, math::kBatchLengthWidth);
45+
46+
LoDTensor seq_len;
47+
seq_len.Resize(len_t->dims());
48+
int64_t* len_data = seq_len.mutable_data<int64_t>(platform::CPUPlace());
49+
for (size_t i = 1; i < x->lod()[0].size(); ++i) {
50+
len_data[i - 1] = x->lod()[0][i] - x->lod()[0][i - 1];
51+
}
52+
framework::TensorCopy(seq_len, ctx.GetPlace(),
53+
ctx.template device_context<DeviceContext>(), len_t);
4454
}
4555
};
4656

paddle/fluid/operators/top_k_op.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class TopkOp : public framework::OperatorWithKernel {
3030
"Output(Indices) of TopkOp should not be null.");
3131

3232
auto input_dims = ctx->GetInputDim("X");
33+
PADDLE_ENFORCE_EQ(input_dims.size(), 2,
34+
"Rank of TopK op's input must be 2.");
3335
const int k = static_cast<int>(ctx->Attrs().Get<int>("k"));
3436

3537
PADDLE_ENFORCE_GE(k, 1, "k must >= 1");

paddle/fluid/pybind/const_value.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ void BindConstValue(pybind11::module* m) {
4646
op_proto_and_checker_maker.def(
4747
"kOpNameScopeAttrName",
4848
framework::OpProtoAndCheckerMaker::OpNamescopeAttrName);
49+
op_proto_and_checker_maker.def(
50+
"kOpCreationCallstackAttrName",
51+
framework::OpProtoAndCheckerMaker::OpCreationCallstackAttrName);
4952
}
5053

5154
} // namespace pybind

python/paddle/fluid/framework.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import contextlib
1919
import re
2020
import six
21+
import traceback
2122

2223
import numpy as np
2324

@@ -572,6 +573,10 @@ def __init__(self,
572573
if role_var_name in op_attrs and len(op_attrs[role_var_name]) == 0:
573574
del op_attrs[role_var_name]
574575

576+
callstack_var_name = op_maker.kOpCreationCallstackAttrName()
577+
op_attrs[callstack_var_name] = list(
578+
reversed(traceback.format_stack()))[1:]
579+
575580
if len(self.desc.type()) != 0:
576581
return
577582
if type is None:

0 commit comments

Comments
 (0)