提交 a94b3dd9 编写于 作者: W wanghaoshuang

Refine comments and function name

1. Add more comments and exmples
2. Rename repeat_lod to expand_lod
3. Remove unused head file
上级 a5adffd0
......@@ -103,28 +103,28 @@ void LoDTensor::ShrinkInLevel(size_t level, size_t elem_begin,
lod_ = new_lod;
}
Vector<size_t> repeat_lod(Vector<size_t> data, Vector<size_t> starts,
Vector<size_t> times, bool is_first) {
Vector<size_t> expand_lod(Vector<size_t> level, Vector<size_t> starts,
Vector<size_t> scales, bool repeat) {
Vector<size_t> result;
result.push_back(data[0]);
result.push_back(level[0]);
size_t p = 0, start = 0, end = 0;
if (is_first == true) {
for (size_t i = 0; i < times.size(); ++i) {
result.push_back(result.back() + times[i] * (data[i + 1] - data[i]));
if (!repeat) {
for (size_t i = 0; i < scales.size(); ++i) {
result.push_back(result.back() + scales[i] * (level[i + 1] - level[i]));
}
} else {
for (size_t i = 0; i < times.size(); ++i) {
while (starts[i] != data[p] && p < data.size()) {
for (size_t i = 0; i < scales.size(); ++i) {
while (starts[i] != level[p] && p < level.size()) {
++p;
}
start = p;
while (starts[i + 1] != data[p] && p < data.size()) {
while (starts[i + 1] != level[p] && p < level.size()) {
++p;
}
end = p + 1;
for (size_t j = 0; j < times[i]; ++j) {
for (size_t j = 0; j < scales[i]; ++j) {
for (size_t index = start; index < end - 1; ++index) {
result.push_back(result.back() + data[index + 1] - data[index]);
result.push_back(result.back() + level[index + 1] - level[index]);
}
}
}
......
......@@ -15,9 +15,6 @@
#pragma once
#include <memory>
#include "paddle/memory/memcpy.h"
#include "paddle/platform/device_context.h"
#include "paddle/platform/place.h"
#ifdef PADDLE_WITH_CUDA
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
......@@ -126,8 +123,8 @@ class LoDTensor : public Tensor {
LoD lod_;
};
Vector<size_t> repeat_lod(Vector<size_t> data, Vector<size_t> starts,
Vector<size_t> times, bool is_first);
Vector<size_t> expand_lod(Vector<size_t> level, Vector<size_t> starts,
Vector<size_t> scales, bool repeat);
} // namespace framework
} // namespace paddle
......@@ -50,28 +50,68 @@ class SeqExpandOpMaker : public framework::OpProtoAndCheckerMaker {
SeqExpandOpMaker(framework::OpProto* proto,
framework::OpAttrChecker* op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) {
// TODO(wanghaoshuang): Add more comments
AddInput("X", "The input('X') of seq_expand op.");
AddInput("Y", "The reference input('Y') of seq_expand op.");
AddOutput("Out", "The output of seq_expand op.");
AddAttr<int>("repeat", "repeat times").SetDefault(0);
AddInput(
"X",
"The input('X') of seq_expand op. It can be LoDTensor or base Tensor.");
AddInput(
"Y",
"The reference input('Y') of seq_expand op."
"It must be a LoDTensor with k-level(k>0)."
"This reference input is essential if 'repeat' attribute is not "
"configured."
"Input(X) will be expanded by LoD of input(Y) while repeat == 0.");
AddOutput("Out",
"The output of seq_expand op."
"The output is a (k+1)-level LoDTensor"
"while input(X) being k-level LoDTensor."
"(Given base tensor is 0-level LoDTensor.)");
AddAttr<int>("repeat",
"(type:int; default value: 0)"
"Repeatting times of each element while expanding input(X)."
"It works while input(Y) is not configured.")
.SetDefault(0);
AddComment(R"DOC(
As an example:
Expand k-level LoDTensor to (k+1)-level LoDTensor
by lod of input(Y) or 'repeat' attribute.
Given:
X.data = [1, 2 , 3, 4]
X.lod = [[0, 3, 4], [0, 1, 3, 4]]
Case 1:
Given a 2-level LoDTensor X:
X.data = [1, 2 , 3, 4]
X.lod = [[0, 3, 4], [0, 1, 3, 4]]
and
repeat = 2
then we get
Out.data = [1, 2, 3, 1, 2, 3, 4, 4]
Out.lod = [[0, 6, 8], [0, 3, 6, 7, 8], [0, 1, 3, 4, 6, 7, 8]]
repeat = 2
then we get 3-level LoDTensor
Out.data = [1, 2, 3, 1, 2, 3, 4, 4]
Out.lod = [[0, 6, 8],
[0, 3, 6, 7, 8],
[0, 1, 3, 4, 6, 7, 8]]
Case 2:
Given 2-level a LoDTensor X
X.data = [1, 2, 3, 4]
X.lod = [[0, 3, 4], [0, 1, 3, 4]]
and
Y.lod = [[0, 6, 8],
[0, 3, 6, 7, 8],
[0,1,3,4,6,7,8]]
then we get 3-level LoDTensor
Out.data = [1, 2, 3, 1, 2, 3, 4, 4]
Out.lod = [[0, 6, 8],
[0, 3, 6, 7, 8],
[0, 1, 3, 4, 6, 7, 8]]
Case 3:
Given a 0-level LoDTensor X
X.data = [1, 2, 3, 4]
X.lod = NULL
and
repeat = 2
then we get 1-level LoDTensor
Out.data = [1, 1, 2, 2, 3, 3, 4, 4]
Out.lod = [[0, 2, 4, 6, 8]]
)DOC");
}
......
......@@ -44,10 +44,10 @@ class SeqExpandKernel : public framework::OpKernel<T> {
}
size_t repeat = static_cast<size_t>(context.Attr<int>("repeat"));
framework::Vector<size_t> repeats;
framework::Vector<size_t> scales;
if (repeat != 0) {
for (int i = 0; i < x_lod[0].size() - 1; ++i) {
repeats.push_back(repeat);
scales.push_back(repeat);
}
std::vector<int64_t> dims = framework::vectorize(x->dims());
dims[0] = dims[0] * repeat;
......@@ -57,18 +57,18 @@ class SeqExpandKernel : public framework::OpKernel<T> {
auto* y = context.Input<LoDTensor>("Y");
auto y_lod = y->lod();
for (int i = 0; i < y_lod[0].size() - 1; ++i) {
repeats.push_back((y_lod[0][i + 1] - y_lod[0][i]) /
(x_lod[0][i + 1] - x_lod[0][i]));
scales.push_back((y_lod[0][i + 1] - y_lod[0][i]) /
(x_lod[0][i + 1] - x_lod[0][i]));
}
out->Resize(y->dims());
}
framework::LoD out_lod;
auto level0 = framework::repeat_lod(x_lod[0], x_lod[0], repeats, true);
auto level0 = framework::expand_lod(x_lod[0], x_lod[0], scales, false);
out_lod.push_back(level0);
for (int i = 1; i < x_lod.size(); ++i) {
out_lod.push_back(
framework::repeat_lod(x_lod[i], x_lod[0], repeats, false));
framework::expand_lod(x_lod[i], x_lod[0], scales, true));
}
size_t element_len = framework::product(x_dims) / x_dims[0];
......@@ -77,9 +77,9 @@ class SeqExpandKernel : public framework::OpKernel<T> {
// copy data
Place place = boost::get<Place>(context.GetPlace());
size_t count = 0;
for (size_t i = 0; i < repeats.size(); ++i) {
for (size_t i = 0; i < scales.size(); ++i) {
count = element_len * (x_lod[0][i + 1] - x_lod[0][i]);
for (size_t j = 0; j < repeats[i]; ++j) {
for (size_t j = 0; j < scales[i]; ++j) {
memory::Copy(place, out_data, place, x_data, sizeof(T) * count);
out_data += count;
}
......@@ -95,9 +95,9 @@ class SeqExpandGradKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& context) const override {
auto* d_out = context.Input<LoDTensor>(framework::GradVarName("Out"));
auto* d_x = context.Output<LoDTensor>(framework::GradVarName("X"));
auto* x = context.Input<LoDTensor>("X");
auto* out = context.Input<LoDTensor>("Out");
auto* d_x = context.Output<LoDTensor>(framework::GradVarName("X"));
auto out_lod = out->lod();
d_x->set_lod(x->lod());
const T* d_out_data = d_out->data<T>();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册