From 3a29e4f8c4e97df814126f4afdd5952b5d44bf7a Mon Sep 17 00:00:00 2001 From: zhangkaihuo Date: Fri, 1 Apr 2022 11:40:47 +0800 Subject: [PATCH] Add Sparse Op: copy_sparse_coo and copy_sparse_csr (#41193) --- paddle/fluid/eager/grad_node_info.cc | 36 ++++--- paddle/phi/api/lib/kernel_dispatch.h | 12 ++- paddle/phi/api/lib/tensor_method.cc | 34 +++++++ paddle/phi/core/sparse_coo_tensor.cc | 5 + paddle/phi/core/sparse_coo_tensor.h | 3 + paddle/phi/core/sparse_csr_tensor.cc | 8 ++ paddle/phi/core/sparse_csr_tensor.h | 4 + paddle/phi/kernels/copy_kernel.h | 1 - paddle/phi/kernels/sparse/copy_kernel.cc | 99 +++++++++++++++++++ paddle/phi/kernels/sparse/copy_kernel.h | 41 ++++++++ paddle/phi/kernels/sparse/cpu/convolution.h | 5 +- .../kernels/sparse/cpu/sparse_utils_kernel.cc | 6 +- .../phi/kernels/sparse/gpu/convolution.cu.h | 10 +- .../kernels/sparse/gpu/sparse_utils_kernel.cu | 6 +- .../kernels/test_sparse_conv3d_dev_api.cc | 15 +-- .../tests/kernels/test_sparse_pool_dev_api.cc | 22 ++--- .../tests/unittests/test_sparse_copy_op.py | 51 ++++++++++ 17 files changed, 306 insertions(+), 52 deletions(-) create mode 100644 paddle/phi/kernels/sparse/copy_kernel.cc create mode 100644 paddle/phi/kernels/sparse/copy_kernel.h create mode 100644 python/paddle/fluid/tests/unittests/test_sparse_copy_op.py diff --git a/paddle/fluid/eager/grad_node_info.cc b/paddle/fluid/eager/grad_node_info.cc index 5f3dfe8e51..22266ff386 100644 --- a/paddle/fluid/eager/grad_node_info.cc +++ b/paddle/fluid/eager/grad_node_info.cc @@ -19,6 +19,7 @@ #include "paddle/phi/common/data_type.h" #include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/core/sparse_coo_tensor.h" #include "paddle/fluid/framework/convert_utils.h" #include "paddle/fluid/framework/data_type.h" @@ -124,29 +125,32 @@ void GradNodeBase::SetGradInMeta(const paddle::experimental::Tensor& fwd_out, return; } + phi::DenseTensor* dense_tensor = nullptr; // Record TensorMeta if (phi::DenseTensor::classof(fwd_out.impl().get())) { // Only Copy Meta - phi::DenseTensor* dense_tensor = - static_cast(fwd_out.impl().get()); - - PADDLE_ENFORCE_NE( - dense_tensor->meta().dtype, phi::DataType::UNDEFINED, - paddle::platform::errors::Fatal( - "Attempting to copy DenseTensorMeta with phi::DataType::UNDEFINED," - "which is illegal.")); - - meta.SetTensorMeta(dense_tensor->meta()); - meta.SetPlace(fwd_out.inner_place()); - - if (paddle::framework::IsComplexType( - paddle::framework::TransToProtoVarType(dense_tensor->type()))) { - need_complex_to_real_ = true; - } + dense_tensor = static_cast(fwd_out.impl().get()); + } else if (phi::SparseCooTensor::classof(fwd_out.impl().get())) { + phi::SparseCooTensor* coo_tensor = + static_cast(fwd_out.impl().get()); + dense_tensor = coo_tensor->mutable_non_zero_elements(); } else { VLOG(6) << "Unable to initialize the DenseTensorMeta of GradSlotMeta with " "non-DenseTensor argument."; } + PADDLE_ENFORCE_NE( + dense_tensor->meta().dtype, phi::DataType::UNDEFINED, + paddle::platform::errors::Fatal( + "Attempting to copy DenseTensorMeta with phi::DataType::UNDEFINED," + "which is illegal.")); + + meta.SetTensorMeta(dense_tensor->meta()); + meta.SetPlace(fwd_out.inner_place()); + + if (paddle::framework::IsComplexType( + paddle::framework::TransToProtoVarType(dense_tensor->type()))) { + need_complex_to_real_ = true; + } } void GradNodeBase::SetGradInMeta( diff --git a/paddle/phi/api/lib/kernel_dispatch.h b/paddle/phi/api/lib/kernel_dispatch.h index 25b74e7fe3..be545ac9ce 100644 --- a/paddle/phi/api/lib/kernel_dispatch.h +++ b/paddle/phi/api/lib/kernel_dispatch.h @@ -25,6 +25,8 @@ limitations under the License. */ #include "paddle/phi/common/data_type.h" #include "paddle/phi/common/layout.h" #include "paddle/phi/core/selected_rows.h" +#include "paddle/phi/core/sparse_coo_tensor.h" +#include "paddle/phi/core/sparse_csr_tensor.h" // TODO(chenweihang): split Key, Kernel, Factory into diff files #include "paddle/phi/core/kernel_factory.h" @@ -40,8 +42,10 @@ std::size_t CountLeadingZeros(uint64_t val); phi::DeviceContext* GetDeviceContextByBackend(phi::Backend backend); enum class KernelType { - DENSE_TENSOR_KENREL, // kernel for DenseTensor - SELECTED_ROWS_KENREL // kernel for SelectedRows + DENSE_TENSOR_KENREL, // kernel for DenseTensor + SELECTED_ROWS_KENREL, // kernel for SelectedRows + SPARSE_COO_KERNEL, // kernel for SparseCooTensor + SPARSE_CSR_KERNEL // kernel for SparseCsrTensor }; // TODO(chenweihang): support DataLayout and DataType selected @@ -130,6 +134,10 @@ struct KernelTypeParser : ArgsIterator { void operator()(const Tensor& x) { if (phi::SelectedRows::classof(x.impl().get())) { kernel_type = KernelType::SELECTED_ROWS_KENREL; + } else if (phi::SparseCooTensor::classof(x.impl().get())) { + kernel_type = KernelType::SPARSE_COO_KERNEL; + } else if (phi::SparseCsrTensor::classof(x.impl().get())) { + kernel_type = KernelType::SPARSE_CSR_KERNEL; } } diff --git a/paddle/phi/api/lib/tensor_method.cc b/paddle/phi/api/lib/tensor_method.cc index 7d9f7a7ae1..c4c77ab937 100644 --- a/paddle/phi/api/lib/tensor_method.cc +++ b/paddle/phi/api/lib/tensor_method.cc @@ -177,6 +177,40 @@ void Tensor::copy_(const Tensor &src, target_place, blocking, static_cast(impl_.get())); + } else if (kernel_type == KernelType::SPARSE_COO_KERNEL) { + auto kernel = phi::KernelFactory::Instance().SelectKernelOrThrowError( + "copy_sparse_coo", {kernel_backend, kernel_layout, kernel_data_type}); + VLOG(6) << "copy API kernel key: " << kernel_key; + VLOG(6) << "copy API kernel: " << kernel; + using kernel_signature = void (*)(const platform::DeviceContext &, + const phi::SparseCooTensor &, + phi::Place, + bool, + phi::SparseCooTensor *); + this->set_impl(std::make_shared()); + auto *kernel_fn = kernel.GetVariadicKernelFn(); + (*kernel_fn)(*dev_ctx, + (*(std::static_pointer_cast(src.impl_))), + target_place, + blocking, + static_cast(impl_.get())); + } else if (kernel_type == KernelType::SPARSE_CSR_KERNEL) { + auto kernel = phi::KernelFactory::Instance().SelectKernelOrThrowError( + "copy_sparse_csr", {kernel_backend, kernel_layout, kernel_data_type}); + VLOG(6) << "copy API kernel key: " << kernel_key; + VLOG(6) << "copy API kernel: " << kernel; + using kernel_signature = void (*)(const platform::DeviceContext &, + const phi::SparseCsrTensor &, + phi::Place, + bool, + phi::SparseCsrTensor *); + this->set_impl(std::make_shared()); + auto *kernel_fn = kernel.GetVariadicKernelFn(); + (*kernel_fn)(*dev_ctx, + (*(std::static_pointer_cast(src.impl_))), + target_place, + blocking, + static_cast(impl_.get())); } else { PADDLE_THROW(phi::errors::InvalidArgument( "We currently only support dense tensor copy for now and if u need to " diff --git a/paddle/phi/core/sparse_coo_tensor.cc b/paddle/phi/core/sparse_coo_tensor.cc index ceaebe4e35..7d4261ef82 100644 --- a/paddle/phi/core/sparse_coo_tensor.cc +++ b/paddle/phi/core/sparse_coo_tensor.cc @@ -16,6 +16,11 @@ limitations under the License. */ namespace phi { +SparseCooTensor::SparseCooTensor() { + DenseTensor non_zero_indices, non_zero_elements; + this->SetMember(non_zero_indices, non_zero_elements, {1}, true); +} + SparseCooTensor::SparseCooTensor(const DenseTensor& non_zero_indices, const DenseTensor& non_zero_elements, const DDim& dims) diff --git a/paddle/phi/core/sparse_coo_tensor.h b/paddle/phi/core/sparse_coo_tensor.h index ca3290f33e..ec43c5d621 100644 --- a/paddle/phi/core/sparse_coo_tensor.h +++ b/paddle/phi/core/sparse_coo_tensor.h @@ -30,6 +30,7 @@ namespace phi { class SparseCooTensor : public TensorBase, public TypeInfoTraits { public: + SparseCooTensor(); /// \brief Create the sparse coo tensor /// \param non_zero_indices The indices of non zero elements in original dense /// tensor. @@ -145,6 +146,8 @@ class SparseCooTensor : public TensorBase, void* AllocateFrom(Allocator* allocator, DataType dtype, size_t requested_size = 0) override; + + /// \brief set the dims of original dense tensor void set_dims(const DDim& dims) { this->dims_ = dims; } private: diff --git a/paddle/phi/core/sparse_csr_tensor.cc b/paddle/phi/core/sparse_csr_tensor.cc index cbf5f941b6..ab9717a564 100644 --- a/paddle/phi/core/sparse_csr_tensor.cc +++ b/paddle/phi/core/sparse_csr_tensor.cc @@ -16,6 +16,14 @@ limitations under the License. */ namespace phi { +SparseCsrTensor::SparseCsrTensor() { + DenseTensor crows, cols, values; + this->non_zero_crows_ = crows; + this->non_zero_cols_ = cols; + this->non_zero_elements_ = values; + this->dims_ = phi::make_ddim({1, 1}); +} + inline void check_shape(const DDim& dims) { bool valid = dims.size() == 2 || dims.size() == 3; diff --git a/paddle/phi/core/sparse_csr_tensor.h b/paddle/phi/core/sparse_csr_tensor.h index 8a9de7a841..7e14cad242 100644 --- a/paddle/phi/core/sparse_csr_tensor.h +++ b/paddle/phi/core/sparse_csr_tensor.h @@ -33,6 +33,7 @@ class CompatibleDenseTensorUtils; class SparseCsrTensor : public TensorBase, public TypeInfoTraits { public: + SparseCsrTensor(); /// \brief Because sparse csr tensor is a resource handle, we provide a /// default /// move constructor to support move semantics. @@ -143,6 +144,9 @@ class SparseCsrTensor : public TensorBase, /// return a mutable pointer of non_zero_elements. DenseTensor* mutable_non_zero_elements() { return &non_zero_elements_; } + /// \brief set the dims of original dense tensor + void set_dims(const DDim& dims) { this->dims_ = dims; } + private: // save the compressed rows information of non zero elements DenseTensor non_zero_crows_; diff --git a/paddle/phi/kernels/copy_kernel.h b/paddle/phi/kernels/copy_kernel.h index 95df29f7e6..21b59d8d11 100644 --- a/paddle/phi/kernels/copy_kernel.h +++ b/paddle/phi/kernels/copy_kernel.h @@ -15,7 +15,6 @@ limitations under the License. */ #pragma once #include "paddle/phi/core/dense_tensor.h" -#include "paddle/phi/core/sparse_csr_tensor.h" namespace phi { diff --git a/paddle/phi/kernels/sparse/copy_kernel.cc b/paddle/phi/kernels/sparse/copy_kernel.cc new file mode 100644 index 0000000000..705c19e020 --- /dev/null +++ b/paddle/phi/kernels/sparse/copy_kernel.cc @@ -0,0 +1,99 @@ +/* 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/phi/kernels/sparse/copy_kernel.h" + +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/core/sparse_coo_tensor.h" +#include "paddle/phi/core/sparse_csr_tensor.h" +#include "paddle/phi/kernels/copy_kernel.h" + +namespace phi { +namespace sparse { + +template +void CopyCoo(const Context& dev_ctx, + const SparseCooTensor& src, + Place dst_place, + bool blocking, + SparseCooTensor* dst) { + phi::Copy(dev_ctx, + src.non_zero_indices(), + dst_place, + blocking, + dst->mutable_non_zero_indices()); + + phi::Copy(dev_ctx, + src.non_zero_elements(), + dst_place, + blocking, + dst->mutable_non_zero_elements()); + dst->set_dims(src.dims()); +} + +template +void CopyCsr(const Context& dev_ctx, + const SparseCsrTensor& src, + Place dst_place, + bool blocking, + SparseCsrTensor* dst) { + phi::Copy(dev_ctx, + src.non_zero_crows(), + dst_place, + blocking, + dst->mutable_non_zero_crows()); + + phi::Copy(dev_ctx, + src.non_zero_cols(), + dst_place, + blocking, + dst->mutable_non_zero_cols()); + + phi::Copy(dev_ctx, + src.non_zero_elements(), + dst_place, + blocking, + dst->mutable_non_zero_elements()); + dst->set_dims(src.dims()); +} + +} // namespace sparse +} // namespace phi + +PD_REGISTER_GENERAL_KERNEL(copy_sparse_coo, + CPU, + ALL_LAYOUT, + phi::sparse::CopyCoo, + ALL_DTYPE) {} + +PD_REGISTER_GENERAL_KERNEL(copy_sparse_csr, + CPU, + ALL_LAYOUT, + phi::sparse::CopyCsr, + ALL_DTYPE) {} + +#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) +PD_REGISTER_GENERAL_KERNEL(copy_sparse_coo, + GPU, + ALL_LAYOUT, + phi::sparse::CopyCoo, + ALL_DTYPE) {} +PD_REGISTER_GENERAL_KERNEL(copy_sparse_csr, + GPU, + ALL_LAYOUT, + phi::sparse::CopyCsr, + ALL_DTYPE) {} +#endif diff --git a/paddle/phi/kernels/sparse/copy_kernel.h b/paddle/phi/kernels/sparse/copy_kernel.h new file mode 100644 index 0000000000..a43621a4df --- /dev/null +++ b/paddle/phi/kernels/sparse/copy_kernel.h @@ -0,0 +1,41 @@ +/* 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. */ + +#pragma once + +#include "paddle/phi/api/lib/utils/storage.h" +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/core/sparse_coo_tensor.h" +#include "paddle/phi/core/sparse_csr_tensor.h" +#include "paddle/phi/kernels/empty_kernel.h" + +namespace phi { +namespace sparse { + +template +void CopyCoo(const Context& dev_ctx, + const SparseCooTensor& src, + Place dst_place, + bool blocking, + SparseCooTensor* dst); + +template +void CopyCsr(const Context& dev_ctx, + const SparseCsrTensor& src, + Place dst_place, + bool blocking, + SparseCsrTensor* dst); + +} // namespace sparse +} // namespace phi diff --git a/paddle/phi/kernels/sparse/cpu/convolution.h b/paddle/phi/kernels/sparse/cpu/convolution.h index 93a335e2f1..4ea93f4ad5 100644 --- a/paddle/phi/kernels/sparse/cpu/convolution.h +++ b/paddle/phi/kernels/sparse/cpu/convolution.h @@ -153,8 +153,9 @@ void UpdateRulebookAndOutIndex(const Context& dev_ctx, const int64_t sparse_dim = 4; DenseTensorMeta indices_meta( DataType::INT32, {sparse_dim, out_non_zero_num}, DataLayout::NCHW); - DenseTensorMeta values_meta( - x.dtype(), {out_non_zero_num, out_channels}, x.layout()); + DenseTensorMeta values_meta(x.dtype(), + {out_non_zero_num, out_channels}, + x.non_zero_elements().layout()); phi::DenseTensor out_indices = phi::Empty(dev_ctx, std::move(indices_meta)); phi::DenseTensor out_values = phi::Empty(dev_ctx, std::move(values_meta)); int* out_indices_ptr = out_indices.data(); diff --git a/paddle/phi/kernels/sparse/cpu/sparse_utils_kernel.cc b/paddle/phi/kernels/sparse/cpu/sparse_utils_kernel.cc index 50e95ee0b8..21dd24b5a9 100644 --- a/paddle/phi/kernels/sparse/cpu/sparse_utils_kernel.cc +++ b/paddle/phi/kernels/sparse/cpu/sparse_utils_kernel.cc @@ -121,7 +121,8 @@ void SparseCsrToCooKernel(const Context& dev_ctx, const auto place = dev_ctx.GetPlace(); DenseTensorMeta indices_meta( DataType::INT64, {sparse_dim, non_zero_num}, DataLayout::NCHW); - DenseTensorMeta values_meta(x.dtype(), {non_zero_num}, x.layout()); + DenseTensorMeta values_meta( + x.dtype(), {non_zero_num}, x.non_zero_elements().layout()); phi::DenseTensor indices = phi::Empty(dev_ctx, std::move(indices_meta)); phi::DenseTensor values = phi::Empty(dev_ctx, std::move(values_meta)); int64_t* coo_indices = indices.mutable_data(place); @@ -174,7 +175,8 @@ void SparseCooToCsrKernel(const Context& dev_ctx, DenseTensorMeta crows_meta( DataType::INT64, {batchs * (rows + 1)}, DataLayout::NCHW); DenseTensorMeta cols_meta(DataType::INT64, {non_zero_num}, DataLayout::NCHW); - DenseTensorMeta values_meta(x.dtype(), {non_zero_num}, x.layout()); + DenseTensorMeta values_meta( + x.dtype(), {non_zero_num}, x.non_zero_elements().layout()); phi::DenseTensor non_zero_crows( phi::make_intrusive(place), std::move(crows_meta)); diff --git a/paddle/phi/kernels/sparse/gpu/convolution.cu.h b/paddle/phi/kernels/sparse/gpu/convolution.cu.h index 5b928817f6..a512a60b94 100644 --- a/paddle/phi/kernels/sparse/gpu/convolution.cu.h +++ b/paddle/phi/kernels/sparse/gpu/convolution.cu.h @@ -349,7 +349,10 @@ int ProductRuleBook(const Context& dev_ctx, int kernel_size = kernel_sizes[0] * kernel_sizes[1] * kernel_sizes[2]; const int rulebook_rows = 3; const int rulebook_cols = kernel_size * non_zero_num; - rulebook->ResizeAndAllocate({rulebook_rows, rulebook_cols}); + DenseTensorMeta rulebook_meta( + DataType::INT32, {rulebook_rows, rulebook_cols}, DataLayout::NCHW); + rulebook->set_meta(rulebook_meta); + dev_ctx.Alloc(rulebook, rulebook->dtype(), rulebook->numel() * sizeof(int)); int* rulebook_ptr = rulebook->data(); const auto x_dims = x.dims(); @@ -608,8 +611,9 @@ int ProductRuleBook(const Context& dev_ctx, const int64_t sparse_dim = 4; DenseTensorMeta indices_meta( DataType::INT32, {sparse_dim, out_non_zero_num}, DataLayout::NCHW); - DenseTensorMeta values_meta( - x.dtype(), {out_non_zero_num, kernel_sizes[4]}, x.layout()); + DenseTensorMeta values_meta(x.dtype(), + {out_non_zero_num, kernel_sizes[4]}, + x.non_zero_elements().layout()); phi::DenseTensor out_indices = phi::Empty(dev_ctx, std::move(indices_meta)); phi::DenseTensor out_values = phi::Empty(dev_ctx, std::move(values_meta)); diff --git a/paddle/phi/kernels/sparse/gpu/sparse_utils_kernel.cu b/paddle/phi/kernels/sparse/gpu/sparse_utils_kernel.cu index 8048180e42..1451ef4535 100644 --- a/paddle/phi/kernels/sparse/gpu/sparse_utils_kernel.cu +++ b/paddle/phi/kernels/sparse/gpu/sparse_utils_kernel.cu @@ -257,7 +257,8 @@ void SparseCsrToCooKernel(const Context& dev_ctx, const auto place = dev_ctx.GetPlace(); DenseTensorMeta indices_meta( DataType::INT64, {sparse_dim, non_zero_num}, DataLayout::NCHW); - DenseTensorMeta values_meta(x.dtype(), {non_zero_num}, x.layout()); + DenseTensorMeta values_meta( + x.dtype(), {non_zero_num}, x.non_zero_elements().layout()); DenseTensorMeta offsets_meta(DataType::INT32, {batchs}, DataLayout::NCHW); DenseTensor indices = phi::Empty(dev_ctx, std::move(indices_meta)); DenseTensor values = phi::Empty(dev_ctx, std::move(values_meta)); @@ -385,7 +386,8 @@ void SparseCooToCsrKernel(const Context& dev_ctx, DenseTensorMeta crows_meta( DataType::INT64, {batchs * (rows + 1)}, DataLayout::NCHW); DenseTensorMeta cols_meta(DataType::INT64, {non_zero_num}, DataLayout::NCHW); - DenseTensorMeta values_meta(x.dtype(), {non_zero_num}, x.layout()); + DenseTensorMeta values_meta( + x.dtype(), {non_zero_num}, x.non_zero_elements().layout()); phi::DenseTensor non_zero_crows( phi::make_intrusive(place), std::move(crows_meta)); diff --git a/paddle/phi/tests/kernels/test_sparse_conv3d_dev_api.cc b/paddle/phi/tests/kernels/test_sparse_conv3d_dev_api.cc index 4800e1402b..5e6b097ad3 100644 --- a/paddle/phi/tests/kernels/test_sparse_conv3d_dev_api.cc +++ b/paddle/phi/tests/kernels/test_sparse_conv3d_dev_api.cc @@ -218,11 +218,8 @@ void TestConv3dBase(const std::vector& indices, correct_out_indices.size() * sizeof(int)); ASSERT_EQ(cmp_indices2, 0); - DenseTensor h_features_tensor = phi::Empty( - dev_ctx_cpu, - DenseTensorMeta(paddle::experimental::CppTypeToDataType::Type(), - {d_out.nnz()}, - d_out.layout())); + DenseTensor h_features_tensor = + phi::EmptyLike(dev_ctx_cpu, d_out.non_zero_elements()); phi::Copy(dev_ctx_gpu, d_out.non_zero_elements(), @@ -243,15 +240,11 @@ void TestConv3dBase(const std::vector& indices, strides, 1, subm); - DenseTensor h_features_grad = phi::Empty( - dev_ctx_cpu, - DenseTensorMeta(grads[0].dtype(), grads[0].dims(), grads[0].layout())); + DenseTensor h_features_grad = phi::EmptyLike(dev_ctx_cpu, grads[0]); phi::Copy(dev_ctx_gpu, grads[0], phi::CPUPlace(), true, &h_features_grad); f_verify(h_features_grad.data(), features_grad); - DenseTensor h_kernel_grad = phi::Empty( - dev_ctx_cpu, - DenseTensorMeta(grads[1].dtype(), grads[1].dims(), grads[1].layout())); + DenseTensor h_kernel_grad = phi::EmptyLike(dev_ctx_cpu, grads[1]); phi::Copy(dev_ctx_gpu, grads[1], phi::CPUPlace(), true, &h_kernel_grad); f_verify(h_kernel_grad.data(), kernel_grad); } diff --git a/paddle/phi/tests/kernels/test_sparse_pool_dev_api.cc b/paddle/phi/tests/kernels/test_sparse_pool_dev_api.cc index 2767370416..80b3392a61 100644 --- a/paddle/phi/tests/kernels/test_sparse_pool_dev_api.cc +++ b/paddle/phi/tests/kernels/test_sparse_pool_dev_api.cc @@ -56,6 +56,10 @@ void TestMaxPoolBase(const std::vector& indices, paddle::memory::allocation::AllocatorFacade::Instance() .GetAllocator(paddle::platform::CPUPlace()) .get()); + dev_ctx_cpu.SetHostAllocator( + paddle::memory::allocation::AllocatorFacade::Instance() + .GetAllocator(phi::CPUPlace()) + .get()); dev_ctx_cpu.Init(); const int in_channels = x_dims[4]; @@ -138,11 +142,8 @@ void TestMaxPoolBase(const std::vector& indices, phi::Copy( dev_ctx_gpu, indices_tensor, phi::GPUPlace(), true, &d_indices_tensor); - DenseTensor d_features_tensor = phi::Empty( - dev_ctx_gpu, - DenseTensorMeta(paddle::experimental::CppTypeToDataType::Type(), - {non_zero_num, in_channels}, - DataLayout::NHWC)); + DenseTensor d_features_tensor = + phi::EmptyLike(dev_ctx_gpu, features_tensor); phi::Copy( dev_ctx_gpu, features_tensor, phi::GPUPlace(), true, &d_features_tensor); @@ -178,11 +179,8 @@ void TestMaxPoolBase(const std::vector& indices, correct_out_indices.size() * sizeof(int)); ASSERT_EQ(cmp_indices2, 0); - DenseTensor h_features_tensor = phi::Empty( - dev_ctx_cpu, - DenseTensorMeta(paddle::experimental::CppTypeToDataType::Type(), - {d_out.nnz()}, - d_out.layout())); + DenseTensor h_features_tensor = + phi::EmptyLike(dev_ctx_cpu, d_out.non_zero_elements()); phi::Copy(dev_ctx_gpu, d_out.non_zero_elements(), @@ -198,9 +196,7 @@ void TestMaxPoolBase(const std::vector& indices, d_out, d_out.non_zero_elements(), kernel_sizes); - DenseTensor h_features_grad = phi::Empty( - dev_ctx_cpu, - DenseTensorMeta(x_grad.dtype(), x_grad.dims(), x_grad.layout())); + DenseTensor h_features_grad = phi::EmptyLike(dev_ctx_cpu, x_grad); phi::Copy(dev_ctx_gpu, x_grad, phi::CPUPlace(), true, &h_features_grad); f_verify(h_features_grad.data(), features_grad); } diff --git a/python/paddle/fluid/tests/unittests/test_sparse_copy_op.py b/python/paddle/fluid/tests/unittests/test_sparse_copy_op.py new file mode 100644 index 0000000000..8dab034d64 --- /dev/null +++ b/python/paddle/fluid/tests/unittests/test_sparse_copy_op.py @@ -0,0 +1,51 @@ +# 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. + +from __future__ import print_function +import unittest +import numpy as np +import paddle +from paddle import _C_ops +from paddle.fluid import core +from paddle.fluid.framework import _test_eager_guard + + +class TestSparseCopy(unittest.TestCase): + def test_copy_sparse_coo(self): + with _test_eager_guard(): + np_x = [[0, 1.0, 0], [2.0, 0, 0], [0, 3.0, 0]] + np_values = [1.0, 2.0, 3.0] + dense_x = paddle.to_tensor(np_x, dtype='float32') + coo_x = dense_x.to_sparse_coo(2) + + np_x_2 = [[0, 3.0, 0], [2.0, 0, 0], [0, 3.0, 0]] + dense_x_2 = paddle.to_tensor(np_x_2, dtype='float32') + coo_x_2 = dense_x_2.to_sparse_coo(2) + coo_x_2.copy_(coo_x, True) + assert np.array_equal(np_values, + coo_x_2.non_zero_elements().numpy()) + + def test_copy_sparse_csr(self): + with _test_eager_guard(): + np_x = [[0, 1.0, 0], [2.0, 0, 0], [0, 3.0, 0]] + np_values = [1.0, 2.0, 3.0] + dense_x = paddle.to_tensor(np_x, dtype='float32') + csr_x = dense_x.to_sparse_csr() + + np_x_2 = [[0, 3.0, 0], [2.0, 0, 0], [0, 3.0, 0]] + dense_x_2 = paddle.to_tensor(np_x_2, dtype='float32') + csr_x_2 = dense_x_2.to_sparse_csr() + csr_x_2.copy_(csr_x, True) + assert np.array_equal(np_values, + csr_x_2.non_zero_elements().numpy()) -- GitLab