Skip to content

Commit d810849

Browse files
authored
Merge pull request #2953 from wangkuiyi/tensor_type_to_eigen
Refactorize Tensor to Eigen convesion
2 parents 2e2a674 + d6d057b commit d810849

File tree

7 files changed

+203
-144
lines changed

7 files changed

+203
-144
lines changed

paddle/framework/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ cc_test(enforce_test SRCS enforce_test.cc DEPS enforce)
44
cc_library(ddim SRCS ddim.cc DEPS eigen3)
55
cc_test(ddim_test SRCS ddim_test.cc DEPS ddim)
66
nv_test(dim_test SRCS dim_test.cu DEPS ddim)
7+
78
cc_library(tensor SRCS tensor.cc DEPS ddim place enforce paddle_memory)
89
cc_test(tensor_test SRCS tensor_test.cc DEPS tensor)
10+
cc_test(eigen_test SRCS eigen_test.cc DEPS tensor)
11+
912
cc_test(variable_test SRCS variable_test.cc)
1013
cc_test(scope_test SRCS scope_test.cc)
1114
proto_library(attr_type SRCS attr_type.proto)

paddle/framework/ddim.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,6 @@ int arity(const DDim& ddim);
119119

120120
std::ostream& operator<<(std::ostream&, const DDim&);
121121

122-
template <int NDIMS>
123-
Eigen::DSizes<Eigen::DenseIndex, NDIMS> ToEigenDSizes(const DDim& dims) {
124-
int rank = arity(dims);
125-
PADDLE_ENFORCE(rank == NDIMS, "DDim and NDIMS must be same");
126-
Eigen::DSizes<Eigen::DenseIndex, NDIMS> dsizes;
127-
for (int d = 0; d < rank; d++) {
128-
dsizes[d] = dims[d];
129-
}
130-
return dsizes;
131-
}
132-
133122
} // namespace framework
134123
} // namespace paddle
135124

paddle/framework/eigen.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License. */
14+
15+
#pragma once
16+
17+
#include "paddle/framework/tensor.h"
18+
#include "unsupported/Eigen/CXX11/Tensor"
19+
20+
namespace paddle {
21+
namespace framework {
22+
23+
// EigenDim converts paddle::platform::DDim into Eigen::DSizes.
24+
template <int D>
25+
struct EigenDim {
26+
using Type = Eigen::DSizes<Eigen::DenseIndex, D>;
27+
28+
static Type From(const DDim& dims) {
29+
PADDLE_ENFORCE(arity(dims) == D, "D must match arity(DDim)");
30+
Type ret;
31+
for (int d = 0; d < arity(dims); d++) {
32+
ret[d] = dims[d];
33+
}
34+
return ret;
35+
}
36+
};
37+
38+
// Interpret paddle::platform::Tensor as EigenTensor and EigenConstTensor.
39+
template <typename T, size_t D, int MajorType = Eigen::RowMajor,
40+
typename IndexType = Eigen::DenseIndex>
41+
struct EigenTensor {
42+
// TODO(qijun) Now, default type in unaligned, and we will make a benchmark on
43+
// the speed of aligned and unaligned version in future.
44+
using Type = Eigen::TensorMap<Eigen::Tensor<T, D, MajorType, IndexType>>;
45+
46+
using ConstType =
47+
Eigen::TensorMap<Eigen::Tensor<const T, D, MajorType, IndexType>>;
48+
49+
static Type From(Tensor& tensor, DDim dims) {
50+
return Type(tensor.data<T>(), EigenDim<D>::From(dims));
51+
}
52+
53+
static Type From(Tensor& tensor) { return From(tensor, tensor.dims_); }
54+
55+
static ConstType From(const Tensor& tensor, DDim dims) {
56+
return ConstType(tensor.data<T>(), EigenDim<D>::From(dims));
57+
}
58+
59+
static ConstType From(const Tensor& tensor) {
60+
return From(tensor, tensor.dims_);
61+
}
62+
};
63+
64+
template <typename T, int MajorType = Eigen::RowMajor,
65+
typename IndexType = Eigen::DenseIndex>
66+
struct EigenVector : public EigenTensor<T, 1, MajorType, IndexType> {
67+
// Flatten is to reshape a Tensor into a one dimension EigenVector
68+
static typename EigenTensor<T, 1>::Type Flatten(Tensor& tensor) {
69+
return EigenTensor<T, 1>::From(
70+
tensor, make_ddim({static_cast<int>(product(tensor.dims_))}));
71+
}
72+
73+
static typename EigenTensor<T, 1>::ConstType Flatten(const Tensor& tensor) {
74+
return EigenTensor<T, 1>::From(
75+
tensor, make_ddim({static_cast<int>(product(tensor.dims_))}));
76+
}
77+
};
78+
79+
template <typename T, int MajorType = Eigen::RowMajor,
80+
typename IndexType = Eigen::DenseIndex>
81+
using EigenMatrix = EigenTensor<T, 2, MajorType, IndexType>;
82+
83+
} // namespace framework
84+
} // namespace paddle

paddle/framework/eigen_test.cc

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
#include "paddle/framework/eigen.h"
15+
#include <gtest/gtest.h>
16+
17+
namespace paddle {
18+
namespace framework {
19+
20+
TEST(EigenDim, From) {
21+
EigenDim<3>::Type ed = EigenDim<3>::From(make_ddim({1, 2, 3}));
22+
ASSERT_EQ(1, ed[0]);
23+
ASSERT_EQ(2, ed[1]);
24+
ASSERT_EQ(3, ed[2]);
25+
}
26+
27+
TEST(Eigen, Tensor) {
28+
Tensor t;
29+
float* p = t.mutable_data<float>(make_ddim({1, 2, 3}), platform::CPUPlace());
30+
for (int i = 0; i < 1 * 2 * 3; i++) {
31+
p[i] = static_cast<float>(i);
32+
}
33+
34+
EigenTensor<float, 3>::Type et = EigenTensor<float, 3>::From(t);
35+
36+
ASSERT_EQ(1, et.dimension(0));
37+
ASSERT_EQ(2, et.dimension(1));
38+
ASSERT_EQ(3, et.dimension(2));
39+
40+
for (int i = 0; i < 1; i++) {
41+
for (int j = 0; j < 2; j++) {
42+
for (int k = 0; k < 3; k++) {
43+
ASSERT_NEAR((i * 2 + j) * 3 + k, et(i, j, k), 1e-6f);
44+
}
45+
}
46+
}
47+
}
48+
49+
TEST(Eigen, VectorFrom) {
50+
Tensor t;
51+
float* p = t.mutable_data<float>(make_ddim({6}), platform::CPUPlace());
52+
for (int i = 0; i < 6; i++) {
53+
p[i] = static_cast<float>(i);
54+
}
55+
56+
EigenVector<float>::Type ev = EigenVector<float>::From(t);
57+
58+
ASSERT_EQ(6, ev.dimension(0));
59+
60+
for (int i = 0; i < 6; i++) {
61+
ASSERT_NEAR(i, ev(i), 1e-6f);
62+
}
63+
}
64+
65+
TEST(Eigen, VectorFlatten) {
66+
Tensor t;
67+
float* p = t.mutable_data<float>(make_ddim({1, 2, 3}), platform::CPUPlace());
68+
for (int i = 0; i < 1 * 2 * 3; i++) {
69+
p[i] = static_cast<float>(i);
70+
}
71+
72+
EigenVector<float>::Type ev = EigenVector<float>::Flatten(t);
73+
74+
ASSERT_EQ(1 * 2 * 3, ev.dimension(0));
75+
76+
for (int i = 0; i < 1 * 2 * 3; i++) {
77+
ASSERT_NEAR(i, ev(i), 1e-6f);
78+
}
79+
}
80+
81+
TEST(Eigen, Matrix) {
82+
Tensor t;
83+
float* p = t.mutable_data<float>(make_ddim({2, 3}), platform::CPUPlace());
84+
for (int i = 0; i < 2 * 3; i++) {
85+
p[i] = static_cast<float>(i);
86+
}
87+
88+
EigenMatrix<float>::Type em = EigenMatrix<float>::From(t);
89+
90+
ASSERT_EQ(2, em.dimension(0));
91+
ASSERT_EQ(3, em.dimension(1));
92+
93+
for (int i = 0; i < 2; i++) {
94+
for (int j = 0; j < 3; j++) {
95+
ASSERT_NEAR(i * 3 + j, em(i, j), 1e-6f);
96+
}
97+
}
98+
}
99+
100+
} // namespace framework
101+
} // namespace paddle

paddle/framework/tensor.h

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ limitations under the License. */
2020
#include <typeindex>
2121
#include "paddle/framework/ddim.h"
2222
#include "paddle/framework/enforce.h"
23-
#include "paddle/framework/tensor_types.h"
2423
#include "paddle/memory/memory.h"
2524
#include "paddle/platform/place.h"
2625
#include "unsupported/Eigen/CXX11/Tensor"
@@ -35,6 +34,15 @@ struct CastToPyBufferImpl;
3534
namespace framework {
3635

3736
class Tensor {
37+
template <bool less, size_t i, typename... args>
38+
friend struct paddle::pybind::details::CastToPyBufferImpl;
39+
40+
template <typename T, size_t D, int MajorType, typename IndexType>
41+
friend struct EigenTensor;
42+
43+
template <typename T, int MajorType, typename IndexType>
44+
friend struct EigenVector;
45+
3846
public:
3947
Tensor() : offset_(0) {}
4048

@@ -46,7 +54,7 @@ class Tensor {
4654
}
4755

4856
template <typename T>
49-
T* raw_data() const {
57+
T* data() {
5058
CheckDims<T>();
5159
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(holder_->ptr()) +
5260
offset_);
@@ -86,66 +94,6 @@ class Tensor {
8694
offset_);
8795
}
8896

89-
template <typename T, size_t NDIMS>
90-
typename TTypes<T, NDIMS>::Tensor shaped(DDim new_dims) {
91-
Eigen::array<Eigen::DenseIndex, NDIMS> dims =
92-
paddle::framework::ToEigenDSizes<NDIMS>(new_dims);
93-
return typename TTypes<T, NDIMS>::Tensor(raw_data<T>(), dims);
94-
}
95-
96-
template <typename T, size_t NDIMS>
97-
typename TTypes<T, NDIMS>::Tensor tensor() {
98-
return typename TTypes<T, NDIMS>::Tensor(
99-
raw_data<T>(), paddle::framework::ToEigenDSizes<NDIMS>(dims_));
100-
}
101-
102-
// flat to rank = 1
103-
template <typename T>
104-
typename TTypes<T>::Flat flat() {
105-
return shaped<T, 1>(make_ddim({static_cast<int>(product(dims_))}));
106-
}
107-
108-
// to TensorType Vec
109-
template <typename T>
110-
typename TTypes<T>::Vec vec() {
111-
return tensor<T, 1>();
112-
}
113-
114-
// to TensorType Matrix
115-
template <typename T>
116-
typename TTypes<T>::Matrix matrix() {
117-
return tensor<T, 2>();
118-
}
119-
120-
// const versions of all the methods above.
121-
template <typename T, size_t NDIMS>
122-
typename TTypes<T, NDIMS>::Tensor shaped(DDim new_dims) const {
123-
Eigen::array<Eigen::DenseIndex, NDIMS> dims =
124-
paddle::framework::ToEigenDSizes<NDIMS>(new_dims);
125-
return typename TTypes<T, NDIMS>::Tensor(data<T>(), dims);
126-
}
127-
128-
template <typename T, size_t NDIMS>
129-
typename TTypes<T, NDIMS>::ConstantTensor tensor() const {
130-
return typename TTypes<T, NDIMS>::Tensor(
131-
data<T>(), paddle::framework::ToEigenDSizes<NDIMS>(dims_));
132-
}
133-
134-
template <typename T>
135-
typename TTypes<T>::ConstFlat flat() const {
136-
return shaped<T, 1>(make_ddim({static_cast<int>(product(dims_))}));
137-
}
138-
139-
template <typename T>
140-
typename TTypes<T>::ConstVec vec() const {
141-
return tensor<T, 1>();
142-
}
143-
144-
template <typename T>
145-
typename TTypes<T>::ConstMatrix matrix() const {
146-
return tensor<T, 2>();
147-
}
148-
14997
template <typename T>
15098
void ShareDataFrom(const Tensor& src) {
15199
src.CheckDims<T>();
@@ -251,8 +199,6 @@ class Tensor {
251199
std::shared_ptr<Placeholder> holder_; // holds the memory block if allocated.
252200
DDim dims_;
253201
size_t offset_; // marks the begin of tensor data area.
254-
template <bool less, size_t i, typename... args>
255-
friend struct paddle::pybind::details::CastToPyBufferImpl;
256202
};
257203

258204
} // namespace framework

paddle/framework/tensor_types.h

Lines changed: 0 additions & 67 deletions
This file was deleted.

0 commit comments

Comments
 (0)