// Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. // // 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. #include "paddle/fluid/framework/tensor_util.h" #include "paddle/phi/core/tensor_utils.h" #include #include namespace platform = paddle::platform; TEST(DenseTensor, Dims) { phi::DenseTensor tt; tt.Resize({2, 3, 4}); phi::DDim dims = tt.dims(); ASSERT_EQ(arity(dims), 3); for (int i = 0; i < 3; ++i) { EXPECT_EQ(i + 2, dims[i]); } } TEST(DenseTensor, DataAssert) { phi::DenseTensor src_tensor; bool caught = false; try { src_tensor.data(); } catch (platform::EnforceNotMet& err) { caught = true; std::string ex_msg = err.what(); EXPECT_TRUE(ex_msg.find("Tensor holds no memory. Call " "Tensor::mutable_data firstly.") != std::string::npos); } ASSERT_TRUE(caught); } TEST(DenseTensor, MutableData) { { phi::DenseTensor src_tensor; float* p1 = nullptr; float* p2 = nullptr; // initialization p1 = src_tensor.mutable_data(common::make_ddim({1, 2, 3}), phi::CPUPlace()); auto p1_holder = src_tensor.Holder(); EXPECT_NE(p1, nullptr); // set src_tensor a new dim with large size // memory is supposed to be re-allocated p2 = src_tensor.mutable_data(common::make_ddim({3, 4}), phi::CPUPlace()); EXPECT_NE(p2, nullptr); auto p2_holder1 = src_tensor.Holder(); EXPECT_NE(p1_holder.get(), p2_holder1.get()); // set src_tensor a new dim with same size // memory block is supposed to be unchanged p1 = src_tensor.mutable_data(common::make_ddim({2, 2, 3}), phi::CPUPlace()); auto p2_holder2 = src_tensor.Holder(); EXPECT_EQ(p2_holder1.get(), p2_holder2.get()); // set src_tensor a new dim with smaller size // memory block is supposed to be unchanged p2 = src_tensor.mutable_data(common::make_ddim({2, 2}), phi::CPUPlace()); auto p2_holder3 = src_tensor.Holder(); EXPECT_EQ(p1, p2); EXPECT_EQ(p2_holder2.get(), p2_holder3.get()); 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(common::make_ddim({2, 2}), phi::CPUPlace()); p3 = reinterpret_cast(tmp); auto p3_holder1 = src_tensor.Holder(); EXPECT_EQ(p1, p3); EXPECT_EQ(p2_holder3.get(), p3_holder1.get()); // set src_tensor a different type but bigger size. // memory block is supposed to be changed. auto* tmp2 = src_tensor.mutable_data(common::make_ddim({2, 2, 3}), phi::CPUPlace()); auto p3_holder2 = src_tensor.Holder(); p4 = reinterpret_cast(tmp2); EXPECT_NE(p1, p4); EXPECT_NE(p3_holder1.get(), p3_holder2.get()); } // Not sure if it's desired, but currently, phi::DenseTensor type can be // changed. { phi::DenseTensor src_tensor; int8_t* p1 = src_tensor.mutable_data(common::make_ddim({1}), phi::CPUPlace()); EXPECT_NE(p1, nullptr); *p1 = 1; uint8_t* p2 = src_tensor.mutable_data(common::make_ddim({1}), phi::CPUPlace()); EXPECT_NE(p2, nullptr); EXPECT_EQ(static_cast(p2[0]), 1); } #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) { phi::DenseTensor src_tensor; float* p1 = nullptr; float* p2 = nullptr; // initialization p1 = src_tensor.mutable_data(common::make_ddim({1, 2, 3}), phi::GPUPlace(0)); auto p1_holder = src_tensor.Holder(); EXPECT_NE(p1, nullptr); // set src_tensor a new dim with large size // memory is supposed to be re-allocated p2 = src_tensor.mutable_data(common::make_ddim({3, 1024}), phi::GPUPlace(0)); auto p2_holder = src_tensor.Holder(); EXPECT_NE(p2, nullptr); EXPECT_NE(p1_holder.get(), p2_holder.get()); // set src_tensor a new dim with same size // memory block is supposed to be unchanged p1 = src_tensor.mutable_data(common::make_ddim({2, 2, 3}), phi::GPUPlace(0)); EXPECT_EQ(p1, p2); // set src_tensor a new dim with smaller size // memory block is supposed to be unchanged p2 = src_tensor.mutable_data(common::make_ddim({2, 2}), phi::GPUPlace(0)); EXPECT_EQ(p1, p2); } #endif } TEST(DenseTensor, ShareDataWith) { { phi::DenseTensor src_tensor; phi::DenseTensor dst_tensor; // Try to share data form uninitialized tensor bool caught = false; try { dst_tensor.ShareDataWith(src_tensor); } catch (paddle::platform::EnforceNotMet& err) { caught = true; std::string ex_msg = err.what(); EXPECT_TRUE(ex_msg.find("Tensor holds no memory. Call " "Tensor::mutable_data firstly.") != std::string::npos); } ASSERT_TRUE(caught); src_tensor.mutable_data(common::make_ddim({2, 3, 4}), phi::CPUPlace()); dst_tensor.ShareDataWith(src_tensor); ASSERT_EQ(src_tensor.data(), dst_tensor.data()); } #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) { phi::DenseTensor src_tensor; phi::DenseTensor dst_tensor; src_tensor.mutable_data(common::make_ddim({2, 3, 4}), phi::GPUPlace(0)); dst_tensor.ShareDataWith(src_tensor); ASSERT_EQ(src_tensor.data(), dst_tensor.data()); } #endif } TEST(DenseTensor, Slice) { { phi::DenseTensor src_tensor; src_tensor.mutable_data(common::make_ddim({5, 3, 4}), phi::CPUPlace()); phi::DenseTensor slice_tensor = src_tensor.Slice(1, 3); phi::DDim slice_dims = slice_tensor.dims(); 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(src_tensor.data()); uintptr_t src_mutable_data_address = reinterpret_cast( src_tensor.mutable_data(src_tensor.dims(), phi::CPUPlace())); uintptr_t slice_data_address = reinterpret_cast(slice_tensor.data()); uintptr_t slice_mutable_data_address = reinterpret_cast( slice_tensor.mutable_data(slice_tensor.dims(), phi::CPUPlace())); 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); } #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) { phi::DenseTensor src_tensor; src_tensor.mutable_data(common::make_ddim({6, 9}), phi::GPUPlace(0)); phi::DenseTensor slice_tensor = src_tensor.Slice(2, 6); phi::DDim slice_dims = slice_tensor.dims(); ASSERT_EQ(arity(slice_dims), 2); EXPECT_EQ(slice_dims[0], 4); EXPECT_EQ(slice_dims[1], 9); uintptr_t src_data_address = reinterpret_cast(src_tensor.data()); uintptr_t src_mutable_data_address = reinterpret_cast( src_tensor.mutable_data(src_tensor.dims(), phi::GPUPlace(0))); uintptr_t slice_data_address = reinterpret_cast(slice_tensor.data()); uintptr_t slice_mutable_data_address = reinterpret_cast(slice_tensor.mutable_data( slice_tensor.dims(), phi::GPUPlace(0))); 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 } TEST(DenseTensor, ReshapeToMatrix) { phi::DenseTensor src; int* src_ptr = src.mutable_data({2, 3, 4, 9}, phi::CPUPlace()); for (int i = 0; i < 2 * 3 * 4 * 9; ++i) { src_ptr[i] = i; } phi::DenseTensor res = phi::ReshapeToMatrix(src, 2); ASSERT_EQ(res.dims()[0], 2 * 3); ASSERT_EQ(res.dims()[1], 4 * 9); } TEST(DenseTensor, Layout) { phi::DenseTensor src; ASSERT_EQ(src.layout(), phi::DataLayout::kNCHW); src.set_layout(phi::DataLayout::kAnyLayout); ASSERT_EQ(src.layout(), phi::DataLayout::kAnyLayout); } TEST(DenseTensor, FP16) { using phi::dtype::float16; phi::DenseTensor src; float16* src_ptr = src.mutable_data({2, 3}, phi::CPUPlace()); for (int i = 0; i < 2 * 3; ++i) { src_ptr[i] = static_cast(i); } EXPECT_EQ(src.memory_size(), 2 * 3 * sizeof(float16)); // EXPECT a human readable error message // src.data(); // phi::DenseTensor holds the wrong type, it holds N6paddle8platform7float16E // at // [/paddle/Paddle/paddle/fluid/framework/tensor_impl.h:43] } TEST(DenseTensor, Split) { { phi::DenseTensor src_tensor; src_tensor.mutable_data(common::make_ddim({6, 2}), phi::CPUPlace()); std::vector split_tensor_list = src_tensor.Split(2, 0); ASSERT_EQ(split_tensor_list.size(), 3UL); EXPECT_EQ(split_tensor_list[0].dims()[0], 2); EXPECT_EQ(split_tensor_list[1].dims()[0], 2); EXPECT_EQ(split_tensor_list[2].dims()[0], 2); EXPECT_EQ(split_tensor_list[0].dims()[1], 2); EXPECT_EQ(split_tensor_list[1].dims()[1], 2); EXPECT_EQ(split_tensor_list[2].dims()[1], 2); uintptr_t src_data_address = reinterpret_cast(src_tensor.data()); uintptr_t src_mutable_data_address = reinterpret_cast( src_tensor.mutable_data(src_tensor.dims(), phi::CPUPlace())); EXPECT_EQ(src_data_address, src_mutable_data_address); for (int i = 0; i < 3; ++i) { uintptr_t split_data_address = reinterpret_cast(split_tensor_list[i].data()); uintptr_t split_mutable_data_address = reinterpret_cast(split_tensor_list[i].mutable_data( split_tensor_list[i].dims(), phi::CPUPlace())); EXPECT_EQ(split_data_address, split_mutable_data_address); EXPECT_EQ(src_data_address + 2 * 2 * i * sizeof(int), split_data_address); } } #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) { phi::DenseTensor src_tensor; src_tensor.mutable_data(common::make_ddim({6, 4}), phi::GPUPlace(0)); std::vector split_tensor_list = src_tensor.Split(2, 0); ASSERT_EQ(split_tensor_list.size(), 3UL); EXPECT_EQ(split_tensor_list[0].dims()[0], 2); EXPECT_EQ(split_tensor_list[1].dims()[0], 2); EXPECT_EQ(split_tensor_list[2].dims()[0], 2); EXPECT_EQ(split_tensor_list[0].dims()[1], 4); EXPECT_EQ(split_tensor_list[1].dims()[1], 4); EXPECT_EQ(split_tensor_list[2].dims()[1], 4); uintptr_t src_data_address = reinterpret_cast(src_tensor.data()); uintptr_t src_mutable_data_address = reinterpret_cast( src_tensor.mutable_data(src_tensor.dims(), phi::GPUPlace(0))); EXPECT_EQ(src_data_address, src_mutable_data_address); for (int i = 0; i < 3; ++i) { uintptr_t split_data_address = reinterpret_cast(split_tensor_list[i].data()); uintptr_t split_mutable_data_address = reinterpret_cast(split_tensor_list[i].mutable_data( split_tensor_list[i].dims(), phi::GPUPlace(0))); EXPECT_EQ(split_data_address, split_mutable_data_address); EXPECT_EQ(src_data_address + 2 * 4 * i * sizeof(double), split_data_address); } } #endif } TEST(DenseTensor, Chunk) { { phi::DenseTensor src_tensor; src_tensor.mutable_data(common::make_ddim({6, 2}), phi::CPUPlace()); std::vector split_tensor_list = src_tensor.Chunk(3, 0); ASSERT_EQ(split_tensor_list.size(), 3UL); EXPECT_EQ(split_tensor_list[0].dims()[0], 2); EXPECT_EQ(split_tensor_list[1].dims()[0], 2); EXPECT_EQ(split_tensor_list[2].dims()[0], 2); EXPECT_EQ(split_tensor_list[0].dims()[1], 2); EXPECT_EQ(split_tensor_list[1].dims()[1], 2); EXPECT_EQ(split_tensor_list[2].dims()[1], 2); uintptr_t src_data_address = reinterpret_cast(src_tensor.data()); uintptr_t src_mutable_data_address = reinterpret_cast( src_tensor.mutable_data(src_tensor.dims(), phi::CPUPlace())); for (int i = 0; i < 3; ++i) { uintptr_t split_data_address = reinterpret_cast(split_tensor_list[i].data()); uintptr_t split_mutable_data_address = reinterpret_cast(split_tensor_list[i].mutable_data( split_tensor_list[i].dims(), phi::CPUPlace())); EXPECT_EQ(src_data_address, src_mutable_data_address); EXPECT_EQ(split_data_address, split_mutable_data_address); EXPECT_EQ(src_data_address + 2 * 2 * i * sizeof(int), split_data_address); } } #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) { phi::DenseTensor src_tensor; src_tensor.mutable_data(common::make_ddim({6, 4}), phi::GPUPlace(0)); std::vector split_tensor_list = src_tensor.Chunk(3, 0); ASSERT_EQ(split_tensor_list.size(), 3UL); EXPECT_EQ(split_tensor_list[0].dims()[0], 2); EXPECT_EQ(split_tensor_list[1].dims()[0], 2); EXPECT_EQ(split_tensor_list[2].dims()[0], 2); EXPECT_EQ(split_tensor_list[0].dims()[1], 4); EXPECT_EQ(split_tensor_list[1].dims()[1], 4); EXPECT_EQ(split_tensor_list[2].dims()[1], 4); uintptr_t src_data_address = reinterpret_cast(src_tensor.data()); uintptr_t src_mutable_data_address = reinterpret_cast( src_tensor.mutable_data(src_tensor.dims(), phi::GPUPlace(0))); EXPECT_EQ(src_data_address, src_mutable_data_address); for (int i = 0; i < 3; ++i) { uintptr_t split_data_address = reinterpret_cast(split_tensor_list[i].data()); uintptr_t split_mutable_data_address = reinterpret_cast(split_tensor_list[i].mutable_data( split_tensor_list[i].dims(), phi::GPUPlace(0))); EXPECT_EQ(split_data_address, split_mutable_data_address); EXPECT_EQ(src_data_address + 2 * 4 * i * sizeof(double), split_data_address); } } #endif }