tensor_test.cc 9.9 KB
Newer Older
1
//  Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
D
dzhwinter 已提交
2 3 4 5 6 7 8 9 10 11 12 13
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
F
fengjiayi 已提交
14

Y
Yi Wang 已提交
15
#include "paddle/fluid/framework/tensor.h"
W
wanghuancoder 已提交
16

F
fengjiayi 已提交
17
#include <gtest/gtest.h>
18
#include <string>
W
wanghuancoder 已提交
19 20 21 22 23 24

namespace paddle {
namespace platform {
struct float16;
}  // namespace platform
}  // namespace paddle
F
fengjiayi 已提交
25

26 27 28
namespace framework = paddle::framework;
namespace platform = paddle::platform;

F
fengjiayi 已提交
29
TEST(Tensor, Dims) {
30
  framework::Tensor tt;
31
  tt.Resize({2, 3, 4});
32
  framework::DDim dims = tt.dims();
F
fengjiayi 已提交
33 34 35 36 37 38 39
  ASSERT_EQ(arity(dims), 3);
  for (int i = 0; i < 3; ++i) {
    EXPECT_EQ(i + 2, dims[i]);
  }
}

TEST(Tensor, DataAssert) {
40
  framework::Tensor src_tensor;
F
fengjiayi 已提交
41

42 43
  bool caught = false;
  try {
F
fengjiayi 已提交
44
    src_tensor.data<double>();
45
  } catch (platform::EnforceNotMet& err) {
46
    caught = true;
47
    std::string ex_msg = err.what();
48 49
    EXPECT_TRUE(ex_msg.find("holder_ should not be null") != std::string::npos);
    EXPECT_TRUE(ex_msg.find("Tensor holds no memory. Call "
50
                            "Tensor::mutable_data firstly.") !=
51
                std::string::npos);
52 53
  }
  ASSERT_TRUE(caught);
F
fengjiayi 已提交
54 55 56
}

TEST(Tensor, MutableData) {
57
  {
58
    framework::Tensor src_tensor;
59 60 61
    float* p1 = nullptr;
    float* p2 = nullptr;
    // initialization
62 63
    p1 = src_tensor.mutable_data<float>(framework::make_ddim({1, 2, 3}),
                                        platform::CPUPlace());
64
    auto p1_holder = src_tensor.Holder();
65
    EXPECT_NE(p1, nullptr);
F
fengjiayi 已提交
66
    // set src_tensor a new dim with large size
67
    // momery is supposed to be re-allocated
68 69
    p2 = src_tensor.mutable_data<float>(framework::make_ddim({3, 4}),
                                        platform::CPUPlace());
70
    EXPECT_NE(p2, nullptr);
71 72
    auto p2_holder1 = src_tensor.Holder();
    EXPECT_NE(p1_holder.get(), p2_holder1.get());
F
fengjiayi 已提交
73
    // set src_tensor a new dim with same size
74
    // momery block is supposed to be unchanged
75 76
    p1 = src_tensor.mutable_data<float>(framework::make_ddim({2, 2, 3}),
                                        platform::CPUPlace());
77 78
    auto p2_holder2 = src_tensor.Holder();
    EXPECT_EQ(p2_holder1.get(), p2_holder2.get());
F
fengjiayi 已提交
79
    // set src_tensor a new dim with smaller size
80
    // momery block is supposed to be unchanged
81 82
    p2 = src_tensor.mutable_data<float>(framework::make_ddim({2, 2}),
                                        platform::CPUPlace());
83
    auto p2_holder3 = src_tensor.Holder();
84
    EXPECT_EQ(p1, p2);
85
    EXPECT_EQ(p2_holder2.get(), p2_holder3.get());
D
dzhwinter 已提交
86 87 88 89 90 91 92 93

    float* p3 = nullptr;
    float* p4 = nullptr;
    // set src_tensor a different type but smaller size.
    // memory block is supposed to be unchanged.
    auto* tmp = src_tensor.mutable_data<uint8_t>(framework::make_ddim({2, 2}),
                                                 platform::CPUPlace());
    p3 = reinterpret_cast<float*>(tmp);
94
    auto p3_holder1 = src_tensor.Holder();
D
dzhwinter 已提交
95
    EXPECT_EQ(p1, p3);
96
    EXPECT_EQ(p2_holder3.get(), p3_holder1.get());
D
dzhwinter 已提交
97 98 99 100 101

    // set src_tensor a different type but bigger size.
    // memory block is supposed to be changed.
    auto* tmp2 = src_tensor.mutable_data<double>(
        framework::make_ddim({2, 2, 3}), platform::CPUPlace());
102
    auto p3_holder2 = src_tensor.Holder();
D
dzhwinter 已提交
103 104
    p4 = reinterpret_cast<float*>(tmp2);
    EXPECT_NE(p1, p4);
105
    EXPECT_NE(p3_holder1.get(), p3_holder2.get());
106
  }
X
Xin Pan 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119
  // Not sure if it's desired, but currently, Tensor type can be changed.
  {
    framework::Tensor src_tensor;
    int8_t* p1 = src_tensor.mutable_data<int8_t>(framework::make_ddim({1}),
                                                 platform::CPUPlace());
    EXPECT_NE(p1, nullptr);
    *p1 = 1;

    uint8_t* p2 = src_tensor.mutable_data<uint8_t>(framework::make_ddim({1}),
                                                   platform::CPUPlace());
    EXPECT_NE(p2, nullptr);
    EXPECT_EQ(static_cast<int>(p2[0]), 1);
  }
L
liaogang 已提交
120

121
#ifdef PADDLE_WITH_CUDA
122
  {
123
    framework::Tensor src_tensor;
124 125 126
    float* p1 = nullptr;
    float* p2 = nullptr;
    // initialization
127 128
    p1 = src_tensor.mutable_data<float>(framework::make_ddim({1, 2, 3}),
                                        platform::CUDAPlace());
129
    auto p1_holder = src_tensor.Holder();
130 131 132
    EXPECT_NE(p1, nullptr);
    // set src_tensor a new dim with large size
    // momery is supposed to be re-allocated
133
    p2 = src_tensor.mutable_data<float>(framework::make_ddim({3, 1024}),
134
                                        platform::CUDAPlace());
135
    auto p2_holder = src_tensor.Holder();
136
    EXPECT_NE(p2, nullptr);
137
    EXPECT_NE(p1_holder.get(), p2_holder.get());
138 139
    // set src_tensor a new dim with same size
    // momery block is supposed to be unchanged
140 141
    p1 = src_tensor.mutable_data<float>(framework::make_ddim({2, 2, 3}),
                                        platform::CUDAPlace());
142 143 144
    EXPECT_EQ(p1, p2);
    // set src_tensor a new dim with smaller size
    // momery block is supposed to be unchanged
145 146
    p2 = src_tensor.mutable_data<float>(framework::make_ddim({2, 2}),
                                        platform::CUDAPlace());
147 148 149
    EXPECT_EQ(p1, p2);
  }
#endif
F
fengjiayi 已提交
150
}
F
fengjiayi 已提交
151

F
fengjiayi 已提交
152
TEST(Tensor, ShareDataWith) {
F
fengjiayi 已提交
153
  {
154 155
    framework::Tensor src_tensor;
    framework::Tensor dst_tensor;
F
fengjiayi 已提交
156 157 158
    // Try to share data form uninitialized tensor
    bool caught = false;
    try {
159
      dst_tensor.ShareDataWith(src_tensor);
160
    } catch (paddle::platform::EnforceNotMet& err) {
F
fengjiayi 已提交
161
      caught = true;
162
      std::string ex_msg = err.what();
163 164 165
      EXPECT_TRUE(ex_msg.find("holder_ should not be null") !=
                  std::string::npos);
      EXPECT_TRUE(ex_msg.find("Tensor holds no memory. Call "
166
                              "Tensor::mutable_data firstly.") !=
167
                  std::string::npos);
F
fengjiayi 已提交
168 169 170
    }
    ASSERT_TRUE(caught);

171 172
    src_tensor.mutable_data<int>(framework::make_ddim({2, 3, 4}),
                                 platform::CPUPlace());
173
    dst_tensor.ShareDataWith(src_tensor);
F
fengjiayi 已提交
174 175 176
    ASSERT_EQ(src_tensor.data<int>(), dst_tensor.data<int>());
  }

177
#ifdef PADDLE_WITH_CUDA
178
  {
179 180 181 182
    framework::Tensor src_tensor;
    framework::Tensor dst_tensor;
    src_tensor.mutable_data<int>(framework::make_ddim({2, 3, 4}),
                                 platform::CUDAPlace());
183
    dst_tensor.ShareDataWith(src_tensor);
184 185 186
    ASSERT_EQ(src_tensor.data<int>(), dst_tensor.data<int>());
  }
#endif
F
fengjiayi 已提交
187 188 189 190
}

TEST(Tensor, Slice) {
  {
191 192 193 194 195
    framework::Tensor src_tensor;
    src_tensor.mutable_data<int>(framework::make_ddim({5, 3, 4}),
                                 platform::CPUPlace());
    framework::Tensor slice_tensor = src_tensor.Slice(1, 3);
    framework::DDim slice_dims = slice_tensor.dims();
F
fengjiayi 已提交
196 197 198 199 200 201 202 203
    ASSERT_EQ(arity(slice_dims), 3);
    EXPECT_EQ(slice_dims[0], 2);
    EXPECT_EQ(slice_dims[1], 3);
    EXPECT_EQ(slice_dims[2], 4);

    uintptr_t src_data_address =
        reinterpret_cast<uintptr_t>(src_tensor.data<int>());
    uintptr_t src_mutable_data_address = reinterpret_cast<uintptr_t>(
204
        src_tensor.mutable_data<int>(src_tensor.dims(), platform::CPUPlace()));
F
fengjiayi 已提交
205 206
    uintptr_t slice_data_address =
        reinterpret_cast<uintptr_t>(slice_tensor.data<int>());
207 208 209
    uintptr_t slice_mutable_data_address =
        reinterpret_cast<uintptr_t>(slice_tensor.mutable_data<int>(
            slice_tensor.dims(), platform::CPUPlace()));
F
fengjiayi 已提交
210 211 212 213 214
    EXPECT_EQ(src_data_address, src_mutable_data_address);
    EXPECT_EQ(slice_data_address, slice_mutable_data_address);
    EXPECT_EQ(src_data_address + 3 * 4 * 1 * sizeof(int), slice_data_address);
  }

215
#ifdef PADDLE_WITH_CUDA
216
  {
217 218 219 220 221
    framework::Tensor src_tensor;
    src_tensor.mutable_data<double>(framework::make_ddim({6, 9}),
                                    platform::CUDAPlace());
    framework::Tensor slice_tensor = src_tensor.Slice(2, 6);
    framework::DDim slice_dims = slice_tensor.dims();
222 223 224
    ASSERT_EQ(arity(slice_dims), 2);
    EXPECT_EQ(slice_dims[0], 4);
    EXPECT_EQ(slice_dims[1], 9);
F
fengjiayi 已提交
225

226 227
    uintptr_t src_data_address =
        reinterpret_cast<uintptr_t>(src_tensor.data<double>());
228 229 230
    uintptr_t src_mutable_data_address =
        reinterpret_cast<uintptr_t>(src_tensor.mutable_data<double>(
            src_tensor.dims(), platform::CUDAPlace()));
231 232
    uintptr_t slice_data_address =
        reinterpret_cast<uintptr_t>(slice_tensor.data<double>());
233 234 235
    uintptr_t slice_mutable_data_address =
        reinterpret_cast<uintptr_t>(slice_tensor.mutable_data<double>(
            slice_tensor.dims(), platform::CUDAPlace()));
236 237 238 239 240
    EXPECT_EQ(src_data_address, src_mutable_data_address);
    EXPECT_EQ(slice_data_address, slice_mutable_data_address);
    EXPECT_EQ(src_data_address + 9 * 2 * sizeof(double), slice_data_address);
  }
#endif
F
fengjiayi 已提交
241 242
}

F
fengjiayi 已提交
243
TEST(Tensor, ReshapeToMatrix) {
244 245
  framework::Tensor src;
  int* src_ptr = src.mutable_data<int>({2, 3, 4, 9}, platform::CPUPlace());
F
WIP  
fengjiayi 已提交
246 247 248
  for (int i = 0; i < 2 * 3 * 4 * 9; ++i) {
    src_ptr[i] = i;
  }
249
  framework::Tensor res = framework::ReshapeToMatrix(src, 2);
F
WIP  
fengjiayi 已提交
250 251
  ASSERT_EQ(res.dims()[0], 2 * 3);
  ASSERT_EQ(res.dims()[1], 4 * 9);
Z
zchen0211 已提交
252
}
D
dzhwinter 已提交
253 254

TEST(Tensor, Layout) {
255
  framework::Tensor src;
M
mozga-intel 已提交
256
  ASSERT_EQ(src.layout(), framework::DataLayout::kNCHW);
257 258
  src.set_layout(framework::DataLayout::kAnyLayout);
  ASSERT_EQ(src.layout(), framework::DataLayout::kAnyLayout);
D
dzhwinter 已提交
259
}
D
dzhwinter 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272 273

TEST(Tensor, FP16) {
  using platform::float16;
  framework::Tensor src;
  float16* src_ptr = src.mutable_data<float16>({2, 3}, platform::CPUPlace());
  for (int i = 0; i < 2 * 3; ++i) {
    src_ptr[i] = static_cast<float16>(i);
  }
  EXPECT_EQ(src.memory_size(), 2 * 3 * sizeof(float16));
  // EXPECT a human readable error message
  // src.data<uint8_t>();
  // Tensor holds the wrong type, it holds N6paddle8platform7float16E at
  // [/paddle/Paddle/paddle/fluid/framework/tensor_impl.h:43]
}