Skip to content

Commit b24afd8

Browse files
author
wanghaox
committed
update the sub_sequence_op to sequence_slice_op code.
1 parent f23d6cc commit b24afd8

File tree

4 files changed

+140
-113
lines changed

4 files changed

+140
-113
lines changed

paddle/operators/sequence_slice_op.cc

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,39 @@ 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. */
1414

15-
#include "paddle/operators/sub_sequence_op.h"
15+
#include "paddle/operators/sequence_slice_op.h"
1616

1717
namespace paddle {
1818
namespace operators {
1919

20-
class SubSequenceOp : public framework::OperatorWithKernel {
20+
class SequenceSliceOp : public framework::OperatorWithKernel {
2121
public:
2222
using framework::OperatorWithKernel::OperatorWithKernel;
2323

2424
void InferShape(framework::InferShapeContext* ctx) const override {
2525
PADDLE_ENFORCE(ctx->HasInput("X"),
26-
"Input(X) of SubSequenceOp should not be null.");
26+
"Input(X) of SequenceSliceOp should not be null.");
27+
PADDLE_ENFORCE(ctx->HasInput("Offset"),
28+
"Input(Offset) of SequenceSliceOp should not be null.");
29+
PADDLE_ENFORCE(ctx->HasInput("Length"),
30+
"Input(Length) of SequenceSliceOp should not be null.");
2731
PADDLE_ENFORCE(ctx->HasOutput("Out"),
28-
"Output(Out) of SubSequenceOp should not be null.");
32+
"Output(Out) of SequenceSliceOp should not be null.");
2933
auto input_dims = ctx->GetInputDim("X");
3034

31-
auto offsets = ctx->Attrs().Get<std::vector<int>>("offset");
32-
auto sizes = ctx->Attrs().Get<std::vector<int>>("size");
33-
34-
auto dim_0 = 0;
35-
for (size_t i = 0; i < sizes.size(); ++i) {
36-
dim_0 += sizes[i];
35+
ctx->SetOutputDim("Out", input_dims);
3736
}
3837

39-
framework::DDim out_dims = input_dims;
40-
out_dims[0] = dim_0;
41-
ctx->SetOutputDim("Out", out_dims);
38+
protected:
39+
framework::OpKernelType GetKernelType(
40+
const framework::ExecutionContext& ctx) const override {
41+
return framework::OpKernelType(
42+
framework::ToDataType(ctx.Input<framework::LoDTensor>("X")->type()),
43+
ctx.device_context());
4244
}
4345
};
4446

45-
class SubSequenceGradOp : public framework::OperatorWithKernel {
47+
class SequenceSliceGradOp : public framework::OperatorWithKernel {
4648
public:
4749
using framework::OperatorWithKernel::OperatorWithKernel;
4850

@@ -53,34 +55,50 @@ class SubSequenceGradOp : public framework::OperatorWithKernel {
5355
"The gradient of X should not be null.");
5456
ctx->SetOutputsDim(framework::GradVarName("X"), ctx->GetInputsDim("X"));
5557
}
58+
59+
protected:
60+
framework::OpKernelType GetKernelType(
61+
const framework::ExecutionContext& ctx) const override {
62+
return framework::OpKernelType(
63+
framework::ToDataType(ctx.Input<framework::LoDTensor>("X")->type()),
64+
ctx.device_context());
65+
}
5666
};
5767

58-
class SubSequenceOpMaker : public framework::OpProtoAndCheckerMaker {
68+
class SequenceSliceOpMaker : public framework::OpProtoAndCheckerMaker {
5969
public:
60-
SubSequenceOpMaker(framework::OpProto* proto,
61-
framework::OpAttrChecker* op_checker)
70+
SequenceSliceOpMaker(framework::OpProto* proto,
71+
framework::OpAttrChecker* op_checker)
6272
: OpProtoAndCheckerMaker(proto, op_checker) {
63-
AddInput("X", "(LoDTensor), "
64-
"the variable-length input of SubSequenceOp");
65-
AddAttr<std::vector<int>>(
66-
"offset",
67-
"A list<int> to describes offset for sub sequence item.");
68-
AddAttr<std::vector<int>>(
69-
"size",
70-
"A list<int> to describes size for sub sequence item.");
73+
AddInput("X",
74+
"(LoDTensor), "
75+
"the input of SequenceSliceOp.");
76+
AddInput("Offset",
77+
"(Tensor), "
78+
"A vector<int> to describes offset for sub sequence item.");
79+
AddInput("Length",
80+
"(Tensor), "
81+
"A vector<int> to describes length for sub sequence item.");
7182
AddOutput("Out",
72-
"(Tensor), Variable-length output of "
73-
"sequence_concat Op.");
83+
"(LoDTensor), output of sequence slice Op.");
7484
AddComment(R"DOC(
75-
Sub Sequence operator
76-
77-
The operator crop a subsequence from given sequence with given start offset and subsequence size.
85+
Sequence slice operator
86+
The operator crop a subsequence from given sequence with given start offset and subsequence length.
7887
It only supports sequence (LoD Tensor with level number is 1).
7988
- Case:
80-
LoD(x) = {{0, 3, 6, 10}}; Dims(x0) = (10, 3, 2)
81-
offset = (0, 1, 1); size = (2, 1, 2)
82-
LoD(Out) = {{0, 2, 3, 5}}; Dims(Out) = (5,3,2)
83-
NOTE: The length of the input, offset and size should be the same. The offset start from 0.
89+
X = [[a1, a2;
90+
b1, b2;
91+
c1, c2]
92+
[d1, d2;
93+
e1, e2]]
94+
LoD(X) = {{0, 3, 5}}; Dims(X) = (4, 1, 2)
95+
Offset = (0, 1); Length = (2, 1)
96+
97+
Out = [[a1, a2;
98+
b1, b2]
99+
[e1, e2]]
100+
LoD(Out) = {{0, 2, 3}}
101+
NOTE: The length of the input, offset and length should be the same. The offset start from 0.
84102
)DOC");
85103
}
86104
};
@@ -89,11 +107,11 @@ NOTE: The length of the input, offset and size should be the same. The offset st
89107
} // namespace paddle
90108

91109
namespace ops = paddle::operators;
92-
REGISTER_OP(sub_sequence, ops::SubSequenceOp, ops::SubSequenceOpMaker,
93-
sub_sequence_grad, ops::SubSequenceGradOp);
110+
REGISTER_OP(sequence_slice, ops::SequenceSliceOp, ops::SequenceSliceOpMaker,
111+
sequence_slice_grad, ops::SequenceSliceGradOp);
94112
REGISTER_OP_CPU_KERNEL(
95-
sub_sequence,
96-
ops::SubSequenceOpKernel<paddle::platform::CPUPlace, float>);
113+
sequence_slice,
114+
ops::SequenceSliceOpKernel<paddle::platform::CPUPlace, float>);
97115
REGISTER_OP_CPU_KERNEL(
98-
sub_sequence_grad,
99-
ops::SubSequenceGradOpKernel<paddle::platform::CPUPlace, float>);
116+
sequence_slice_grad,
117+
ops::SequenceSliceGradOpKernel<paddle::platform::CPUPlace, float>);

paddle/operators/sequence_slice_op.cu

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ 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. */
1414

15-
#define EIGEN_USE_GPU
16-
17-
#include "paddle/operators/sub_sequence_op.h"
15+
#include "paddle/operators/sequence_slice_op.h"
1816

1917
namespace ops = paddle::operators;
2018
REGISTER_OP_GPU_KERNEL(
21-
sub_sequence,
22-
ops::SubSequenceOpKernel<paddle::platform::GPUPlace, float>);
19+
sequence_slice,
20+
ops::SequenceSliceOpKernel<paddle::platform::GPUPlace, float>);
2321
REGISTER_OP_GPU_KERNEL(
24-
sub_sequence_grad,
25-
ops::SubSequenceGradOpKernel<paddle::platform::GPUPlace, float>);
22+
sequence_slice_grad,
23+
ops::SequenceSliceGradOpKernel<paddle::platform::GPUPlace, float>);

paddle/operators/sequence_slice_op.h

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

1515
#pragma once
16-
#include "paddle/framework/eigen.h"
1716
#include "paddle/framework/op_registry.h"
17+
#include "paddle/operators/math/math_function.h"
1818
#include "paddle/operators/strided_memcpy.h"
1919

2020
namespace paddle {
@@ -25,109 +25,124 @@ using LoDTensor = framework::LoDTensor;
2525
using LoD = framework::LoD;
2626

2727
template <typename T>
28-
LoD subsequenceLoD(const T* in, const std::vector<int> offsets,
29-
const std::vector<int> sizes) {
30-
auto out_lod = in->lod();
28+
LoD SequenceSliceLoD(const T& in, const int64_t* offset_data,
29+
const int64_t* length_data) {
30+
auto out_lod = in.lod();
3131
size_t lod_offset = 0;
3232

33-
auto n = in->lod()[0].size() - 1;
33+
auto n = in.lod()[0].size() - 1;
3434
out_lod[0][0] = 0;
3535
for (size_t i = 0; i < n; ++i) {
36-
lod_offset += sizes[i];
36+
lod_offset += length_data[i];
3737
out_lod[0][i+1] = lod_offset;
3838
}
3939
return out_lod;
4040
}
4141

4242
template <typename Place, typename T>
43-
class SubSequenceOpKernel : public framework::OpKernel<T> {
43+
class SequenceSliceOpKernel : public framework::OpKernel<T> {
4444
public:
4545
void Compute(const framework::ExecutionContext& ctx) const override {
4646
auto* in = ctx.Input<LoDTensor>("X");
47-
std::vector<int> offsets = ctx.Attr<std::vector<int>>("offset");
48-
std::vector<int> sizes = ctx.Attr<std::vector<int>>("size");
47+
auto* offset = ctx.Input<Tensor>("Offset");
48+
auto* length = ctx.Input<Tensor>("Length");
4949
auto* out = ctx.Output<LoDTensor>("Out");
5050

51-
auto offset_len = offsets.size();
52-
auto size_len = sizes.size();
51+
const int64_t* offset_data = offset->data<int64_t>();
52+
const int64_t* length_data = length->data<int64_t>();
53+
54+
if (platform::is_gpu_place(ctx.GetPlace())) {
55+
framework::Tensor offset_cpu;
56+
offset_cpu.mutable_data<T>(offset->dims(), platform::CPUPlace());
57+
offset_cpu.CopyFrom(*offset, platform::CPUPlace(), ctx.device_context());
58+
offset_data = offset_cpu.data<int64_t>();
59+
60+
framework::Tensor length_cpu;
61+
length_cpu.mutable_data<T>(length->dims(), platform::CPUPlace());
62+
length_cpu.CopyFrom(*length, platform::CPUPlace(), ctx.device_context());
63+
length_data = length_cpu.data<int64_t>();
64+
}
5365

5466
auto lod = in->lod();
5567
auto n = lod[0].size() - 1;
5668

5769
PADDLE_ENFORCE_EQ(lod.size(), 1UL, "Only support one level sequence now.");
58-
PADDLE_ENFORCE_EQ(n, offset_len,
59-
"The length of input and offset should be the same")
60-
PADDLE_ENFORCE_EQ(n, size_len,
61-
"The length of input and size should be the same")
70+
PADDLE_ENFORCE_EQ(offset->dims().size(), 1UL,
71+
"Only support one level sequence now.");
72+
PADDLE_ENFORCE_EQ(length->dims().size(), 1UL,
73+
"Only support one level sequence now.");
74+
PADDLE_ENFORCE_EQ(
75+
n, length->dims()[0],
76+
"The size of input-sequence and length-array should be the same")
77+
PADDLE_ENFORCE_EQ(
78+
n, offset->dims()[0],
79+
"The size of input-sequence and offset-array should be the same")
6280

6381
for (size_t i = 0; i < n; ++i) {
64-
auto offset = offsets[i];
65-
auto size = sizes[i];
66-
PADDLE_ENFORCE_LT(lod[0][i] + offset + size, lod[0][i + 1],
67-
"The target tensor's length overflow")
82+
PADDLE_ENFORCE_LT(0, offset_data[i], "The offset must greater than zero")
83+
PADDLE_ENFORCE_LT(0, length_data[i], "The length must greater than zero")
84+
PADDLE_ENFORCE_LT(lod[0][i] + offset_data[i] + length_data[i],
85+
lod[0][i + 1], "The target tensor's length overflow")
6886
}
6987

7088
out->mutable_data<T>(ctx.GetPlace());
71-
auto out_lod = subsequenceLoD(in, offsets, sizes);
89+
auto out_lod = SequenceSliceLoD(*in, offset_data, length_data);
7290
out->set_lod(out_lod);
91+
math::SetConstant<Place, T> set_zero;
92+
set_zero(ctx.device_context(), out, static_cast<T>(0));
7393

7494
auto in_stride = framework::stride(in->dims());
7595
auto out_stride = framework::stride(out->dims());
7696

7797
size_t out_offset = 0;
7898
for (size_t i = 0; i < n; ++i) {
79-
auto offset = offsets[i];
80-
auto size = sizes[i];
81-
82-
Tensor in_t = in->Slice(static_cast<int>(lod[0][i] + offset),
83-
static_cast<int>(lod[0][i] + offset + size));
99+
Tensor in_t =
100+
in->Slice(static_cast<int>(lod[0][i] + offset_data[i]),
101+
static_cast<int>(lod[0][i] + offset_data[i] +
102+
length_data[i]));
84103

85104
StridedMemcpy<T>(ctx.device_context(), in_t.data<T>(),
86105
in_stride, in_t.dims(), out_stride,
87106
out->data<T>() + out_offset);
88-
out_offset += size * in_stride[0];
107+
out_offset += length_data[i] * in_stride[0];
89108
}
90109
}
91110
};
92111

93112
template <typename Place, typename T>
94-
class SubSequenceGradOpKernel : public framework::OpKernel<T> {
113+
class SequenceSliceGradOpKernel : public framework::OpKernel<T> {
95114
public:
96115
void Compute(const framework::ExecutionContext& ctx) const override {
97116
auto* in = ctx.Input<LoDTensor>("X");
98-
std::vector<int> offsets = ctx.Attr<std::vector<int>>("offset");
99-
std::vector<int> sizes = ctx.Attr<std::vector<int>>("size");
117+
auto* offset = ctx.Input<Tensor>("Offset");
118+
auto* length = ctx.Input<Tensor>("Length");
100119
auto* out_grad =
101120
ctx.Input<framework::LoDTensor>(framework::GradVarName("Out"));
102121
auto* x_grad =
103122
ctx.Output<framework::LoDTensor>(framework::GradVarName("X"));
104123

105-
auto offset_len = offsets.size();
106-
auto size_len = sizes.size();
124+
const int64_t* offset_data = offset->data<int64_t>();
125+
const int64_t* length_data = length->data<int64_t>();
107126

108-
auto lod = in->lod();
109-
auto n = lod[0].size() - 1;
127+
if (platform::is_gpu_place(ctx.GetPlace())) {
128+
framework::Tensor offset_cpu;
129+
offset_cpu.mutable_data<T>(offset->dims(), platform::CPUPlace());
130+
offset_cpu.CopyFrom(*offset, platform::CPUPlace(), ctx.device_context());
131+
offset_data = offset_cpu.data<int64_t>();
110132

111-
// check input data format
112-
PADDLE_ENFORCE_EQ(lod.size(), 1UL, "Only support one level sequence now.");
113-
PADDLE_ENFORCE_EQ(n, offset_len,
114-
"The length of input and offset should be the same")
115-
PADDLE_ENFORCE_EQ(n, size_len,
116-
"The length of input and size should be the same")
117-
118-
for (size_t i = 0; i < n; ++i) {
119-
auto offset = offsets[i];
120-
auto size = sizes[i];
121-
PADDLE_ENFORCE_LT(lod[0][i] + offset + size, lod[0][i + 1],
122-
"The target tensor's length overflow")
133+
framework::Tensor length_cpu;
134+
length_cpu.mutable_data<T>(length->dims(), platform::CPUPlace());
135+
length_cpu.CopyFrom(*length, platform::CPUPlace(), ctx.device_context());
136+
length_data = length_cpu.data<int64_t>();
123137
}
124138

125-
auto out_lod = subsequenceLoD(in, offsets, sizes);
139+
auto lod = in->lod();
140+
auto out_lod = SequenceSliceLoD(*in, offset_data, length_data);
126141

127142
x_grad->set_lod(lod);
128143
x_grad->mutable_data<T>(ctx.GetPlace());
129-
auto temp = framework::EigenVector<T>::Flatten(*x_grad);
130-
temp.device(ctx.GetEigenDevice<Place>()) = temp.constant(static_cast<T>(0));
144+
math::SetConstant<Place, T> set_zero;
145+
set_zero(ctx.device_context(), x_grad, static_cast<T>(0));
131146

132147
auto out_grad_stride = framework::stride(out_grad->dims());
133148

@@ -139,11 +154,9 @@ class SubSequenceGradOpKernel : public framework::OpKernel<T> {
139154

140155
auto x_grad_stride = framework::stride(x_grad->dims());
141156

142-
auto offset = offsets[i];
143-
auto size = sizes[i];
144-
145-
Tensor x_grad_t = x_grad->Slice(static_cast<int>(lod[0][i] + offset),
146-
static_cast<int>(lod[0][i] + offset + size));
157+
Tensor x_grad_t = x_grad->Slice(
158+
static_cast<int>(lod[0][i] + offset_data[i]),
159+
static_cast<int>(lod[0][i] + offset_data[i] + length_data[i]));
147160

148161
StridedMemcpy<T>(ctx.device_context(), out_grad_t.data<T>(),
149162
out_grad_stride, out_grad_t.dims(), x_grad_stride,

0 commit comments

Comments
 (0)