chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
cc_test(
|
||||
test_custom_kernel
|
||||
SRCS test_custom_kernel.cc
|
||||
DEPS phi common)
|
||||
if(WIN32)
|
||||
cc_test(
|
||||
test_dense_tensor
|
||||
SRCS test_dense_tensor.cc
|
||||
DEPS type_info common)
|
||||
else()
|
||||
cc_test(
|
||||
test_dense_tensor
|
||||
SRCS test_dense_tensor.cc
|
||||
DEPS phi common)
|
||||
endif()
|
||||
cc_test(test_intrusive_ptr SRCS test_intrusive_ptr.cc)
|
||||
cc_test(test_type_info SRCS test_type_info.cc)
|
||||
if(WIN32)
|
||||
paddle_test(test_kernel_factory SRCS test_kernel_factory.cc DEPS phi common)
|
||||
else()
|
||||
cc_test(
|
||||
test_kernel_factory
|
||||
SRCS test_kernel_factory.cc
|
||||
DEPS phi common)
|
||||
endif()
|
||||
cc_test(
|
||||
test_sparse_coo_tensor
|
||||
SRCS test_sparse_coo_tensor.cc
|
||||
DEPS phi common)
|
||||
cc_test(
|
||||
test_sparse_csr_tensor
|
||||
SRCS test_sparse_csr_tensor.cc
|
||||
DEPS phi common)
|
||||
cc_test(
|
||||
test_op_utils
|
||||
SRCS test_op_utils.cc
|
||||
DEPS op_compat_infos)
|
||||
cc_test(
|
||||
test_meta_fn_utils
|
||||
SRCS test_meta_fn_utils.cc
|
||||
DEPS phi common)
|
||||
|
||||
if(WIN32)
|
||||
cc_test(
|
||||
test_ddim
|
||||
SRCS test_ddim.cc
|
||||
DEPS type_info common)
|
||||
else()
|
||||
cc_test(
|
||||
test_ddim
|
||||
SRCS test_ddim.cc
|
||||
DEPS phi common)
|
||||
endif()
|
||||
if(WITH_GPU)
|
||||
nv_test(
|
||||
test_dim
|
||||
SRCS test_dim.cu
|
||||
DEPS phi common)
|
||||
elseif(WITH_ROCM)
|
||||
hip_test(
|
||||
test_dim
|
||||
SRCS test_dim.cu
|
||||
DEPS phi common)
|
||||
endif()
|
||||
|
||||
cc_test(
|
||||
selected_rows_test
|
||||
SRCS test_selected_rows.cc
|
||||
DEPS phi common)
|
||||
if(WITH_TESTING AND TEST selected_rows_test)
|
||||
set_tests_properties(selected_rows_test PROPERTIES TIMEOUT 120)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
cc_test(test_rw_lock SRCS test_rw_lock.cc)
|
||||
endif()
|
||||
cc_test(
|
||||
test_string_tensor
|
||||
SRCS test_string_tensor.cc
|
||||
DEPS phi common)
|
||||
cc_test(unroll_array_ops_test SRCS unroll_array_ops_test.cc)
|
||||
|
||||
cc_test(
|
||||
test_tensor_array
|
||||
SRCS test_tensor_array.cc
|
||||
DEPS phi common)
|
||||
|
||||
if(WITH_GPU)
|
||||
if(WIN32)
|
||||
nv_test(
|
||||
test_mixed_vector
|
||||
SRCS test_mixed_vector.cc test_mixed_vector.cu
|
||||
DEPS type_info common tensor)
|
||||
else()
|
||||
nv_test(
|
||||
test_mixed_vector
|
||||
SRCS test_mixed_vector.cc test_mixed_vector.cu
|
||||
DEPS phi common tensor)
|
||||
endif()
|
||||
elseif(WITH_ROCM)
|
||||
hip_test(
|
||||
test_mixed_vector
|
||||
SRCS test_mixed_vector.cc test_mixed_vector.cu
|
||||
DEPS phi common tensor)
|
||||
else()
|
||||
cc_test(
|
||||
test_mixed_vector
|
||||
SRCS test_mixed_vector.cc
|
||||
DEPS phi common tensor)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
paddle_test(test_c_tcp_store SRCS test_tcp_store.cc DEPS phi common)
|
||||
endif()
|
||||
|
||||
if(WITH_XPU)
|
||||
paddle_test(data_type_transform_test_xpu SRCS data_type_transform_test_xpu.cc)
|
||||
endif()
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2021 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. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "paddle/phi/core/allocator.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
class FancyAllocator : public phi::Allocator {
|
||||
public:
|
||||
static void Delete(Allocation* allocation) {
|
||||
::operator delete(allocation->ptr());
|
||||
}
|
||||
|
||||
AllocationPtr Allocate(size_t bytes_size) override {
|
||||
void* data = ::operator new(bytes_size);
|
||||
auto* allocation = new phi::Allocation(data, bytes_size, phi::CPUPlace());
|
||||
return AllocationPtr(allocation, Delete);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright (c) 2025 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 "gtest/gtest.h"
|
||||
#include "paddle/fluid/framework/tensor_util.h"
|
||||
#include "paddle/phi/core/framework/data_type_transform.h"
|
||||
#include "paddle/phi/core/kernel_factory.h"
|
||||
|
||||
template <typename InT, typename OutT>
|
||||
void TransformTest(const phi::KernelKey& kernel_type_for_var,
|
||||
const phi::KernelKey& expected_kernel_type,
|
||||
const phi::CPUPlace& cpu_place,
|
||||
const phi::XPUPlace& xpu_place,
|
||||
const InT* cpu_data,
|
||||
const int data_number) {
|
||||
phi::XPUContext context(xpu_place);
|
||||
phi::DenseTensor in;
|
||||
phi::DenseTensor in_xpu;
|
||||
phi::DenseTensor out;
|
||||
phi::DenseTensor out_xpu;
|
||||
|
||||
// copy from cpu_data to cpu tensor
|
||||
InT* in_ptr =
|
||||
in.mutable_data<InT>(common::make_ddim({data_number}), cpu_place);
|
||||
memcpy(in_ptr, cpu_data, sizeof(InT) * data_number);
|
||||
|
||||
// test case 1: on xpu
|
||||
{
|
||||
// copy from cpu tensor to xpu tensor
|
||||
paddle::framework::TensorCopy(in, xpu_place, context, &in_xpu);
|
||||
context.Wait();
|
||||
|
||||
// call trans data
|
||||
phi::TransDataType(
|
||||
kernel_type_for_var, expected_kernel_type, in_xpu, &out_xpu);
|
||||
|
||||
// copy from xpu tensor to cpu tensor
|
||||
paddle::framework::TensorCopy(out_xpu, cpu_place, context, &out);
|
||||
context.Wait();
|
||||
|
||||
// check result
|
||||
OutT* out_ptr = out.data<OutT>();
|
||||
for (int i = 0; i < data_number; ++i) {
|
||||
EXPECT_EQ(out_ptr[i], static_cast<OutT>(cpu_data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// test case 2: on cpu
|
||||
{
|
||||
// call trans data
|
||||
phi::TransDataType(kernel_type_for_var, expected_kernel_type, in, &out);
|
||||
|
||||
// check result
|
||||
OutT* out_ptr = out.data<OutT>();
|
||||
for (int i = 0; i < data_number; ++i) {
|
||||
EXPECT_EQ(out_ptr[i], static_cast<OutT>(cpu_data[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DataTypeTransform, XPUTransform) {
|
||||
auto cpu_place = phi::CPUPlace();
|
||||
auto xpu_place = phi::XPUPlace(0);
|
||||
phi::XPUContext context(xpu_place);
|
||||
|
||||
auto kernel_fp16 = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::FLOAT16);
|
||||
auto kernel_fp32 = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::FLOAT32);
|
||||
auto kernel_fp64 = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::FLOAT64);
|
||||
auto kernel_int16 = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::INT16);
|
||||
auto kernel_int32 = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::INT32);
|
||||
auto kernel_int64 = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::INT64);
|
||||
auto kernel_bool = phi::KernelKey(
|
||||
xpu_place, phi::DataLayout::ALL_LAYOUT, phi::DataType::BOOL);
|
||||
|
||||
{
|
||||
// float16 -> any
|
||||
phi::dtype::float16 cpu_data[6] = {phi::dtype::float16(0),
|
||||
phi::dtype::float16(1),
|
||||
phi::dtype::float16(2),
|
||||
phi::dtype::float16(3),
|
||||
phi::dtype::float16(4),
|
||||
phi::dtype::float16(5)};
|
||||
TransformTest<phi::dtype::float16, float>(
|
||||
kernel_fp16, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<phi::dtype::float16, double>(
|
||||
kernel_fp16, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<phi::dtype::float16, int32_t>(
|
||||
kernel_fp16, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<phi::dtype::float16, int64_t>(
|
||||
kernel_fp16, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<phi::dtype::float16, bool>(
|
||||
kernel_fp16, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
{
|
||||
// float -> any
|
||||
float cpu_data[6] = {0, 1, 2, 3, 4, 5};
|
||||
TransformTest<float, phi::dtype::float16>(
|
||||
kernel_fp32, kernel_fp16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<float, float>(
|
||||
kernel_fp32, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<float, double>(
|
||||
kernel_fp32, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<float, int16_t>(
|
||||
kernel_fp32, kernel_int16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<float, int32_t>(
|
||||
kernel_fp32, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<float, int64_t>(
|
||||
kernel_fp32, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<float, bool>(
|
||||
kernel_fp32, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
{
|
||||
// double -> any
|
||||
double cpu_data[6] = {0, 1, 2, 3, 4, 5};
|
||||
TransformTest<double, phi::dtype::float16>(
|
||||
kernel_fp64, kernel_fp16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<double, float>(
|
||||
kernel_fp64, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<double, double>(
|
||||
kernel_fp64, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<double, int16_t>(
|
||||
kernel_fp64, kernel_int16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<double, int32_t>(
|
||||
kernel_fp64, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<double, int64_t>(
|
||||
kernel_fp64, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<double, bool>(
|
||||
kernel_fp64, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
{
|
||||
// int16 -> any
|
||||
int16_t cpu_data[6] = {0, 1, 2, 3, 4, 5};
|
||||
TransformTest<int16_t, phi::dtype::float16>(
|
||||
kernel_int16, kernel_fp16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int16_t, float>(
|
||||
kernel_int16, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int16_t, double>(
|
||||
kernel_int16, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int16_t, int16_t>(
|
||||
kernel_int16, kernel_int16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int16_t, int32_t>(
|
||||
kernel_int16, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int16_t, int64_t>(
|
||||
kernel_int16, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int16_t, bool>(
|
||||
kernel_int16, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
{
|
||||
// int32 -> any
|
||||
int32_t cpu_data[6] = {0, 1, 2, 3, 4, 5};
|
||||
TransformTest<int32_t, phi::dtype::float16>(
|
||||
kernel_int32, kernel_fp16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int32_t, float>(
|
||||
kernel_int32, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int32_t, double>(
|
||||
kernel_int32, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int32_t, int16_t>(
|
||||
kernel_int32, kernel_int16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int32_t, int32_t>(
|
||||
kernel_int32, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int32_t, int64_t>(
|
||||
kernel_int32, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int32_t, bool>(
|
||||
kernel_int32, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
{
|
||||
// int64 -> any
|
||||
int64_t cpu_data[6] = {0, 1, 2, 3, 4, 5};
|
||||
TransformTest<int64_t, phi::dtype::float16>(
|
||||
kernel_int64, kernel_fp16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int64_t, float>(
|
||||
kernel_int64, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int64_t, double>(
|
||||
kernel_int64, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int64_t, int16_t>(
|
||||
kernel_int64, kernel_int16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int64_t, int32_t>(
|
||||
kernel_int64, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int64_t, int64_t>(
|
||||
kernel_int64, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<int64_t, bool>(
|
||||
kernel_int64, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
{
|
||||
// bool -> any
|
||||
bool cpu_data[6] = {0, 1, 0, 1, 1, 0};
|
||||
TransformTest<bool, phi::dtype::float16>(
|
||||
kernel_bool, kernel_fp16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<bool, float>(
|
||||
kernel_bool, kernel_fp32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<bool, double>(
|
||||
kernel_bool, kernel_fp64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<bool, int16_t>(
|
||||
kernel_bool, kernel_int16, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<bool, int32_t>(
|
||||
kernel_bool, kernel_int32, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<bool, int64_t>(
|
||||
kernel_bool, kernel_int64, cpu_place, xpu_place, cpu_data, 6);
|
||||
TransformTest<bool, bool>(
|
||||
kernel_bool, kernel_bool, cpu_place, xpu_place, cpu_data, 6);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/* Copyright (c) 2021 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. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include <type_traits>
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
template <typename T,
|
||||
typename =
|
||||
typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||
class RandomGenerator {
|
||||
using distribution_type =
|
||||
typename std::conditional<std::is_integral<T>::value,
|
||||
std::uniform_int_distribution<T>,
|
||||
std::uniform_real_distribution<T>>::type;
|
||||
|
||||
std::default_random_engine engine;
|
||||
distribution_type distribution;
|
||||
|
||||
public:
|
||||
auto operator()() -> decltype(distribution(engine)) {
|
||||
return distribution(engine);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Container, typename T = typename Container::value_type>
|
||||
auto make_generator(Container const&) -> decltype(RandomGenerator<T>()) {
|
||||
return RandomGenerator<T>();
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,303 @@
|
||||
/* Copyright (c) 2022 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. */
|
||||
|
||||
#if defined _WIN32 || defined __APPLE__
|
||||
#else
|
||||
#define _LINUX
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#ifdef _LINUX
|
||||
#include "paddle/phi/api/lib/utils/allocator.h"
|
||||
#include "paddle/phi/backends/context_pool.h"
|
||||
#include "paddle/phi/common/int_array.h"
|
||||
#include "paddle/phi/common/scalar.h"
|
||||
#include "paddle/phi/core/kernel_context.h"
|
||||
#include "paddle/phi/core/kernel_factory.h"
|
||||
#include "paddle/phi/core/kernel_registry.h"
|
||||
#include "paddle/phi/core/meta_tensor.h"
|
||||
#include "paddle/phi/infermeta/binary.h"
|
||||
|
||||
// user kernel function
|
||||
namespace custom_kernel {
|
||||
|
||||
// Here we use fake_dot for test
|
||||
// input 3: two Tensors and one std::vector<Tensor>
|
||||
// attribute 11: fake_attributes
|
||||
// output 2: one Tensor* and one std::vector<Tensor*>
|
||||
template <typename T, typename Context>
|
||||
void FakeDot(const Context& dev_ctx,
|
||||
const phi::DenseTensor& x,
|
||||
const phi::DenseTensor& y,
|
||||
const std::vector<const phi::DenseTensor*>& fake_input_vec,
|
||||
bool fake_attr_bool,
|
||||
int fake_attr_int,
|
||||
float fake_attr_float,
|
||||
double fake_attr_double,
|
||||
int64_t fake_attr_int64,
|
||||
phi::DataType fake_attr_dtype,
|
||||
const phi::Scalar& fake_attr_scalar,
|
||||
const phi::IntArray& fake_attr_int_array,
|
||||
const std::vector<int64_t>& fake_attr_int64_vec,
|
||||
const std::vector<int>& fake_attr_int_vec,
|
||||
phi::DenseTensor* out,
|
||||
std::vector<phi::DenseTensor*> fake_out_vec) {
|
||||
// print param info
|
||||
std::cout << "fake_input_vec.size: " << fake_input_vec.size() << std::endl;
|
||||
std::cout << "fake_attr_bool: " << fake_attr_bool << std::endl;
|
||||
std::cout << "fake_attr_int: " << fake_attr_int << std::endl;
|
||||
std::cout << "fake_attr_float: " << fake_attr_float << std::endl;
|
||||
std::cout << "fake_attr_double: " << fake_attr_double << std::endl;
|
||||
std::cout << "fake_attr_int64: " << fake_attr_int64 << std::endl;
|
||||
std::cout << "fake_attr_dtype: " << fake_attr_dtype << std::endl;
|
||||
std::cout << "fake_attr_int64_vec: " << fake_attr_int64_vec.size()
|
||||
<< std::endl;
|
||||
std::cout << "fake_attr_int_vec: " << fake_attr_int_vec.size() << std::endl;
|
||||
std::cout << "fake_out_vec: " << fake_out_vec.size() << std::endl;
|
||||
|
||||
// assert check
|
||||
assert(fake_input_vec.size() == 2);
|
||||
assert(fake_attr_bool == false);
|
||||
assert(fake_attr_int == 1);
|
||||
assert(fake_attr_float == 2);
|
||||
assert(fake_attr_double == 3);
|
||||
assert(fake_attr_int64 == 4);
|
||||
assert(fake_attr_dtype == phi::DataType::UINT32);
|
||||
assert(fake_attr_int64_vec.empty());
|
||||
assert(fake_attr_int_vec.empty());
|
||||
assert(fake_out_vec.size() == 2);
|
||||
|
||||
auto const *x_ptr = x.data<T>(), *x_ptr_ = &x_ptr[0];
|
||||
auto const *y_ptr = y.data<T>(), *y_ptr_ = &y_ptr[0];
|
||||
T* z = dev_ctx.template Alloc<T>(out);
|
||||
auto&& d = x.dims();
|
||||
auto const N = x.numel();
|
||||
auto const B = d[d.size() - 1];
|
||||
for (int j = 0; j < N / B; j++) {
|
||||
T ss = 0;
|
||||
for (int i = 0; i < B; i++) ss += (*x_ptr_++) * (*y_ptr_++);
|
||||
z[j] = ss;
|
||||
}
|
||||
}
|
||||
} // namespace custom_kernel
|
||||
|
||||
PD_REGISTER_BUILTIN_KERNEL(fake_dot,
|
||||
CPU,
|
||||
ALL_LAYOUT,
|
||||
custom_kernel::FakeDot,
|
||||
float,
|
||||
double,
|
||||
int,
|
||||
int64_t,
|
||||
int8_t,
|
||||
uint8_t) {}
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
// Upper code will store dot kernels info into OpKernelInfoMap
|
||||
TEST(CustomKernel, custom_kernel_dot) {
|
||||
std::string op_name = "fake_dot";
|
||||
phi::Backend backend = phi::Backend::CPU;
|
||||
phi::DataLayout layout = phi::DataLayout::ALL_LAYOUT;
|
||||
|
||||
// 1.custom kernel info parsed and store
|
||||
EXPECT_TRUE(phi::CustomKernelMap::Instance().GetMap().find(op_name) !=
|
||||
phi::CustomKernelMap::Instance().GetMap().end());
|
||||
|
||||
auto& custom_kernels = phi::CustomKernelMap::Instance().Kernels();
|
||||
// 2.info check
|
||||
EXPECT_EQ(6, static_cast<int>(custom_kernels[op_name].size()));
|
||||
auto& custom_fake_dot_kernels = custom_kernels[op_name];
|
||||
EXPECT_TRUE(custom_fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::FLOAT32)) !=
|
||||
custom_fake_dot_kernels.end());
|
||||
EXPECT_TRUE(custom_fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::FLOAT64)) !=
|
||||
custom_fake_dot_kernels.end());
|
||||
EXPECT_TRUE(custom_fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT32)) !=
|
||||
custom_fake_dot_kernels.end());
|
||||
EXPECT_TRUE(custom_fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT64)) !=
|
||||
custom_fake_dot_kernels.end());
|
||||
EXPECT_TRUE(custom_fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT8)) !=
|
||||
custom_fake_dot_kernels.end());
|
||||
EXPECT_TRUE(custom_fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::UINT8)) !=
|
||||
custom_fake_dot_kernels.end());
|
||||
|
||||
// 3.before register
|
||||
auto& kernels = phi::KernelFactory::Instance().kernels();
|
||||
EXPECT_TRUE(kernels.find(op_name) == kernels.end());
|
||||
|
||||
// mock fake_dot is supported by phi for check while registering
|
||||
auto& fake_dot_kernels = kernels[op_name];
|
||||
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::FLOAT32)) ==
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::FLOAT64)) ==
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT32)) ==
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT64)) ==
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT8)) ==
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::UINT8)) ==
|
||||
fake_dot_kernels.end());
|
||||
|
||||
// register
|
||||
phi::CustomKernelMap::Instance().RegisterCustomKernels();
|
||||
|
||||
EXPECT_EQ(0, static_cast<int>(custom_fake_dot_kernels.size()));
|
||||
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::FLOAT32)) !=
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::FLOAT64)) !=
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT32)) !=
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT64)) !=
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::INT8)) !=
|
||||
fake_dot_kernels.end());
|
||||
EXPECT_TRUE(fake_dot_kernels.find(
|
||||
phi::KernelKey(backend, layout, phi::DataType::UINT8)) !=
|
||||
fake_dot_kernels.end());
|
||||
|
||||
// 4.kernel select
|
||||
auto kernel_result = phi::KernelFactory::Instance().SelectKernelOrThrowError(
|
||||
op_name, phi::KernelKey(backend, layout, phi::DataType::UINT8));
|
||||
const auto& kernel = kernel_result.kernel;
|
||||
|
||||
// 5.prepare parameters for kernel
|
||||
const auto alloc =
|
||||
std::make_unique<paddle::experimental::DefaultAllocator>(phi::CPUPlace());
|
||||
auto dense_x = std::make_shared<phi::DenseTensor>(
|
||||
alloc.get(),
|
||||
phi::DenseTensorMeta(phi::DataType::UINT8,
|
||||
common::make_ddim({2, 3}),
|
||||
phi::DataLayout::NCHW));
|
||||
auto* dev_ctx = phi::DeviceContextPool::Instance().Get(phi::CPUPlace());
|
||||
auto* dense_x_data = dev_ctx->template Alloc<uint8_t>(dense_x.get());
|
||||
|
||||
auto dense_y = std::make_shared<phi::DenseTensor>(
|
||||
alloc.get(),
|
||||
phi::DenseTensorMeta(phi::DataType::UINT8,
|
||||
common::make_ddim({2, 3}),
|
||||
phi::DataLayout::NCHW));
|
||||
auto* dense_y_data = dev_ctx->template Alloc<uint8_t>(dense_y.get());
|
||||
|
||||
// dot x,y and result
|
||||
std::array<uint8_t, 2> sum = {0, 0};
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
dense_x_data[i * 3 + j] = (i * 3 + j);
|
||||
dense_y_data[i * 3 + j] = (i * 3 + j);
|
||||
sum[i] += (i * 3 + j) * (i * 3 + j);
|
||||
}
|
||||
}
|
||||
|
||||
// 6.prepare kernel_context
|
||||
auto kernel_context = phi::KernelContext(dev_ctx);
|
||||
kernel_context.EmplaceBackInput(dense_x.get()); // idx:0, index:[0,1)
|
||||
kernel_context.EmplaceBackInput(dense_y.get()); // idx:1, index:[1,2)
|
||||
|
||||
// fake_input_vec: idx:2, index:[2,4)
|
||||
size_t fake_input_vec_idx = 2;
|
||||
size_t fake_input_vec_index_start = 2;
|
||||
size_t fake_input_vec_index_end = 4;
|
||||
kernel_context.EmplaceBackInputWithoutSetRange(dense_x.get());
|
||||
kernel_context.EmplaceBackInputWithoutSetRange(dense_y.get());
|
||||
kernel_context.AssignInputRange(
|
||||
std::make_pair(fake_input_vec_index_start, fake_input_vec_index_end),
|
||||
fake_input_vec_idx);
|
||||
|
||||
bool fake_attr_bool = false;
|
||||
int fake_attr_int = 1;
|
||||
float fake_attr_float = 2.0;
|
||||
double fake_attr_double = 3.0;
|
||||
int64_t fake_attr_int64 = 4;
|
||||
phi::DataType fake_attr_dtype = phi::DataType::UINT32;
|
||||
phi::DenseTensor tmp_tensor;
|
||||
tmp_tensor.Resize({1});
|
||||
dev_ctx->template Alloc<uint8_t>(&tmp_tensor);
|
||||
phi::Scalar fake_attr_scalar{tmp_tensor};
|
||||
phi::IntArray fake_attr_int_array;
|
||||
std::vector<int64_t> fake_attr_int64_vec;
|
||||
std::vector<int> fake_attr_int_vec;
|
||||
|
||||
kernel_context.EmplaceBackAttr(fake_attr_bool);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_int);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_float);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_double);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_int64);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_dtype);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_scalar);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_int_array);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_int64_vec);
|
||||
kernel_context.EmplaceBackAttr(fake_attr_int_vec);
|
||||
|
||||
auto dense_out = std::make_shared<phi::DenseTensor>();
|
||||
|
||||
phi::MetaTensor meta_out(dense_out.get());
|
||||
phi::DotInferMeta(*dense_x, *dense_y, &meta_out);
|
||||
kernel_context.EmplaceBackOutput(dense_out.get()); // idx:0 index:[0,1)
|
||||
|
||||
// fake_input_vec: idx:1, index:[1,3)
|
||||
size_t fake_out_vec_idx = 1;
|
||||
size_t fake_out_vec_index_start = 1;
|
||||
size_t fake_out_vec_index_end = 3;
|
||||
kernel_context.EmplaceBackOutputWithoutSetRange(dense_out.get());
|
||||
kernel_context.EmplaceBackOutputWithoutSetRange(dense_out.get());
|
||||
kernel_context.AssignOutputRange(
|
||||
std::make_pair(fake_out_vec_index_start, fake_out_vec_index_end),
|
||||
fake_out_vec_idx);
|
||||
|
||||
// 7.kernel call
|
||||
kernel(&kernel_context);
|
||||
|
||||
// 8.check result
|
||||
ASSERT_EQ(dense_out->dims().size(), 1);
|
||||
ASSERT_EQ(dense_out->dims()[0], 2);
|
||||
ASSERT_EQ(dense_out->numel(), 2);
|
||||
ASSERT_EQ(dense_out->dtype(), phi::DataType::UINT8);
|
||||
ASSERT_EQ(dense_out->layout(), phi::DataLayout::NCHW);
|
||||
ASSERT_EQ(dense_out->initialized(), true);
|
||||
|
||||
auto expect_result = sum;
|
||||
auto actual_result0 = dense_out->data<uint8_t>()[0];
|
||||
auto actual_result1 = dense_out->data<uint8_t>()[1];
|
||||
ASSERT_EQ(expect_result[0], actual_result0);
|
||||
ASSERT_EQ(expect_result[1], actual_result1);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2022 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 <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/ddim.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
TEST(DDim, Equality) {
|
||||
// default construct ddim
|
||||
phi::DDim default_ddim;
|
||||
EXPECT_EQ(arity(default_ddim), -1);
|
||||
EXPECT_EQ(default_ddim[0], 0);
|
||||
|
||||
// construct a zero-DDim
|
||||
phi::DDim zero_ddim = common::make_ddim({});
|
||||
EXPECT_EQ(arity(zero_ddim), 0);
|
||||
EXPECT_EQ(zero_ddim.size(), 0);
|
||||
EXPECT_EQ(common::product(zero_ddim), 1);
|
||||
|
||||
std::vector<int64_t> zero_vec;
|
||||
phi::DDim zero_ddim1 = common::make_ddim(zero_vec);
|
||||
EXPECT_EQ(arity(zero_ddim1), 0);
|
||||
EXPECT_EQ(zero_ddim1.size(), 0);
|
||||
EXPECT_EQ(common::product(zero_ddim1), 1);
|
||||
|
||||
// zero-DDim to vector
|
||||
std::vector<int64_t> zero_ddim_vec = common::vectorize(zero_ddim);
|
||||
EXPECT_EQ(zero_ddim_vec.size(), size_t(0));
|
||||
|
||||
// reshape zero-DDim
|
||||
std::vector<int> reshape_vec = {1};
|
||||
phi::DDim reshape_ddim = zero_ddim.reshape(reshape_vec);
|
||||
EXPECT_EQ(arity(reshape_ddim), 1);
|
||||
EXPECT_EQ(reshape_ddim.size(), 1);
|
||||
EXPECT_EQ(common::product(reshape_ddim), 1);
|
||||
|
||||
// construct a DDim from an initialization list
|
||||
phi::DDim ddim = common::make_ddim({9, 1, 5});
|
||||
EXPECT_EQ(ddim[0], 9);
|
||||
EXPECT_EQ(ddim[1], 1);
|
||||
EXPECT_EQ(ddim[2], 5);
|
||||
|
||||
// arity of a DDim
|
||||
EXPECT_EQ(common::arity(ddim), 3);
|
||||
EXPECT_EQ(ddim.size(), 3);
|
||||
|
||||
// mutate a DDim
|
||||
ddim[1] = 2;
|
||||
EXPECT_EQ(ddim[1], 2);
|
||||
ddim[0] = 6;
|
||||
EXPECT_EQ(ddim[0], 6);
|
||||
|
||||
// construct a DDim from a vector
|
||||
std::vector<int64_t> vec({9, 1, 5});
|
||||
phi::DDim vddim = common::make_ddim(vec);
|
||||
EXPECT_EQ(vddim[0], 9);
|
||||
EXPECT_EQ(vddim[1], 1);
|
||||
EXPECT_EQ(vddim[2], 5);
|
||||
|
||||
// vectorize a DDim
|
||||
std::vector<int64_t> res_vec = common::vectorize(vddim);
|
||||
EXPECT_EQ(res_vec[0], 9);
|
||||
EXPECT_EQ(res_vec[1], 1);
|
||||
EXPECT_EQ(res_vec[2], 5);
|
||||
phi::Dim<3> d(3, 2, 1);
|
||||
res_vec = common::vectorize(phi::DDim(d));
|
||||
EXPECT_EQ(res_vec[0], 3);
|
||||
EXPECT_EQ(res_vec[1], 2);
|
||||
EXPECT_EQ(res_vec[2], 1);
|
||||
|
||||
// product of a DDim
|
||||
EXPECT_EQ(common::product(vddim), 45);
|
||||
EXPECT_EQ(common::product(common::make_ddim({3, 2, 5, 3})), 90);
|
||||
|
||||
// slice a DDim
|
||||
phi::DDim ddim2 = common::make_ddim({1, 2, 3, 4, 5, 6});
|
||||
phi::DDim slice_dim1 = common::slice_ddim(ddim2, 2, 5);
|
||||
EXPECT_EQ(arity(slice_dim1), 3);
|
||||
EXPECT_EQ(slice_dim1[0], 3);
|
||||
EXPECT_EQ(slice_dim1[1], 4);
|
||||
EXPECT_EQ(slice_dim1[2], 5);
|
||||
|
||||
phi::DDim slice_dim2 = common::slice_ddim(ddim2, 0, 6);
|
||||
EXPECT_EQ(arity(slice_dim2), 6);
|
||||
EXPECT_EQ(slice_dim2[0], 1);
|
||||
EXPECT_EQ(slice_dim2[1], 2);
|
||||
EXPECT_EQ(slice_dim2[2], 3);
|
||||
EXPECT_EQ(slice_dim2[3], 4);
|
||||
EXPECT_EQ(slice_dim2[4], 5);
|
||||
EXPECT_EQ(slice_dim2[5], 6);
|
||||
|
||||
phi::DDim slice_dim3 = common::slice_ddim(ddim2, 1, 1);
|
||||
EXPECT_EQ(arity(slice_dim3), 0);
|
||||
EXPECT_EQ(slice_dim3.size(), 0);
|
||||
EXPECT_EQ(common::product(slice_dim3), 1);
|
||||
}
|
||||
|
||||
TEST(DDim, Print) {
|
||||
// print a DDim
|
||||
std::stringstream ss1;
|
||||
phi::DDim ddim = common::make_ddim({2, 3, 4});
|
||||
ss1 << ddim;
|
||||
EXPECT_EQ("2, 3, 4", ss1.str());
|
||||
|
||||
// print a zero-DDim
|
||||
std::stringstream ss2;
|
||||
phi::DDim zero_ddim = common::make_ddim({});
|
||||
ss2 << zero_ddim;
|
||||
EXPECT_EQ("", ss2.str());
|
||||
}
|
||||
|
||||
TEST(DDim, Hash) {
|
||||
// hash a DDim
|
||||
std::size_t h = 0;
|
||||
phi::DDim ddim = common::make_ddim({2, 3, 4});
|
||||
h = std::hash<phi::DDim>()(ddim);
|
||||
EXPECT_EQ(h, 0xa16fb2b2967ul);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,376 @@
|
||||
/* Copyright (c) 2021 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 "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/dense_tensor.h"
|
||||
#include "test/cpp/phi/core/allocator.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
TEST(dense_tensor, meta) {
|
||||
const DDim dims({1, 2});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
// TODO(Shixiaowei02): need to check the lod is valid.
|
||||
const LegacyLoD lod{};
|
||||
|
||||
DenseTensorMeta meta_0;
|
||||
PADDLE_ENFORCE_EQ(meta_0.valid(),
|
||||
false,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in default DenseTensorMeta. Expected "
|
||||
"meta_0 to be invalid, but got: %s",
|
||||
meta_0.valid()));
|
||||
|
||||
DenseTensorMeta meta_1(dtype, dims);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_1.dtype,
|
||||
dtype,
|
||||
common::errors::InvalidArgument("Fail in DenseTensorMeta with dtype and "
|
||||
"dims. Expected dtype: %s, but got: %s",
|
||||
dtype,
|
||||
meta_1.dtype));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_1.dims,
|
||||
dims,
|
||||
common::errors::InvalidArgument("Fail in DenseTensorMeta with dtype and "
|
||||
"dims. Expected dims: %s, but got: %s",
|
||||
dims,
|
||||
meta_1.dims));
|
||||
PADDLE_ENFORCE_EQ(meta_1.valid(),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype and dims. Expected "
|
||||
"meta_1 to be valid, but got: %s",
|
||||
meta_1.valid()));
|
||||
|
||||
DenseTensorMeta meta_2(dtype, dims, layout);
|
||||
PADDLE_ENFORCE_EQ(meta_2.dtype,
|
||||
dtype,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims and layout. "
|
||||
"Expected dtype: %s, but got: %s",
|
||||
dtype,
|
||||
meta_2.dtype));
|
||||
PADDLE_ENFORCE_EQ(meta_2.dims,
|
||||
dims,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims "
|
||||
"and layout. Expected dims: %s, but got: %s",
|
||||
dims,
|
||||
meta_2.dims));
|
||||
PADDLE_ENFORCE_EQ(meta_2.layout,
|
||||
layout,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims and layout. "
|
||||
"Expected layout: %s, but got: %s",
|
||||
layout,
|
||||
meta_2.layout));
|
||||
PADDLE_ENFORCE_EQ(meta_2.valid(),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims and layout. "
|
||||
"Expected meta_2 to be valid, but got: %s",
|
||||
meta_2.valid()));
|
||||
|
||||
DenseTensorMeta meta_3(dtype, dims, layout, lod);
|
||||
PADDLE_ENFORCE_EQ(meta_3.dtype,
|
||||
dtype,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims, layout and "
|
||||
"lod. Expected dtype: %s, but got: %s",
|
||||
dtype,
|
||||
meta_3.dtype));
|
||||
PADDLE_ENFORCE_EQ(meta_3.dims,
|
||||
dims,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims, layout and "
|
||||
"lod. Expected dims: %s, but got: %s",
|
||||
dims,
|
||||
meta_3.dims));
|
||||
PADDLE_ENFORCE_EQ(meta_3.layout,
|
||||
layout,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims, layout and "
|
||||
"lod. Expected layout: %s, but got: %s",
|
||||
layout,
|
||||
meta_3.layout));
|
||||
PADDLE_ENFORCE_EQ(meta_3.legacy_lod,
|
||||
lod,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims, layout and "
|
||||
"lod. Expected lod: %s, but got: %s",
|
||||
lod,
|
||||
meta_3.legacy_lod));
|
||||
PADDLE_ENFORCE_EQ(meta_3.valid(),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in DenseTensorMeta with dtype, dims, layout and "
|
||||
"lod. Expected meta_3 to be valid, but got: %s",
|
||||
meta_3.valid()));
|
||||
|
||||
DenseTensorMeta meta_4(meta_3);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_4.dtype,
|
||||
dtype,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected dtype: %s, but got: %s",
|
||||
dtype,
|
||||
meta_4.dtype));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_4.dims,
|
||||
dims,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected dims: %s, but got: %s",
|
||||
dims,
|
||||
meta_4.dims));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_4.layout,
|
||||
layout,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected layout: %s, but got: %s",
|
||||
layout,
|
||||
meta_4.layout));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_4.legacy_lod,
|
||||
lod,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected lod: %s, but got: %s",
|
||||
lod,
|
||||
meta_4.legacy_lod));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_4.valid(),
|
||||
true,
|
||||
common::errors::InvalidArgument("Fail in copy DenseTensorMeta. Expected "
|
||||
"meta_4 to be valid, but got: %s",
|
||||
meta_4.valid()));
|
||||
|
||||
DenseTensorMeta meta_5(meta_4);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_5.dtype,
|
||||
dtype,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected dtype: %s, but got: %s",
|
||||
dtype,
|
||||
meta_5.dtype));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_5.dims,
|
||||
dims,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected dims: %s, but got: %s",
|
||||
dims,
|
||||
meta_5.dims));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_5.layout,
|
||||
layout,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected layout: %s, but got: %s",
|
||||
layout,
|
||||
meta_5.layout));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_5.legacy_lod,
|
||||
lod,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail in copy DenseTensorMeta. Expected lod: %s, but got: %s",
|
||||
lod,
|
||||
meta_5.legacy_lod));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
meta_5.valid(),
|
||||
true,
|
||||
common::errors::InvalidArgument("Fail in copy DenseTensorMeta. Expected "
|
||||
"meta_5 to be valid, but got: %s",
|
||||
meta_5.valid()));
|
||||
}
|
||||
|
||||
TEST(dense_tensor, zero_size_strides) {
|
||||
const auto zero_size_dims = common::make_ddim({0, 2048});
|
||||
const auto zero_size_strides = DenseTensorMeta::calc_strides(zero_size_dims);
|
||||
const auto expected_zero_size_strides = common::make_ddim({2048, 1});
|
||||
EXPECT_EQ(zero_size_strides, expected_zero_size_strides);
|
||||
|
||||
DenseTensorMeta zero_size_meta(DataType::FLOAT32, zero_size_dims);
|
||||
EXPECT_EQ(zero_size_meta.strides, expected_zero_size_strides);
|
||||
EXPECT_TRUE(zero_size_meta.is_contiguous());
|
||||
|
||||
const auto reshaped_zero_size_dims = common::make_ddim({0, 512, 4});
|
||||
EXPECT_EQ(DenseTensorMeta::calc_strides(reshaped_zero_size_dims),
|
||||
common::make_ddim({2048, 4, 1}));
|
||||
|
||||
const auto unknown_dims = common::make_ddim({-1, 2048});
|
||||
EXPECT_EQ(DenseTensorMeta::calc_strides(unknown_dims), unknown_dims);
|
||||
}
|
||||
|
||||
TEST(dense_tensor, def_ctor) {
|
||||
DenseTensor tensor_0;
|
||||
PADDLE_ENFORCE_EQ(
|
||||
tensor_0.valid(),
|
||||
true,
|
||||
common::errors::InvalidArgument("Fail in default DenseTensor. Expected "
|
||||
"tensor_0 to be valid, but got: %s",
|
||||
tensor_0.valid()));
|
||||
}
|
||||
|
||||
TEST(dense_tensor, ctor) {
|
||||
const DDim dims({1, 2});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
const LegacyLoD lod{};
|
||||
DenseTensorMeta meta(dtype, dims, layout, lod);
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
|
||||
auto check_dense_tensor = [](const DenseTensor& t,
|
||||
const DenseTensorMeta& m) -> bool {
|
||||
bool r{true};
|
||||
r = r && (t.numel() == product(m.dims));
|
||||
r = r && (t.dims() == m.dims);
|
||||
r = r && (t.dtype() == m.dtype);
|
||||
r = r && (t.layout() == m.layout);
|
||||
r = r && (t.place() == phi::CPUPlace());
|
||||
r = r && t.initialized();
|
||||
r = r && t.IsSharedWith(t);
|
||||
return r;
|
||||
};
|
||||
|
||||
DenseTensor tensor_0(alloc, meta);
|
||||
check_dense_tensor(tensor_0, meta);
|
||||
|
||||
DenseTensor tensor_1(alloc, DenseTensorMeta(meta));
|
||||
check_dense_tensor(tensor_0, meta);
|
||||
}
|
||||
|
||||
TEST(dense_tensor, resize) {
|
||||
const DDim dims({1, 2});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
const LegacyLoD lod{};
|
||||
DenseTensorMeta meta(dtype, dims, layout, lod);
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
DenseTensor tensor_0(alloc, meta);
|
||||
|
||||
PADDLE_ENFORCE_EQ(
|
||||
tensor_0.capacity(),
|
||||
2u,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail to initialize DenseTensor. Expected capacity: 2, but got: %s",
|
||||
tensor_0.capacity()));
|
||||
tensor_0.ResizeAndAllocate({1, 2, 3});
|
||||
PADDLE_ENFORCE_EQ(
|
||||
tensor_0.capacity(),
|
||||
6u,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail to resize DenseTensor. Expected capacity: 6, but got: %s",
|
||||
tensor_0.capacity()));
|
||||
}
|
||||
|
||||
TEST(dense_tensor, shallow_copy) {
|
||||
const DDim dims({1, 2});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
const LegacyLoD lod{};
|
||||
DenseTensorMeta meta(dtype, dims, layout, lod);
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
DenseTensor tensor_0(alloc, meta);
|
||||
|
||||
DenseTensor tensor_1(tensor_0);
|
||||
PADDLE_ENFORCE_EQ(tensor_0.meta(),
|
||||
tensor_1.meta(),
|
||||
common::errors::InvalidArgument(
|
||||
"Fail to copy DenseTensor. Expected tensor_0 and "
|
||||
"tensor_1 to have the same meta"));
|
||||
}
|
||||
|
||||
TEST(dense_tensor, dim_indexing) {
|
||||
const DDim dims({4, 3, 2, 0});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
const LegacyLoD lod{};
|
||||
DenseTensorMeta meta(dtype, dims, layout, lod);
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
DenseTensor tensor_0(alloc, meta);
|
||||
int ndim = tensor_0.dims().size();
|
||||
auto tensor_0_dims = tensor_0.dims();
|
||||
for (int i = -ndim; i < ndim; ++i) {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
tensor_0_dims[(i + ndim) % ndim],
|
||||
tensor_0.dims(i),
|
||||
common::errors::InvalidArgument(
|
||||
"Dimension mismatch at index %d. Expected: %d, but got: %d",
|
||||
i,
|
||||
tensor_0_dims[i],
|
||||
tensor_0.dims(i)));
|
||||
}
|
||||
|
||||
// throw exception for index >= ndim
|
||||
bool caught_exception = false;
|
||||
try {
|
||||
tensor_0.dims(ndim);
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
caught_exception = true;
|
||||
}
|
||||
PADDLE_ENFORCE_EQ(
|
||||
caught_exception,
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"Expected an exception to be thrown for index >= ndim"));
|
||||
|
||||
// throw exception for index < -ndim
|
||||
caught_exception = false;
|
||||
try {
|
||||
tensor_0.dims(-ndim - 1);
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
caught_exception = true;
|
||||
}
|
||||
PADDLE_ENFORCE_EQ(
|
||||
caught_exception,
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"Expected an exception to be thrown for index < -ndim"));
|
||||
}
|
||||
|
||||
TEST(dense_tensor, storage_properties) {
|
||||
const DataType dtype{DataType::FLOAT32};
|
||||
const DDim dims({1, 2});
|
||||
DenseTensorMeta meta(dtype, dims);
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
DenseTensor tensor(fancy_allocator.get(), meta);
|
||||
|
||||
// test error type storage properties
|
||||
#ifdef PADDLE_WITH_DNNL
|
||||
bool caught_exception = false;
|
||||
try {
|
||||
tensor.storage_properties<OneDNNStorageProperties>();
|
||||
} catch (common::enforce::EnforceNotMet& error) {
|
||||
caught_exception = true;
|
||||
}
|
||||
PADDLE_ENFORCE_EQ(caught_exception,
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"Fail to get storage properties. Expected an exception "
|
||||
"to be thrown for OneDNNStorageProperties"));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2022 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 <thrust/device_vector.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/common/dim.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
__global__ void test(phi::Dim<2>* o) { o[0] = common::make_dim(5, 6); }
|
||||
|
||||
__global__ void dyn_idx_gpu(int64_t* o) {
|
||||
auto d = common::make_dim(5, 6);
|
||||
o[0] = d[1];
|
||||
}
|
||||
|
||||
TEST(Dim, Equality) {
|
||||
// construct a Dim on the CPU
|
||||
auto a = common::make_dim(3, 4);
|
||||
EXPECT_EQ(a[0], 3);
|
||||
EXPECT_EQ(a[1], 4);
|
||||
|
||||
// construct a Dim on the GPU
|
||||
thrust::device_vector<phi::Dim<2>> t(2);
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
hipLaunchKernelGGL(
|
||||
test, dim3(1), dim3(1), 0, 0, thrust::raw_pointer_cast(t.data()));
|
||||
#else
|
||||
test<<<1, 1>>>(thrust::raw_pointer_cast(t.data()));
|
||||
#endif
|
||||
a = t[0];
|
||||
EXPECT_EQ(a[0], 5);
|
||||
EXPECT_EQ(a[1], 6);
|
||||
|
||||
// product
|
||||
EXPECT_EQ(common::product(a), 30);
|
||||
|
||||
// mutate a Dim
|
||||
auto b = common::make_dim(7, 8);
|
||||
b[1] = 10;
|
||||
EXPECT_EQ(b[0], 7);
|
||||
EXPECT_EQ(b[1], 10);
|
||||
|
||||
b[0] = 8;
|
||||
b[1] = 11;
|
||||
EXPECT_EQ(b[0], 8);
|
||||
EXPECT_EQ(b[1], 11);
|
||||
|
||||
// dynamic access on GPU
|
||||
thrust::device_vector<int64_t> r(1);
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
hipLaunchKernelGGL(
|
||||
dyn_idx_gpu, dim3(1), dim3(1), 0, 0, thrust::raw_pointer_cast(r.data()));
|
||||
#else
|
||||
dyn_idx_gpu<<<1, 1>>>(thrust::raw_pointer_cast(r.data()));
|
||||
#endif
|
||||
int64_t res = r[0];
|
||||
EXPECT_EQ(res, 6);
|
||||
}
|
||||
|
||||
TEST(Dim, Bool) {
|
||||
auto a = common::make_dim(3, 4);
|
||||
auto b = common::make_dim(5, 6);
|
||||
auto c = common::make_dim(3, 4);
|
||||
|
||||
// comparison
|
||||
EXPECT_TRUE(a == a);
|
||||
EXPECT_FALSE(a == b);
|
||||
EXPECT_TRUE(a == c);
|
||||
}
|
||||
|
||||
TEST(Dim, Print) {
|
||||
{
|
||||
std::stringstream ss;
|
||||
auto a = common::make_dim(2, 3);
|
||||
ss << a;
|
||||
EXPECT_EQ(ss.str(), "2, 3");
|
||||
}
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << common::make_dim(8);
|
||||
EXPECT_EQ(ss.str(), "8");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,157 @@
|
||||
/* Copyright (c) 2021 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 <future>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/utils/intrusive_ptr.h"
|
||||
#include "paddle/phi/core/utils/intrusive_ref_counter.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
struct SharedObject : public intrusive_ref_counter<SharedObject> {
|
||||
int i{0};
|
||||
};
|
||||
|
||||
TEST(intrusive_ref_counter, async) {
|
||||
SharedObject obj;
|
||||
const size_t num{100};
|
||||
std::vector<std::future<void>> results;
|
||||
auto add_ref_and_release = [](const SharedObject* p) {
|
||||
intrusive_ptr_add_ref<SharedObject>(p);
|
||||
intrusive_ptr_release<SharedObject>(p);
|
||||
};
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
results.emplace_back(std::async(add_ref_and_release, &obj));
|
||||
}
|
||||
for (auto& result : results) {
|
||||
result.get();
|
||||
}
|
||||
PADDLE_ENFORCE_EQ(obj.use_count(),
|
||||
1U,
|
||||
common::errors::InvalidArgument(
|
||||
"Required obj.use_count() should be equal to 1, "
|
||||
"But received obj.use_count() = %d.",
|
||||
obj.use_count()));
|
||||
}
|
||||
|
||||
TEST(intrusive_ptr, default_ctor) {
|
||||
intrusive_ptr<SharedObject> p;
|
||||
PADDLE_ENFORCE_EQ(p == nullptr,
|
||||
true,
|
||||
common::errors::Fatal("Input pointer is not a nullptr"));
|
||||
}
|
||||
TEST(intrusive_ptr, private_ctor) {
|
||||
auto p = make_intrusive<SharedObject>();
|
||||
const auto* ptr0 = p.get();
|
||||
auto p1 = std::move(p);
|
||||
intrusive_ptr<intrusive_ref_counter<SharedObject>> p2(std::move(p1));
|
||||
const auto* ptr1 = p2.get();
|
||||
PADDLE_ENFORCE_EQ(ptr0,
|
||||
ptr1,
|
||||
common::errors::InvalidArgument(
|
||||
"Required ptr0 should be equal to ptr1. "));
|
||||
}
|
||||
|
||||
TEST(intrusive_ptr, reset_with_obj) {
|
||||
SharedObject obj;
|
||||
obj.i = 1;
|
||||
intrusive_ptr<SharedObject> p;
|
||||
p.reset(&obj, true);
|
||||
PADDLE_ENFORCE_EQ(p->i,
|
||||
obj.i,
|
||||
common::errors::InvalidArgument(
|
||||
"Required p->i should be equal to obj.i. "));
|
||||
}
|
||||
|
||||
TEST(intrusive_ptr, reset_with_ptr) {
|
||||
auto* ptr = new SharedObject;
|
||||
ptr->i = 1;
|
||||
intrusive_ptr<SharedObject> p;
|
||||
p.reset(ptr, false);
|
||||
PADDLE_ENFORCE_EQ((*p).i,
|
||||
ptr->i,
|
||||
common::errors::InvalidArgument(
|
||||
"Required (*p).i should be equal to ptr->i. "));
|
||||
p.reset();
|
||||
PADDLE_ENFORCE_EQ(
|
||||
p == nullptr,
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"p is not a nullptr, something wrong with intrusive_ptr<T>.reset"));
|
||||
}
|
||||
TEST(intrusive_ptr, op_comp) {
|
||||
auto p = make_intrusive<SharedObject>();
|
||||
auto copy = copy_intrusive<SharedObject>(p);
|
||||
auto null = intrusive_ptr<SharedObject>();
|
||||
auto p1 = make_intrusive<SharedObject>();
|
||||
PADDLE_ENFORCE_EQ(p == copy,
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"intrusive_ptr p is not equal to its copy, something "
|
||||
"wrong with copy constructor "));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
p != p1,
|
||||
true,
|
||||
common::errors::Fatal("intrusive_ptr p is equal to another pointer, "
|
||||
"something wrong with constructor"));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
p == copy.get(),
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"blank intrusive_ptr p's content is not equal to its copy, something "
|
||||
"wrong with constructor or get function"));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
p != p1.get(),
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"intrusive_ptr p's content is equal to another blank pointer, "
|
||||
"something wrong with constructor or get function"));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
p.get() == copy,
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"blank intrusive_ptr p's content is not equal to its copy, something "
|
||||
"wrong with constructor or get function"));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
p.get() != p1,
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"intrusive_ptr p's content is equal to another blank pointer, "
|
||||
"something wrong with constructor or get function"));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
null == nullptr,
|
||||
true,
|
||||
common::errors::Fatal("variable or constant whose name is null is not a "
|
||||
"nullptr, something wrong with operator=="));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
nullptr == null,
|
||||
true,
|
||||
common::errors::Fatal("variable or constant whose name is null is not a "
|
||||
"nullptr, something wrong with operator=="));
|
||||
PADDLE_ENFORCE_EQ(p != nullptr,
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"intrusive_ptr p is not not_equal to null, something "
|
||||
"wrong with constructor or operator!= "));
|
||||
PADDLE_ENFORCE_EQ(nullptr != p,
|
||||
true,
|
||||
common::errors::Fatal(
|
||||
"intrusive_ptr p is not not_equal to null, something "
|
||||
"wrong with constructor or operator!= "));
|
||||
}
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,149 @@
|
||||
/* Copyright (c) 2021 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 <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/common/float16.h"
|
||||
#include "paddle/phi/core/dense_tensor.h"
|
||||
#include "paddle/phi/core/kernel_factory.h"
|
||||
#include "paddle/phi/core/kernel_registry.h"
|
||||
|
||||
PD_DECLARE_KERNEL(scale, CPU, ALL_LAYOUT);
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
// TODO(chenweihang): add more unittests later
|
||||
|
||||
TEST(KernelKey, ConstructAndOStream) {
|
||||
phi::KernelKey key(
|
||||
phi::Backend::CPU, phi::DataLayout::NCHW, phi::DataType::FLOAT32);
|
||||
EXPECT_EQ(key.backend(), phi::Backend::CPU);
|
||||
EXPECT_EQ(key.layout(), phi::DataLayout::NCHW);
|
||||
EXPECT_EQ(key.dtype(), phi::DataType::FLOAT32);
|
||||
std::ostringstream oss;
|
||||
oss << key;
|
||||
std::cout << oss.str();
|
||||
oss.flush();
|
||||
}
|
||||
|
||||
TEST(KernelFactory, SelectedKernelMap) {
|
||||
auto kernel_map = phi::KernelFactory::Instance().SelectKernelMap("scale");
|
||||
EXPECT_GT(kernel_map.size(), 1UL);
|
||||
for (auto& iter : kernel_map) {
|
||||
std::cout << iter.first << ": " << iter.second;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename Context>
|
||||
void TestKernel(const Context& dev_ctx,
|
||||
const DenseTensor& x,
|
||||
const DenseTensor& param,
|
||||
DenseTensor* out) {}
|
||||
|
||||
TEST(KernelRegistry, SetFP32Input) {
|
||||
phi::KernelKey kernel_key(
|
||||
phi::Backend::CPU, phi::DataLayout::ALL_LAYOUT, phi::DataType::FLOAT16);
|
||||
auto test_kernel =
|
||||
phi::KernelFactory::Instance().SelectKernel("test", kernel_key);
|
||||
EXPECT_TRUE(test_kernel.IsValid());
|
||||
auto& arg_defs = test_kernel.args_def();
|
||||
auto& input_defs = arg_defs.input_defs();
|
||||
auto& attr_defs = arg_defs.attribute_defs();
|
||||
auto& output_defs = arg_defs.output_defs();
|
||||
EXPECT_EQ(input_defs.size(), 2UL);
|
||||
EXPECT_EQ(attr_defs.size(), 0UL);
|
||||
EXPECT_EQ(output_defs.size(), 1UL);
|
||||
EXPECT_EQ(input_defs.at(0).dtype, phi::DataType::FLOAT16);
|
||||
EXPECT_EQ(input_defs.at(1).dtype, phi::DataType::FLOAT32);
|
||||
EXPECT_EQ(output_defs.at(0).dtype, phi::DataType::FLOAT16);
|
||||
}
|
||||
|
||||
TEST(AttributeType, OStream) {
|
||||
std::ostringstream oss;
|
||||
oss << phi::AttributeType::UNDEFINED;
|
||||
EXPECT_EQ(oss.str(), "Undefined");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::BOOL;
|
||||
EXPECT_EQ(oss.str(), "bool");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::INT32;
|
||||
EXPECT_EQ(oss.str(), "int");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::INT64;
|
||||
EXPECT_EQ(oss.str(), "int64_t");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::FLOAT32;
|
||||
EXPECT_EQ(oss.str(), "float");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::FLOAT64;
|
||||
EXPECT_EQ(oss.str(), "double");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::STRING;
|
||||
EXPECT_EQ(oss.str(), "string");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::BOOLS;
|
||||
EXPECT_EQ(oss.str(), "vector<bool>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::INT32S;
|
||||
EXPECT_EQ(oss.str(), "vector<int>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::INT64S;
|
||||
EXPECT_EQ(oss.str(), "vector<int64_t>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::FLOAT32S;
|
||||
EXPECT_EQ(oss.str(), "vector<float>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::FLOAT64S;
|
||||
EXPECT_EQ(oss.str(), "vector<double>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::STRINGS;
|
||||
EXPECT_EQ(oss.str(), "vector<string>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::SCALAR;
|
||||
EXPECT_EQ(oss.str(), "Scalar");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::SCALARS;
|
||||
EXPECT_EQ(oss.str(), "vector<Scalar>");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::INT_ARRAY;
|
||||
EXPECT_EQ(oss.str(), "IntArray");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::DATA_TYPE;
|
||||
EXPECT_EQ(oss.str(), "DataType");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::DATA_LAYOUT;
|
||||
EXPECT_EQ(oss.str(), "DataLayout");
|
||||
oss.str("");
|
||||
oss << phi::AttributeType::PLACE;
|
||||
EXPECT_EQ(oss.str(), "Place");
|
||||
oss.str("");
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
|
||||
PD_REGISTER_KERNEL(test,
|
||||
CPU,
|
||||
ALL_LAYOUT,
|
||||
phi::tests::TestKernel,
|
||||
float,
|
||||
double,
|
||||
phi::dtype::float16) {
|
||||
if (kernel_key.dtype() == phi::DataType::FLOAT16) {
|
||||
kernel->InputAt(1).SetDataType(phi::DataType::FLOAT32);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Copyright (c) 2022 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 <iostream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/dense_tensor.h"
|
||||
#include "paddle/phi/core/infermeta_utils.h"
|
||||
#include "paddle/phi/infermeta/unary.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
TEST(MetaFnFactory, InferMetaFnExists) {
|
||||
phi::DenseTensor dense_x;
|
||||
dense_x.Resize(common::make_ddim({3, 4}));
|
||||
|
||||
phi::MetaTensor meta_x(&dense_x);
|
||||
phi::DenseTensor dense_out1;
|
||||
phi::MetaTensor meta_out(&dense_out1);
|
||||
phi::UnchangedInferMeta(meta_x, &meta_out);
|
||||
}
|
||||
|
||||
void TestEmptyVectorInputInferMeta(const std::vector<const MetaTensor*>& inputs,
|
||||
std::vector<MetaTensor*> outputs) {
|
||||
ASSERT_EQ(inputs.size(), 0UL);
|
||||
ASSERT_EQ(outputs.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST(MetaFnFactory, EmptyVectorInputInferMetaFn) {
|
||||
phi::InferMetaContext ctx;
|
||||
ctx.EmplaceBackInput(MetaTensor());
|
||||
ctx.EmplaceBackOutput(MetaTensor());
|
||||
|
||||
PD_INFER_META(TestEmptyVectorInputInferMeta)(&ctx);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,74 @@
|
||||
/* Copyright (c) 2016 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/phi/core/mixed_vector.h"
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "gtest/gtest-message.h"
|
||||
#include "gtest/gtest-test-part.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/gtest_pred_impl.h"
|
||||
|
||||
template <typename T>
|
||||
using vec = phi::Vector<T>;
|
||||
|
||||
TEST(mixed_vector, CPU_VECTOR) {
|
||||
vec<int> tmp;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
tmp.push_back(i);
|
||||
}
|
||||
ASSERT_EQ(tmp.size(), 10UL);
|
||||
vec<int> tmp2;
|
||||
tmp2 = tmp;
|
||||
ASSERT_EQ(tmp2.size(), 10UL);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ASSERT_EQ(tmp2[i], i);
|
||||
ASSERT_EQ(tmp2[i], tmp[i]);
|
||||
}
|
||||
int cnt = 0;
|
||||
for (auto& t : tmp2) {
|
||||
ASSERT_EQ(t, cnt);
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(mixed_vector, InitWithCount) {
|
||||
phi::Vector<int> vec(10, 10);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ASSERT_EQ(vec[i], 10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(mixed_vector, ForEach) {
|
||||
vec<int> tmp;
|
||||
for (auto& v : tmp) {
|
||||
VLOG(3) << v;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(mixed_vector, Reserve) {
|
||||
phi::Vector<int> vec;
|
||||
vec.reserve(1);
|
||||
vec.push_back(0);
|
||||
vec.push_back(0);
|
||||
vec.push_back(0);
|
||||
}
|
||||
|
||||
TEST(mixed_vector, Resize) {
|
||||
phi::Vector<int> vec;
|
||||
vec.resize(1);
|
||||
vec.push_back(0);
|
||||
vec.push_back(0);
|
||||
vec.push_back(0);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Copyright (c) 2016 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. */
|
||||
|
||||
#ifdef PADDLE_WITH_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
#include <hip/hip_runtime.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/backends/context_pool.h"
|
||||
#include "paddle/phi/backends/gpu/gpu_info.h"
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/phi/core/mixed_vector.h"
|
||||
|
||||
template <typename T>
|
||||
using vec = phi::MixVector<T>;
|
||||
using gpuStream_t = phi::gpuStream_t;
|
||||
|
||||
static __global__ void multiply_10(int* ptr) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ptr[i] *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
gpuStream_t GetCUDAStream(phi::GPUPlace place) {
|
||||
return reinterpret_cast<const phi::GPUContext*>(
|
||||
phi::DeviceContextPool::Instance().Get(place))
|
||||
->stream();
|
||||
}
|
||||
|
||||
TEST(mixed_vector, GPU_VECTOR) {
|
||||
std::vector<int> x;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
x.push_back(i);
|
||||
}
|
||||
vec<int> tmp(&x);
|
||||
ASSERT_EQ(tmp.size(), 10UL);
|
||||
phi::GPUPlace gpu(0);
|
||||
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
hipLaunchKernelGGL(multiply_10,
|
||||
dim3(1),
|
||||
dim3(1),
|
||||
0,
|
||||
GetCUDAStream(gpu),
|
||||
tmp.MutableData(gpu));
|
||||
#else
|
||||
multiply_10<<<1, 1, 0, GetCUDAStream(gpu)>>>(tmp.MutableData(gpu));
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ASSERT_EQ(tmp[i], i * 10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(mixed_vector, MultiGPU) {
|
||||
if (phi::backends::gpu::GetGPUDeviceCount() < 2) {
|
||||
LOG(WARNING) << "Skip mixed_vector.MultiGPU since there are not multiple "
|
||||
"GPUs in your machine.";
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> x;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
x.push_back(i);
|
||||
}
|
||||
vec<int> tmp(&x);
|
||||
ASSERT_EQ(tmp.size(), 10UL);
|
||||
phi::GPUPlace gpu0(0);
|
||||
phi::backends::gpu::SetDeviceId(0);
|
||||
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
hipLaunchKernelGGL(multiply_10,
|
||||
dim3(1),
|
||||
dim3(1),
|
||||
0,
|
||||
GetCUDAStream(gpu0),
|
||||
tmp.MutableData(gpu0));
|
||||
#else
|
||||
multiply_10<<<1, 1, 0, GetCUDAStream(gpu0)>>>(tmp.MutableData(gpu0));
|
||||
#endif
|
||||
phi::GPUPlace gpu1(1);
|
||||
auto* gpu1_ptr = tmp.MutableData(gpu1);
|
||||
phi::backends::gpu::SetDeviceId(1);
|
||||
|
||||
#ifdef PADDLE_WITH_HIP
|
||||
hipLaunchKernelGGL(
|
||||
multiply_10, dim3(1), dim3(1), 0, GetCUDAStream(gpu1), gpu1_ptr);
|
||||
#else
|
||||
multiply_10<<<1, 1, 0, GetCUDAStream(gpu1)>>>(gpu1_ptr);
|
||||
#endif
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ASSERT_EQ(tmp[i], i * 100);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) 2021 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 <iostream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/fluid/operators/ops_signature/signatures.h"
|
||||
#include "paddle/phi/core/compat/op_utils.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
TEST(OpUtilsMap, ArgMappingFnExists) {
|
||||
std::cout << "enter ArgMappingFnExists";
|
||||
auto scale_arg_mapping_fn =
|
||||
phi::OpUtilsMap::Instance().GetArgumentMappingFn("scale");
|
||||
EXPECT_NE(scale_arg_mapping_fn, nullptr);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Copyright (c) 2022 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 <gtest/gtest.h> // NOLINT
|
||||
|
||||
#include <thread> // NOLINT
|
||||
|
||||
#include "paddle/phi/core/utils/rw_lock.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
void f1(phi::RWLock *lock) {
|
||||
lock->RDLock();
|
||||
lock->UNLock();
|
||||
}
|
||||
|
||||
TEST(RWLOCK, read_read) {
|
||||
phi::RWLock lock;
|
||||
lock.RDLock();
|
||||
std::thread t1(f1, &lock);
|
||||
std::thread t2(f1, &lock);
|
||||
t1.join();
|
||||
t2.join();
|
||||
lock.UNLock();
|
||||
}
|
||||
|
||||
void f2(phi::RWLock *lock, std::vector<int> *result) {
|
||||
lock->RDLock();
|
||||
ASSERT_EQ(result->size(), 0UL);
|
||||
lock->UNLock();
|
||||
}
|
||||
|
||||
void f3(phi::RWLock *lock, std::vector<int> *result) {
|
||||
lock->WRLock();
|
||||
result->push_back(1);
|
||||
lock->UNLock();
|
||||
}
|
||||
|
||||
TEST(RWLOCK, read_write) {
|
||||
phi::RWLock lock;
|
||||
std::vector<int> result;
|
||||
|
||||
lock.RDLock();
|
||||
std::thread t1(f2, &lock, &result);
|
||||
t1.join();
|
||||
std::thread t2(f3, &lock, &result);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
ASSERT_EQ(result.size(), 0UL);
|
||||
lock.UNLock();
|
||||
t2.join();
|
||||
ASSERT_EQ(result.size(), 1UL);
|
||||
}
|
||||
|
||||
void f4(phi::RWLock *lock, std::vector<int> *result) {
|
||||
lock->RDLock();
|
||||
ASSERT_EQ(result->size(), 1UL);
|
||||
lock->UNLock();
|
||||
}
|
||||
|
||||
TEST(RWLOCK, write_read) {
|
||||
phi::RWLock lock;
|
||||
std::vector<int> result;
|
||||
|
||||
lock.WRLock();
|
||||
std::thread t1(f4, &lock, &result);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
result.push_back(1);
|
||||
lock.UNLock();
|
||||
t1.join();
|
||||
}
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,185 @@
|
||||
/* Copyright (c) 2022 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 <ctime>
|
||||
|
||||
#include <thread> // NOLINT
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/selected_rows.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
class SelectedRowsTester : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
std::vector<int64_t> rows{0, 4, 7};
|
||||
int64_t height = 10;
|
||||
int64_t row_numel = 100;
|
||||
selected_rows_ = std::make_unique<SelectedRows>(rows, height);
|
||||
|
||||
phi::DenseTensor* value = selected_rows_->mutable_value();
|
||||
auto* data = value->mutable_data<float>(
|
||||
common::make_ddim({static_cast<int64_t>(rows.size()), row_numel}),
|
||||
place_);
|
||||
for (int64_t i = 0; i < value->numel(); ++i) {
|
||||
data[i] = static_cast<float>(i);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
phi::CPUPlace place_;
|
||||
std::unique_ptr<phi::SelectedRows> selected_rows_{nullptr};
|
||||
};
|
||||
|
||||
TEST_F(SelectedRowsTester, height) { ASSERT_EQ(selected_rows_->height(), 10); }
|
||||
|
||||
TEST_F(SelectedRowsTester, dims) {
|
||||
ASSERT_EQ(selected_rows_->value().dims(), common::make_ddim({3, 100}));
|
||||
}
|
||||
|
||||
TEST_F(SelectedRowsTester, complete_dims) {
|
||||
ASSERT_EQ(selected_rows_->GetCompleteDims(), common::make_ddim({10, 100}));
|
||||
}
|
||||
|
||||
TEST(SelectedRows, SparseTable) {
|
||||
phi::CPUPlace cpu;
|
||||
SelectedRows table;
|
||||
|
||||
int64_t table_size = 100;
|
||||
int64_t embedding_width = 8;
|
||||
// initialize a sparse table
|
||||
table.mutable_value()->Resize(
|
||||
common::make_ddim({table_size, embedding_width}));
|
||||
auto* data = table.mutable_value()->mutable_data<float>(cpu);
|
||||
for (int64_t i = 0; i < table_size; ++i) {
|
||||
for (int64_t j = 0; j < embedding_width; ++j) {
|
||||
data[i * embedding_width + j] = static_cast<float>(i);
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(table.AutoGrownIndex(10, true, false), 0);
|
||||
ASSERT_EQ(table.AutoGrownIndex(8, true, false), 1);
|
||||
ASSERT_EQ(table.AutoGrownIndex(8, true, false), 1);
|
||||
ASSERT_EQ(table.AutoGrownIndex(6, true, false), 2);
|
||||
for (int64_t i = 11; i < 20; i++) {
|
||||
ASSERT_EQ(table.AutoGrownIndex(i, true, true), -1);
|
||||
ASSERT_TRUE(!table.HasKey(i));
|
||||
}
|
||||
ASSERT_TRUE(table.HasKey(10));
|
||||
ASSERT_TRUE(table.HasKey(8));
|
||||
ASSERT_TRUE(table.HasKey(6));
|
||||
ASSERT_EQ(table.rows().size(), 3UL);
|
||||
|
||||
phi::DenseTensor ids;
|
||||
ids.Resize(common::make_ddim({4}));
|
||||
auto* ids_data = ids.mutable_data<int64_t>(cpu);
|
||||
ids_data[0] = static_cast<int64_t>(6);
|
||||
ids_data[1] = static_cast<int64_t>(6);
|
||||
ids_data[2] = static_cast<int64_t>(8);
|
||||
ids_data[3] = static_cast<int64_t>(10);
|
||||
|
||||
phi::DenseTensor get_value;
|
||||
auto* value_data = get_value.mutable_data<float>(
|
||||
common::make_ddim({4, embedding_width}), cpu);
|
||||
table.Get(ids, &get_value);
|
||||
|
||||
for (int j = 0; j < embedding_width; ++j) {
|
||||
ASSERT_EQ(value_data[0 * embedding_width + j], 2);
|
||||
}
|
||||
for (int j = 0; j < embedding_width; ++j) {
|
||||
ASSERT_EQ(value_data[1 * embedding_width + j], 2);
|
||||
}
|
||||
for (int j = 0; j < embedding_width; ++j) {
|
||||
ASSERT_EQ(value_data[2 * embedding_width + j], 1);
|
||||
}
|
||||
for (int j = 0; j < embedding_width; ++j) {
|
||||
ASSERT_EQ(value_data[3 * embedding_width + j], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void f1(SelectedRows* table, int table_size) {
|
||||
for (int i = 1000000; i > 0; --i) {
|
||||
auto id = i % table_size;
|
||||
int64_t index1 = table->AutoGrownIndex(id, true);
|
||||
int64_t index2 = table->AutoGrownIndex(id, false);
|
||||
int64_t index3 = table->AutoGrownIndex(id, true);
|
||||
ASSERT_EQ(index1, index2);
|
||||
ASSERT_EQ(index2, index3);
|
||||
}
|
||||
}
|
||||
|
||||
void f2(SelectedRows* table, int table_size) {
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
auto id = i % table_size;
|
||||
int64_t index1 = table->AutoGrownIndex(id, true);
|
||||
int64_t index2 = table->AutoGrownIndex(id, false);
|
||||
int64_t index3 = table->AutoGrownIndex(id, true);
|
||||
ASSERT_EQ(index1, index2);
|
||||
ASSERT_EQ(index2, index3);
|
||||
}
|
||||
}
|
||||
|
||||
void f3(SelectedRows* table, int table_size) {
|
||||
clock_t t1 = clock();
|
||||
for (int i = 100000; i > 0; --i) {
|
||||
auto id1 = table->AutoGrownIndex(i % table_size, true);
|
||||
auto id2 = table->Index(i % table_size);
|
||||
ASSERT_EQ(id1, id2);
|
||||
}
|
||||
clock_t t2 = clock();
|
||||
std::cout << "f3 run time:" << t2 - t1 << std::endl;
|
||||
}
|
||||
|
||||
void f4(SelectedRows* table, int table_size) {
|
||||
clock_t t1 = clock();
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
auto id1 = table->AutoGrownIndex(i % table_size, true);
|
||||
auto id2 = table->Index(i % table_size);
|
||||
ASSERT_EQ(id1, id2);
|
||||
}
|
||||
clock_t t2 = clock();
|
||||
std::cout << "f4 run time:" << t2 - t1 << std::endl;
|
||||
}
|
||||
|
||||
TEST(SelectedRows, MultiThreadAutoIndex) {
|
||||
phi::CPUPlace cpu;
|
||||
SelectedRows table;
|
||||
|
||||
int64_t table_size = 100000;
|
||||
int64_t embedding_width = 8;
|
||||
// initialize a sparse table
|
||||
table.mutable_value()->Resize(
|
||||
common::make_ddim({table_size, embedding_width}));
|
||||
auto* data = table.mutable_value()->mutable_data<float>(cpu);
|
||||
for (int64_t i = 0; i < table_size; ++i) {
|
||||
for (int64_t j = 0; j < embedding_width; ++j) {
|
||||
data[i * embedding_width + j] = static_cast<float>(i);
|
||||
}
|
||||
}
|
||||
|
||||
std::thread t1(f1, &table, table_size);
|
||||
std::thread t11(f1, &table, table_size);
|
||||
std::thread t2(f2, &table, table_size);
|
||||
std::thread t22(f2, &table, table_size);
|
||||
t1.join();
|
||||
t11.join();
|
||||
t2.join();
|
||||
t22.join();
|
||||
std::thread t3(f3, &table, table_size);
|
||||
std::thread t4(f4, &table, table_size);
|
||||
t3.join();
|
||||
t4.join();
|
||||
}
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,114 @@
|
||||
/* Copyright (c) 2021 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 "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/dense_tensor.h"
|
||||
#include "paddle/phi/core/sparse_coo_tensor.h"
|
||||
#include "test/cpp/phi/core/allocator.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
TEST(sparse_coo_tensor, construct) {
|
||||
phi::CPUPlace cpu;
|
||||
auto dense_dims = common::make_ddim({3, 3});
|
||||
std::vector<float> non_zero_data = {1.0, 2.0, 3.0};
|
||||
std::vector<int64_t> indices_data = {0, 1, 2, 0, 2, 1};
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
auto indices_dims =
|
||||
common::make_ddim({2, static_cast<int>(non_zero_data.size())});
|
||||
DenseTensorMeta indices_meta(DataType::INT64, indices_dims, DataLayout::NCHW);
|
||||
DenseTensor indices(alloc, indices_meta);
|
||||
memcpy(indices.mutable_data<int64_t>(cpu),
|
||||
&indices_data[0],
|
||||
indices_data.size() * sizeof(int64_t));
|
||||
|
||||
auto elements_dims =
|
||||
common::make_ddim({static_cast<int>(non_zero_data.size())});
|
||||
DenseTensorMeta elements_meta(
|
||||
DataType::FLOAT32, elements_dims, DataLayout::NCHW);
|
||||
DenseTensor elements(alloc, elements_meta);
|
||||
|
||||
memcpy(elements.mutable_data<float>(cpu),
|
||||
&non_zero_data[0],
|
||||
non_zero_data.size() * sizeof(float));
|
||||
|
||||
SparseCooTensor sparse(indices, elements, dense_dims);
|
||||
|
||||
CHECK(sparse.initialized() == true);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
sparse.nnz(),
|
||||
non_zero_data.size(),
|
||||
common::errors::InvalidArgument(
|
||||
"Required sparse.nnz() should be equal to non_zero_data.size(). "));
|
||||
PADDLE_ENFORCE_EQ(sparse.numel(),
|
||||
9,
|
||||
common::errors::InvalidArgument(
|
||||
"Required sparse.numel() should be equal to 9. "));
|
||||
CHECK(sparse.dims() == dense_dims);
|
||||
CHECK(sparse.dtype() == DataType::FLOAT32);
|
||||
CHECK(sparse.place() == phi::CPUPlace());
|
||||
}
|
||||
|
||||
TEST(sparse_coo_tensor, other_function) {
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
auto dense_dims = common::make_ddim({4, 4});
|
||||
const int non_zero_num = 2;
|
||||
auto indices_dims = common::make_ddim({2, non_zero_num});
|
||||
DenseTensorMeta indices_meta(DataType::INT64, indices_dims, DataLayout::NCHW);
|
||||
DenseTensor indices(alloc, indices_meta);
|
||||
|
||||
auto elements_dims = common::make_ddim({non_zero_num});
|
||||
DenseTensorMeta elements_meta(
|
||||
DataType::FLOAT32, elements_dims, DataLayout::NCHW);
|
||||
DenseTensor elements(alloc, elements_meta);
|
||||
|
||||
SparseCooTensor coo(indices, elements, dense_dims);
|
||||
CHECK(coo.initialized());
|
||||
PADDLE_ENFORCE_EQ(coo.dims(),
|
||||
dense_dims,
|
||||
common::errors::InvalidArgument(
|
||||
"Required coo.dims() should be equal to dense_dims. "));
|
||||
|
||||
// Test Resize
|
||||
auto dense_dims_3d = common::make_ddim({2, 4, 4});
|
||||
coo.Resize(dense_dims_3d, 1, 3);
|
||||
PADDLE_ENFORCE_EQ(coo.nnz(),
|
||||
3,
|
||||
common::errors::InvalidArgument(
|
||||
"Required coo.nnz() should be equal to 3. "));
|
||||
|
||||
// Test shallow_copy
|
||||
SparseCooTensor coo2(coo);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
coo.dims(),
|
||||
coo2.dims(),
|
||||
common::errors::Fatal("`coo.dims()` is not equal to `coo2.dims()`, "
|
||||
"something wrong with shallow copy assignment"));
|
||||
|
||||
// Test shallow_copy_assignment
|
||||
SparseCooTensor coo3 = coo2;
|
||||
CHECK(coo3.dims() == coo2.dims());
|
||||
PADDLE_ENFORCE_EQ(
|
||||
coo3.dims(),
|
||||
coo2.dims(),
|
||||
common::errors::Fatal("`coo3.dims()` is not equal to `coo2.dims()`, "
|
||||
"something wrong with shallow copy assignment"));
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,125 @@
|
||||
/* Copyright (c) 2021 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 "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/api/lib/utils/allocator.h"
|
||||
#include "paddle/phi/core/dense_tensor.h"
|
||||
#include "paddle/phi/core/sparse_csr_tensor.h"
|
||||
#include "test/cpp/phi/core/allocator.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
TEST(sparse_csr_tensor, construct) {
|
||||
phi::CPUPlace cpu;
|
||||
auto dense_dims = common::make_ddim({3, 3});
|
||||
std::vector<float> non_zero_data = {1.0, 2.0, 3.0};
|
||||
std::vector<int64_t> crows_data = {0, 1, 1, 3};
|
||||
std::vector<int64_t> cols_data = {1, 0, 2};
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto alloc = fancy_allocator.get();
|
||||
// create non_zero_crows
|
||||
auto crows_dims = common::make_ddim({static_cast<int>(crows_data.size())});
|
||||
DenseTensorMeta crows_meta(DataType::INT64, crows_dims, DataLayout::NCHW);
|
||||
DenseTensor crows(alloc, crows_meta);
|
||||
memcpy(crows.mutable_data<int64_t>(cpu),
|
||||
&crows_data[0],
|
||||
crows_data.size() * sizeof(int64_t));
|
||||
|
||||
// create non_zero_cols
|
||||
auto cols_dims = common::make_ddim({static_cast<int>(cols_data.size())});
|
||||
DenseTensorMeta cols_meta(DataType::INT64, cols_dims, DataLayout::NCHW);
|
||||
DenseTensor cols(alloc, cols_meta);
|
||||
memcpy(cols.mutable_data<int64_t>(cpu),
|
||||
&cols_data[0],
|
||||
cols_data.size() * sizeof(int64_t));
|
||||
|
||||
// create non_zero_elements
|
||||
auto elements_dims =
|
||||
common::make_ddim({static_cast<int>(non_zero_data.size())});
|
||||
DenseTensorMeta elements_meta(
|
||||
DataType::FLOAT32, elements_dims, DataLayout::NCHW);
|
||||
DenseTensor elements(alloc, elements_meta);
|
||||
memcpy(elements.mutable_data<float>(cpu),
|
||||
&non_zero_data[0],
|
||||
non_zero_data.size() * sizeof(float));
|
||||
|
||||
SparseCsrTensor sparse(crows, cols, elements, dense_dims);
|
||||
|
||||
PADDLE_ENFORCE_EQ(sparse.non_zero_cols().numel(),
|
||||
non_zero_data.size(),
|
||||
common::errors::InvalidArgument(
|
||||
"Required sparse.non_zero_cols().numel() should be "
|
||||
"equal to non_zero_data.size(). "));
|
||||
PADDLE_ENFORCE_EQ(sparse.numel(),
|
||||
9,
|
||||
common::errors::InvalidArgument(
|
||||
"Required sparse.numel() should be equal to 9. "));
|
||||
CHECK(sparse.dims() == dense_dims);
|
||||
CHECK(sparse.dtype() == DataType::FLOAT32);
|
||||
CHECK(sparse.place() == phi::CPUPlace());
|
||||
CHECK(sparse.initialized() == true);
|
||||
}
|
||||
TEST(sparse_csr_tensor, other_function) {
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto alloc = fancy_allocator.get();
|
||||
auto dense_dims = common::make_ddim({4, 4});
|
||||
auto crows_dims = common::make_ddim({dense_dims[0] + 1});
|
||||
DenseTensorMeta crows_meta(DataType::INT64, crows_dims, DataLayout::NCHW);
|
||||
DenseTensor crows(alloc, crows_meta);
|
||||
|
||||
const int64_t non_zero_num = 5;
|
||||
auto cols_dims = common::make_ddim({non_zero_num});
|
||||
DenseTensorMeta cols_meta(DataType::INT64, cols_dims, DataLayout::NCHW);
|
||||
DenseTensor cols(alloc, cols_meta);
|
||||
DenseTensorMeta values_meta(DataType::FLOAT32, cols_dims, DataLayout::NCHW);
|
||||
DenseTensor values(alloc, values_meta);
|
||||
|
||||
SparseCsrTensor csr(crows, cols, values, dense_dims);
|
||||
CHECK(csr.initialized());
|
||||
PADDLE_ENFORCE_EQ(csr.dims(),
|
||||
dense_dims,
|
||||
common::errors::InvalidArgument(
|
||||
"Required csr.dims() should be equal to dense_dims. "));
|
||||
|
||||
// Test Resize
|
||||
auto dense_dims_3d = common::make_ddim({2, 4, 4});
|
||||
csr.Resize(dense_dims_3d, 2);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
csr.non_zero_cols().numel(),
|
||||
2,
|
||||
common::errors::InvalidArgument(
|
||||
"Required csr.non_zero_cols().numel() should be equal to 2. "));
|
||||
|
||||
// Test shallow_copy
|
||||
SparseCsrTensor csr2(csr);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
csr.dims(),
|
||||
csr2.dims(),
|
||||
common::errors::Fatal("`csr.dims()` should be equal to `csr2.dims()`, "
|
||||
"something wrong with shallow copy"));
|
||||
|
||||
// Test shallow_copy_assignment
|
||||
SparseCsrTensor csr3 = csr2;
|
||||
PADDLE_ENFORCE_EQ(
|
||||
csr3.dims(),
|
||||
csr2.dims(),
|
||||
common::errors::Fatal("``csr3.dims()` should be equal to `csr2.dims()`, "
|
||||
"something wrong with shallow copy assignment"));
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,356 @@
|
||||
/* Copyright (c) 2022 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 <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/api/lib/utils/allocator.h"
|
||||
#include "paddle/phi/backends/context_pool.h"
|
||||
#include "paddle/phi/common/pstring.h"
|
||||
#include "paddle/phi/core/string_tensor.h"
|
||||
#include "test/cpp/phi/core/allocator.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
using pstring = ::phi::dtype::pstring;
|
||||
|
||||
TEST(string_tensor, ctor) {
|
||||
const DDim dims({1, 2});
|
||||
StringTensorMeta meta(dims);
|
||||
const auto string_allocator =
|
||||
std::make_unique<paddle::experimental::DefaultAllocator>(phi::CPUPlace());
|
||||
const auto alloc = string_allocator.get();
|
||||
auto check_string_tensor = [](const StringTensor& t,
|
||||
const StringTensorMeta& m) -> bool {
|
||||
bool r{true};
|
||||
r = r && (t.numel() == product(m.dims));
|
||||
r = r && (t.dims() == m.dims);
|
||||
r = r && (t.place() == phi::CPUPlace());
|
||||
r = r && t.initialized();
|
||||
r = r && t.IsSharedWith(t);
|
||||
r = r && (t.meta() == m);
|
||||
return r;
|
||||
};
|
||||
auto cpu = CPUPlace();
|
||||
|
||||
phi::DeviceContextPool& pool = phi::DeviceContextPool::Instance();
|
||||
CPUContext* cpu_ctx = reinterpret_cast<CPUContext*>(pool.Get(cpu));
|
||||
|
||||
StringTensor tensor_0(alloc, meta);
|
||||
check_string_tensor(tensor_0, meta);
|
||||
|
||||
pstring pshort_str = pstring("A short pstring.");
|
||||
pstring plong_str =
|
||||
pstring("A large pstring whose length is longer than 22.");
|
||||
|
||||
pstring* data = cpu_ctx->template Alloc<pstring>(&tensor_0);
|
||||
data[0] = plong_str;
|
||||
data[1] = pshort_str;
|
||||
PADDLE_ENFORCE_EQ(tensor_0.data()[0],
|
||||
plong_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_0 should be equal to '%s', but got '%s'.",
|
||||
plong_str,
|
||||
tensor_0.data()[0]));
|
||||
PADDLE_ENFORCE_EQ(tensor_0.data()[1],
|
||||
pshort_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_0 should be equal to '%s', but got '%s'.",
|
||||
pshort_str,
|
||||
tensor_0.data()[1]));
|
||||
|
||||
// Test Copy Constructor
|
||||
StringTensor tensor_1(tensor_0);
|
||||
PADDLE_ENFORCE_EQ(tensor_1.data()[0],
|
||||
plong_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_1 should be equal to '%s', but got '%s'.",
|
||||
plong_str,
|
||||
tensor_1.data()[0]));
|
||||
PADDLE_ENFORCE_EQ(tensor_1.data()[1],
|
||||
pshort_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_1 should be equal to '%s', but got '%s'.",
|
||||
pshort_str,
|
||||
tensor_1.data()[1]));
|
||||
|
||||
// Test Copy Assignment
|
||||
StringTensor tensor_2(alloc, meta);
|
||||
tensor_2 = tensor_1;
|
||||
PADDLE_ENFORCE_EQ(tensor_2.data()[0],
|
||||
plong_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_2 should be equal to '%s', but got '%s'.",
|
||||
plong_str,
|
||||
tensor_2.data()[0]));
|
||||
PADDLE_ENFORCE_EQ(tensor_2.data()[1],
|
||||
pshort_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_2 should be equal to '%s', but got '%s'.",
|
||||
pshort_str,
|
||||
tensor_2.data()[1]));
|
||||
|
||||
// Test Move Assignment
|
||||
StringTensor tensor_3(alloc, meta);
|
||||
tensor_3 = std::move(tensor_1);
|
||||
PADDLE_ENFORCE_EQ(tensor_3.data()[0],
|
||||
plong_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_3 should be equal to '%s', but got '%s'.",
|
||||
plong_str,
|
||||
tensor_3.data()[0]));
|
||||
PADDLE_ENFORCE_EQ(tensor_3.data()[1],
|
||||
pshort_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The tensor_3 should be equal to '%s', but got '%s'.",
|
||||
pshort_str,
|
||||
tensor_3.data()[1]));
|
||||
|
||||
tensor_3.set_meta(meta);
|
||||
}
|
||||
|
||||
TEST(pstring, func) {
|
||||
// Test Ctor
|
||||
pstring empty_str;
|
||||
pstring nchar_str(5, 'A');
|
||||
pstring copy_nchar_str(nchar_str);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
empty_str,
|
||||
"",
|
||||
common::errors::InvalidArgument(
|
||||
"The empty_str should be empty, but got '%s'.", empty_str));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
nchar_str,
|
||||
"AAAAA",
|
||||
common::errors::InvalidArgument(
|
||||
"The nchar_str should be 'AAAAA', but got '%s'.", nchar_str));
|
||||
PADDLE_ENFORCE_EQ(copy_nchar_str,
|
||||
"AAAAA",
|
||||
common::errors::InvalidArgument(
|
||||
"The copy_nchar_str should be 'AAAAA', but got '%s'.",
|
||||
copy_nchar_str));
|
||||
|
||||
// Test Move Ctor
|
||||
pstring move_nchar_str(nchar_str);
|
||||
PADDLE_ENFORCE_EQ(move_nchar_str,
|
||||
"AAAAA",
|
||||
common::errors::InvalidArgument(
|
||||
"The move_nchar_str should be 'AAAAA', but got '%s'.",
|
||||
move_nchar_str));
|
||||
pstring std_str(std::string("BBBB"));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
std_str,
|
||||
"BBBB",
|
||||
common::errors::InvalidArgument(
|
||||
"The std_str should be 'BBBB', but got '%s'.", std_str));
|
||||
|
||||
pstring long_str = "A large pstring whose length is longer than 22.";
|
||||
pstring short_str = "A short pstring.";
|
||||
|
||||
// Test operator+
|
||||
pstring plus_str = move_nchar_str + std_str;
|
||||
PADDLE_ENFORCE_EQ(
|
||||
plus_str,
|
||||
"AAAAABBBB",
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be 'AAAAABBBB', but got '%s'.", plus_str));
|
||||
|
||||
// Test insert
|
||||
plus_str.insert(5, 1, 'C');
|
||||
PADDLE_ENFORCE_EQ(
|
||||
plus_str,
|
||||
"AAAAACBBBB",
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be 'AAAAABBBB', but got '%s'.", plus_str));
|
||||
plus_str.insert(5, "DDD", 0, 2);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
plus_str,
|
||||
"AAAAADDCBBBB",
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be 'AAAAABBBB', but got '%s'.", plus_str));
|
||||
|
||||
// Test pushback
|
||||
plus_str.push_back('E');
|
||||
PADDLE_ENFORCE_EQ(
|
||||
plus_str,
|
||||
"AAAAADDCBBBBE",
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be 'AAAAADDCBBBBE', but got '%s'.", plus_str));
|
||||
|
||||
// Test append
|
||||
plus_str.append("FF");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
plus_str,
|
||||
"AAAAADDCBBBBEFF",
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be 'AAAAADDCBBBBEFF', but got '%s'.", plus_str));
|
||||
plus_str.append(2, 'G');
|
||||
PADDLE_ENFORCE_EQ(
|
||||
plus_str,
|
||||
"AAAAADDCBBBBEFFGG",
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be 'AAAAADDCBBBBEFFGG', but got '%s'.",
|
||||
plus_str));
|
||||
|
||||
// Test operator[]
|
||||
PADDLE_ENFORCE_EQ(
|
||||
long_str[0],
|
||||
'A',
|
||||
common::errors::InvalidArgument(
|
||||
"The long_str[0] should be 'A', but got '%s'.", long_str[0]));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
short_str[0],
|
||||
'A',
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str[0] should be 'A', but got '%s'.", short_str[0]));
|
||||
|
||||
// Test capacity
|
||||
PADDLE_ENFORCE_EQ(short_str.capacity(),
|
||||
22UL,
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str's capacity should be 22, but got %d.",
|
||||
short_str.capacity()));
|
||||
|
||||
// Test reserve
|
||||
pstring reserve_str;
|
||||
PADDLE_ENFORCE_EQ(reserve_str.capacity(),
|
||||
22UL,
|
||||
common::errors::InvalidArgument(
|
||||
"The reserve_str's capacity should be 22, but got %d.",
|
||||
reserve_str.capacity()));
|
||||
// small -> large
|
||||
reserve_str.reserve(100);
|
||||
PADDLE_ENFORCE_EQ(reserve_str.capacity(),
|
||||
111UL,
|
||||
common::errors::InvalidArgument(
|
||||
"The reserve_str's capacity should be 111, but got %d.",
|
||||
reserve_str.capacity())); // align(100) - 1 = 111
|
||||
// reserve more memory
|
||||
reserve_str.reserve(200);
|
||||
PADDLE_ENFORCE_EQ(reserve_str.capacity(),
|
||||
207UL,
|
||||
common::errors::InvalidArgument(
|
||||
"The reserve_str's capacity should be 207, but got %d.",
|
||||
reserve_str.capacity())); // align(200) - 1 = 207
|
||||
|
||||
// Test operator<<
|
||||
std::ostringstream oss1, oss2;
|
||||
oss1 << long_str;
|
||||
PADDLE_ENFORCE_EQ(
|
||||
oss1.str(),
|
||||
long_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The oss1 should be '%s', but got '%s'.", long_str, oss1.str()));
|
||||
|
||||
// Test iterator
|
||||
for (auto str_item : long_str) {
|
||||
oss2 << str_item;
|
||||
}
|
||||
PADDLE_ENFORCE_EQ(
|
||||
oss2.str(),
|
||||
long_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The oss2 should be '%s', but got '%s'.", long_str, oss2.str()));
|
||||
|
||||
// Test comparison operators
|
||||
PADDLE_ENFORCE_EQ((long_str < short_str),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"The long_str should be less than short_str."));
|
||||
|
||||
PADDLE_ENFORCE_EQ((long_str > short_str),
|
||||
false,
|
||||
common::errors::InvalidArgument(
|
||||
"The long_str should not be greater than short_str."));
|
||||
PADDLE_ENFORCE_EQ((long_str == short_str),
|
||||
false,
|
||||
common::errors::InvalidArgument(
|
||||
"The long_str should not be equal to short_str."));
|
||||
PADDLE_ENFORCE_EQ((long_str != short_str),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"The long_str should not be equal to short_str."));
|
||||
PADDLE_ENFORCE_EQ((short_str < long_str),
|
||||
false,
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str should not be less than long_str."));
|
||||
PADDLE_ENFORCE_EQ((short_str > long_str),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str should be greater than long_str."));
|
||||
PADDLE_ENFORCE_EQ((move_nchar_str < plus_str),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"The move_nchar_str should be less than plus_str."));
|
||||
PADDLE_ENFORCE_EQ((plus_str > move_nchar_str),
|
||||
true,
|
||||
common::errors::InvalidArgument(
|
||||
"The plus_str should be greater than move_nchar_str."));
|
||||
|
||||
// Test empty
|
||||
PADDLE_ENFORCE_EQ(
|
||||
empty_str.empty(),
|
||||
true,
|
||||
common::errors::InvalidArgument("The empty_str should be empty."));
|
||||
PADDLE_ENFORCE_EQ(
|
||||
nchar_str.empty(),
|
||||
false,
|
||||
common::errors::InvalidArgument("The nchar_str should not be empty."));
|
||||
PADDLE_ENFORCE_EQ(empty_str.length(),
|
||||
0UL,
|
||||
common::errors::InvalidArgument(
|
||||
"The empty_str's length should be 0, but got %d.",
|
||||
empty_str.length()));
|
||||
|
||||
// Test Resize
|
||||
nchar_str.resize(6, 'B');
|
||||
PADDLE_ENFORCE_EQ(
|
||||
nchar_str,
|
||||
"AAAAAB",
|
||||
common::errors::InvalidArgument(
|
||||
"The nchar_str should be 'AAAAAB', but got '%s'.", nchar_str));
|
||||
|
||||
// Test operator =
|
||||
long_str = std::move(nchar_str);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
long_str,
|
||||
"AAAAAB",
|
||||
common::errors::InvalidArgument(
|
||||
"The long_str should be 'AAAAAB', but got '%s'.", long_str));
|
||||
long_str = short_str;
|
||||
PADDLE_ENFORCE_EQ(
|
||||
short_str,
|
||||
long_str,
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str should be '%s', but got '%s'.", long_str, short_str));
|
||||
short_str = 'A';
|
||||
PADDLE_ENFORCE_EQ(
|
||||
short_str,
|
||||
"A",
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str should be 'A', but got '%s'.", short_str));
|
||||
short_str = std::move(copy_nchar_str);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
short_str,
|
||||
"AAAAA",
|
||||
common::errors::InvalidArgument(
|
||||
"The short_str should be 'AAAAA', but got '%s'.", short_str));
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2022 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 "gtest/gtest.h"
|
||||
#include "paddle/phi/core/distributed/store/tcp_store.h"
|
||||
#include "paddle/phi/core/distributed/store/tcp_utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace phi {
|
||||
namespace distributed {
|
||||
|
||||
TEST(MasterDaemon, init) {
|
||||
int socket = tcputils::tcp_listen("", std::to_string(0), AF_INET);
|
||||
std::unique_ptr<detail::MasterDaemon> d =
|
||||
detail::MasterDaemon::createDaemon(socket, 1, 100);
|
||||
d->start();
|
||||
printf("started to sleep 2s\n");
|
||||
#ifdef _WIN32
|
||||
Sleep(2 * 1000);
|
||||
#else
|
||||
usleep(2 * 1000 * 1000);
|
||||
#endif
|
||||
printf("end to reset\n");
|
||||
|
||||
d.reset();
|
||||
}
|
||||
|
||||
/* now for only c compile test
|
||||
TEST(TCPStore, init) {
|
||||
TCPStore store("127.0.0.1", 6170, true, 1);
|
||||
store.add("my", 3);
|
||||
auto ret1 = store.get("my");
|
||||
store.add("my", 3);
|
||||
auto ret2 = store.get("my");
|
||||
PADDLE_ENFORCE_EQ(ret1[0] + 3, ret2[0],
|
||||
paddle::errors::Fatal("result of add is not right"));
|
||||
}
|
||||
*/
|
||||
} // namespace distributed
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,122 @@
|
||||
/* Copyright (c) 2022 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 <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/common/errors.h"
|
||||
#include "paddle/phi/backends/all_context.h"
|
||||
#include "paddle/phi/core/enforce.h"
|
||||
#include "paddle/phi/core/tensor_array.h"
|
||||
#include "test/cpp/phi/core/allocator.h"
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
using pstring = ::phi::dtype::pstring;
|
||||
|
||||
TEST(tensor_array, tensor_array_not_init) {
|
||||
const DDim dims({1, 2});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
const LegacyLoD lod{};
|
||||
DenseTensorMeta meta(dtype, dims, layout, lod);
|
||||
DenseTensor tensor_0;
|
||||
tensor_0.set_meta(meta);
|
||||
|
||||
std::vector<DenseTensor> tensors;
|
||||
tensors.push_back(tensor_0);
|
||||
tensors.push_back(tensor_0);
|
||||
tensors.push_back(tensor_0);
|
||||
|
||||
TensorArray tensor_array(tensors);
|
||||
|
||||
try {
|
||||
tensor_array.dims();
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
std::string ex_msg = error.what();
|
||||
EXPECT_TRUE(ex_msg.find("dims") != std::string::npos);
|
||||
}
|
||||
|
||||
try {
|
||||
tensor_array.place();
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
std::string ex_msg = error.what();
|
||||
EXPECT_TRUE(ex_msg.find("place") != std::string::npos);
|
||||
}
|
||||
|
||||
try {
|
||||
tensor_array.dtype();
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
std::string ex_msg = error.what();
|
||||
EXPECT_TRUE(ex_msg.find("dtype") != std::string::npos);
|
||||
}
|
||||
|
||||
try {
|
||||
tensor_array.layout();
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
std::string ex_msg = error.what();
|
||||
EXPECT_TRUE(ex_msg.find("layout") != std::string::npos);
|
||||
}
|
||||
|
||||
try {
|
||||
tensor_array.numel();
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
std::string ex_msg = error.what();
|
||||
EXPECT_TRUE(ex_msg.find("numel") != std::string::npos);
|
||||
}
|
||||
|
||||
try {
|
||||
tensor_array.valid();
|
||||
} catch (const common::enforce::EnforceNotMet& error) {
|
||||
std::string ex_msg = error.what();
|
||||
EXPECT_TRUE(ex_msg.find("valid") != std::string::npos);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(!tensor_array.initialized());
|
||||
}
|
||||
|
||||
TEST(tensor_array, tensor_array_init) {
|
||||
const DDim dims1({1, 2});
|
||||
const DDim dims2({1, 2, 3});
|
||||
const DataType dtype{DataType::INT8};
|
||||
const DataLayout layout{DataLayout::NHWC};
|
||||
const LegacyLoD lod{};
|
||||
|
||||
DenseTensorMeta meta1(dtype, dims1, layout, lod);
|
||||
DenseTensorMeta meta2(dtype, dims2, layout, lod);
|
||||
|
||||
auto fancy_allocator = std::unique_ptr<Allocator>(new FancyAllocator);
|
||||
auto* alloc = fancy_allocator.get();
|
||||
DenseTensor tensor_0;
|
||||
tensor_0.set_meta(meta1);
|
||||
|
||||
DenseTensor tensor_1;
|
||||
tensor_1.set_meta(meta2);
|
||||
|
||||
std::vector<DenseTensor> tensors;
|
||||
tensors.push_back(tensor_0);
|
||||
tensors.push_back(tensor_1);
|
||||
tensors.push_back(tensor_0);
|
||||
|
||||
TensorArray tensor_array(tensors);
|
||||
tensor_array.AllocateFrom(alloc, DataType::INT8);
|
||||
|
||||
EXPECT_TRUE(tensor_array.initialized());
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,86 @@
|
||||
/* Copyright (c) 2021 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 <memory>
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/phi/core/utils/type_registry.h"
|
||||
|
||||
namespace phi {
|
||||
|
||||
template <typename BaseT, typename DerivedT>
|
||||
const TypeInfo<BaseT> TypeInfoTraits<BaseT, DerivedT>::kType =
|
||||
RegisterStaticType<BaseT>(DerivedT::name());
|
||||
|
||||
template <typename BaseT, typename DerivedT>
|
||||
bool TypeInfoTraits<BaseT, DerivedT>::classof(const BaseT* obj) {
|
||||
return obj->type_info() == kType;
|
||||
}
|
||||
|
||||
template <typename BaseT, typename DerivedT>
|
||||
TypeInfoTraits<BaseT, DerivedT>::TypeInfoTraits() {
|
||||
static_cast<BaseT*>(static_cast<DerivedT*>(this))->type_info_ = kType;
|
||||
}
|
||||
|
||||
namespace tests {
|
||||
|
||||
template <typename T>
|
||||
class Base {
|
||||
public:
|
||||
TypeInfo<Base<T>> type_info() const { return type_info_; }
|
||||
|
||||
private:
|
||||
template <typename T1, typename T2>
|
||||
friend class phi::TypeInfoTraits;
|
||||
TypeInfo<Base<T>> type_info_{TypeInfo<Base<T>>::kUnknownType};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class DerivedA : public Base<T>, public TypeInfoTraits<Base<T>, DerivedA<T>> {
|
||||
public:
|
||||
static const char* name() { return "DerivedA"; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class DerivedB : public Base<T>, public TypeInfoTraits<Base<T>, DerivedB<T>> {
|
||||
public:
|
||||
static const char* name() { return "DerivedB"; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void check_type_info() {
|
||||
std::unique_ptr<Base<T>> base(new Base<T>);
|
||||
std::unique_ptr<Base<T>> derived_a(new DerivedA<T>);
|
||||
std::unique_ptr<Base<T>> derived_b(new DerivedB<T>);
|
||||
|
||||
EXPECT_EQ(DerivedA<T>::classof(derived_a.get()), true);
|
||||
EXPECT_EQ(DerivedB<T>::classof(derived_b.get()), true);
|
||||
EXPECT_EQ(DerivedB<T>::classof(derived_a.get()), false);
|
||||
EXPECT_EQ(DerivedA<T>::classof(derived_b.get()), false);
|
||||
|
||||
EXPECT_EQ(base->type_info().id(), 0);
|
||||
EXPECT_EQ(derived_a->type_info().id(), 1);
|
||||
EXPECT_EQ(derived_b->type_info().id(), 2);
|
||||
|
||||
EXPECT_EQ(base->type_info().name(), "Unknown");
|
||||
EXPECT_EQ(derived_a->type_info().name(), "DerivedA");
|
||||
EXPECT_EQ(derived_b->type_info().name(), "DerivedB");
|
||||
}
|
||||
|
||||
TEST(type_info, base) {
|
||||
check_type_info<int>();
|
||||
check_type_info<float>();
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Copyright (c) 2021 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. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono> // NOLINT
|
||||
|
||||
namespace phi {
|
||||
namespace tests {
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
std::chrono::high_resolution_clock::time_point start;
|
||||
std::chrono::high_resolution_clock::time_point startu;
|
||||
|
||||
void tic() { start = std::chrono::high_resolution_clock::now(); }
|
||||
double toc() {
|
||||
startu = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> time_span =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(startu -
|
||||
start);
|
||||
double used_time_ms = static_cast<double>(time_span.count()) * 1000.0;
|
||||
return used_time_ms;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace phi
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2022 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/common/unroll_array_ops.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace phi {
|
||||
namespace framework {
|
||||
|
||||
template <typename T>
|
||||
bool CheckEquality(const T* p, size_t n, T val) {
|
||||
return std::all_of(p, p + n, [val](const T& v) { return v == val; });
|
||||
}
|
||||
|
||||
template <int D1, int D2>
|
||||
bool FillConstantTestMain() {
|
||||
static_assert(D1 >= D2);
|
||||
std::array<int, D1> arr = {};
|
||||
arr.fill(0);
|
||||
|
||||
common::UnrollFillConstant<D2>::Run(arr.data(), 1);
|
||||
return CheckEquality(arr.data(), D2, 1) &&
|
||||
CheckEquality(arr.data() + D2, arr.size() - D2, 0);
|
||||
}
|
||||
|
||||
TEST(unroll_ops, fill_constant) {
|
||||
EXPECT_TRUE((FillConstantTestMain<9, 0>()));
|
||||
EXPECT_TRUE((FillConstantTestMain<9, 1>()));
|
||||
EXPECT_TRUE((FillConstantTestMain<9, 4>()));
|
||||
EXPECT_TRUE((FillConstantTestMain<9, 9>()));
|
||||
}
|
||||
|
||||
TEST(unroll_ops, assign) {
|
||||
const int a[] = {1, 2, 3, 4, 5}; // NOLINT
|
||||
int b[] = {0, 0, 0, 0, 0}; // NOLINT
|
||||
common::UnrollAssign<3>::Run(a, b);
|
||||
EXPECT_EQ(b[0], 1);
|
||||
EXPECT_EQ(b[1], 2);
|
||||
EXPECT_EQ(b[2], 3);
|
||||
EXPECT_EQ(b[3], 0);
|
||||
EXPECT_EQ(b[4], 0);
|
||||
}
|
||||
|
||||
TEST(unroll_ops, var_args_assign) {
|
||||
int a[] = {0, 0, 0}; // NOLINT
|
||||
common::UnrollVarArgsAssign<int>::Run(a, 1, 2);
|
||||
EXPECT_EQ(a[0], 1);
|
||||
EXPECT_EQ(a[1], 2);
|
||||
EXPECT_EQ(a[2], 0);
|
||||
}
|
||||
|
||||
TEST(unroll_ops, compare) {
|
||||
int a[] = {1, 2, 3}; // NOLINT
|
||||
int b[] = {1, 2, 4}; // NOLINT
|
||||
EXPECT_TRUE(common::UnrollCompare<2>::Run(a, b));
|
||||
EXPECT_FALSE(common::UnrollCompare<3>::Run(a, b));
|
||||
|
||||
b[0] = -1;
|
||||
EXPECT_TRUE(common::UnrollCompare<0>::Run(a, b));
|
||||
EXPECT_FALSE(common::UnrollCompare<1>::Run(a, b));
|
||||
}
|
||||
|
||||
TEST(unroll_ops, product) {
|
||||
int a[] = {2, 3, 4}; // NOLINT
|
||||
EXPECT_EQ(common::UnrollProduct<3>::Run(a), a[0] * a[1] * a[2]);
|
||||
}
|
||||
|
||||
} // namespace framework
|
||||
} // namespace phi
|
||||
Reference in New Issue
Block a user