diff --git a/paddle/fluid/eager/grad_node_info.cc b/paddle/fluid/eager/grad_node_info.cc index 5f3dfe8e513ed4c828445413e27054ad0982005e..22266ff3862932ef8746d7f2ebf7474b4befde82 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 25b74e7fe31b955a8b25529871c503179b302629..be545ac9ce2f78fd925014d613306556c282edf1 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 7d9f7a7ae17c8670fd8ebd15db9b3d8d510df519..c4c77ab93790d9ce419f9f29361ef816f00791f4 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 ceaebe4e35b7120af160e27fca4347add941d458..7d4261ef829727c731345010ee049c029765f0fc 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 ca3290f33e61eb730d3f17a0b8cc72cbf1c0db58..ec43c5d62179b4e6d7b35f15a3ffc85ba173218a 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 cbf5f941b665d8ae2be58472069d2e04891afe29..ab9717a564eb5a69d9018ce04657cfdee54ecdb4 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 8a9de7a8414221a4240a71b3972430d1398a11f3..7e14cad242d12561a712f6dc315368b6a0afe599 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 95df29f7e653af4d27fccc009da1fcdaa2264f59..21b59d8d11b8d5806e16fc08015311454b8b7518 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 0000000000000000000000000000000000000000..705c19e020c84f7fff04ebef0129b1928047ec98 --- /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 0000000000000000000000000000000000000000..a43621a4dfeedded5cee9163b417a3e60730918d --- /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 93a335e2f1c35700d2bf5ef54400c52ed54f6be2..4ea93f4ad5aaf17e718fbb0b81cc3d35a0927d21 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 50e95ee0b8a4876a65b8ba7d09fd2d112eac2b30..21dd24b5a99049c23ad15f22fca57612ddfea643 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 5b928817f64d748ec824a2c28e569181034d1072..a512a60b94ff89e64843062d3890060b99a555f5 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 8048180e425ead98e6db15514caf38c406a2aebf..1451ef45356af585747c0a34cc2ae7047645465c 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 4800e1402ba56f2956c207f44f2656a71d50b92c..5e6b097ad367bffad064c71428860047f99d9b9a 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 27673704168c9eace0958db770a2309d10da648c..80b3392a611b03df841abc3418f65b2337895ae6 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 0000000000000000000000000000000000000000..8dab034d643edb46eedcf11f81213c4760a91b77 --- /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())