diff --git a/paddle/fluid/eager/accumulation/gradient_accumulation.cc b/paddle/fluid/eager/accumulation/gradient_accumulation.cc index 826b02b3db0720c0d158a778c8f441e312085c5c..1224b92dec835619cbb458cd68761522aa4d2dd2 100644 --- a/paddle/fluid/eager/accumulation/gradient_accumulation.cc +++ b/paddle/fluid/eager/accumulation/gradient_accumulation.cc @@ -19,6 +19,7 @@ #include "paddle/fluid/eager/eager_tensor.h" #include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/framework/eigen.h" +#include "paddle/fluid/imperative/gradient_accumulator.h" #include "paddle/fluid/operators/math/blas.h" #include "paddle/fluid/operators/math/math_function.h" #include "paddle/fluid/operators/math/math_function_impl.h" @@ -259,80 +260,32 @@ void TensorAdd(const egr::EagerTensor& src, egr::EagerTensor* dst) { paddle::framework::DataTypeToString(data_type), place)); } -void VariableAdd(const egr::EagerTensor& src, egr::EagerTensor* dst) { - // TODO(jiabin): Support other tensor type later - auto* dst_tensor = - dst->MutableVar()->GetMutable(); - auto& src_tensor = src.Var().Get(); - - auto numel = src_tensor.numel(); - - // FIXME(minqiyang): loss_grad op will pass a zero grad of label - // ugly fix for it - if (numel == 0) { - return; - } - - PADDLE_ENFORCE_EQ( - dst_tensor->numel(), numel, - paddle::platform::errors::PreconditionNotMet( - "The number of elements of source tensor and destination tensor " - "should be equal, but got the number of elements of source tensor is " - "%zu and the number of elements of destination tensor is %zu.", - numel, dst_tensor->numel())); - - auto data_type = src_tensor.type(); - auto place = src_tensor.place(); - - PADDLE_ENFORCE_EQ(dst_tensor->type(), data_type, - paddle::platform::errors::PreconditionNotMet( - "The data type of source tensor and destination tensor " - "should be equal, Otherwise, the calculation results " - "will be incorrect.")); - -#define PADDLE_TENSOR_ADD(cpp_type) \ - if (data_type == paddle::framework::DataTypeTrait::DataType()) { \ - TensorAddFunctor func( \ - numel, src_tensor.data(), \ - dst_tensor->mutable_data(place)); \ - paddle::platform::VisitPlace(place, func); \ - return; \ - } - - // TODO(jiabin): Support NPU here - PADDLE_TENSOR_ADD(float); -// NOTE(phlrain): xpu only support float -#ifndef PADDLE_WITH_XPU - PADDLE_TENSOR_ADD(double); - // NOTE(chenweihang): only support complex grad tensor accumulated, - // support selected rows if needed in the future - PADDLE_TENSOR_ADD(paddle::platform::complex); - PADDLE_TENSOR_ADD(paddle::platform::complex); -#endif -#undef PADDLE_TENSOR_ADD - - if (data_type == paddle::framework::proto::VarType::FP16) { - if (paddle::platform::is_gpu_place(place)) { -#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) - return TensorAddImpl(src_tensor, dst_tensor, - place); -#else - PADDLE_THROW(paddle::platform::errors::Unimplemented( - "Gradient accumulation of data type (%s) on place (%s) is not " - "supported in imperative mode", - paddle::framework::DataTypeToString(data_type), place)); -#endif - } else if (paddle::platform::is_cpu_place(place)) { - return TensorAddImpl(src_tensor, dst_tensor, - place); +void VariableAdd(const egr::EagerTensor& src_tensor, + egr::EagerTensor* dst_tensor) { + auto& src = src_tensor.Var(); + auto* dst = dst_tensor->MutableVar(); + + if (dst->IsType()) { + if (src.IsType()) { + paddle::imperative::TensorAdd(src, dst); + } else if (src.IsType()) { + paddle::imperative::SelectedRowsAddToTensor(src, dst); + } else { + PADDLE_THROW(paddle::platform::errors::InvalidArgument( + "Unexpected branch, output variable type is %s", + paddle::framework::ToTypeName(dst->Type()))); + } + } else { + if (src.IsType()) { + paddle::framework::Variable new_dst; + paddle::imperative::SelectedRowsAddTensor(*dst, src, &new_dst); + *dst = std::move(new_dst); + } else { + PADDLE_THROW(paddle::platform::errors::InvalidArgument( + "Unexpected branch, output variable type is %s", + paddle::framework::ToTypeName(dst->Type()))); } } - PADDLE_THROW(paddle::platform::errors::Unimplemented( - "Gradient accumulation of data type (%s) on place (%s) is not " - "supported in imperative mode", - paddle::framework::DataTypeToString(data_type), place)); } } // namespace egr diff --git a/paddle/fluid/eager/legacy/infer_var_type_context.h b/paddle/fluid/eager/legacy/infer_var_type_context.h index 9d9cbeb38ccfabd7cd30714f7253d8cd863ac308..0bc37bee25e849c2c2d5770d7912de7da22fa73a 100644 --- a/paddle/fluid/eager/legacy/infer_var_type_context.h +++ b/paddle/fluid/eager/legacy/infer_var_type_context.h @@ -137,6 +137,10 @@ class TensorRuntimeInferVarTypeContext out->MutableVar()->GetMutable(); break; } + case paddle::framework::proto::VarType::SELECTED_ROWS: { + out->MutableVar()->GetMutable(); + break; + } default: { PADDLE_THROW(paddle::platform::errors::NotFound( "Cannot found var type: %s while running runtime InferVarType", diff --git a/paddle/fluid/imperative/gradient_accumulator.cc b/paddle/fluid/imperative/gradient_accumulator.cc index 9ae8b75075a1a724c31a8e03e071912ba140715a..ffd9aae8ff013145ee166ba687b71405160905ec 100644 --- a/paddle/fluid/imperative/gradient_accumulator.cc +++ b/paddle/fluid/imperative/gradient_accumulator.cc @@ -373,10 +373,9 @@ void SelectedRowsAddToTensor(const framework::Variable& src, framework::DataTypeToString(data_type))); } -static void SelectedRowsAddTensor( - const framework::Variable& src_selected_rows_var, - const framework::Variable& src_tensor_var, - framework::Variable* dst_tensor_var) { +void SelectedRowsAddTensor(const framework::Variable& src_selected_rows_var, + const framework::Variable& src_tensor_var, + framework::Variable* dst_tensor_var) { const auto& src_selected_rows = src_selected_rows_var.Get(); const auto& src_tensor = src_tensor_var.Get(); diff --git a/paddle/fluid/imperative/gradient_accumulator.h b/paddle/fluid/imperative/gradient_accumulator.h index 8896e5d0f406447f524bcdd9215db30d6d2ecc28..f9f8081d30fd47621abb0ab90c40108db0e21295 100644 --- a/paddle/fluid/imperative/gradient_accumulator.h +++ b/paddle/fluid/imperative/gradient_accumulator.h @@ -163,5 +163,14 @@ class SortedGradientAccumulator : public GradientAccumulator { std::vector tmp_grad_vars_; }; +void SelectedRowsAddToTensor(const framework::Variable& src, + framework::Variable* dst); + +void SelectedRowsAddTensor(const framework::Variable& src_selected_rows_var, + const framework::Variable& src_tensor_var, + framework::Variable* dst_tensor_var); + +void TensorAdd(const framework::Variable& src, framework::Variable* dst); + } // namespace imperative } // namespace paddle diff --git a/python/paddle/fluid/tests/unittests/test_imperative_lod_tensor_to_selected_rows.py b/python/paddle/fluid/tests/unittests/test_imperative_lod_tensor_to_selected_rows.py index 64f1715fc975f7bc39e837920dd493590727526d..d54194164a559a743bc5740b2cb941d2ad05fcdd 100644 --- a/python/paddle/fluid/tests/unittests/test_imperative_lod_tensor_to_selected_rows.py +++ b/python/paddle/fluid/tests/unittests/test_imperative_lod_tensor_to_selected_rows.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# 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. @@ -26,6 +26,7 @@ from test_imperative_base import new_program_scope import numpy as np import six from utils import DyGraphProgramDescTracerTestHelper +from paddle.fluid.framework import _test_eager_guard class SimpleNet(fluid.Layer): @@ -74,7 +75,7 @@ class SimpleNet(fluid.Layer): class TestDygraphSimpleNet(unittest.TestCase): - def test_simple_net(self): + def func_simple_net(self): for is_sparse in [True, False]: dtype_list = ["float32"] if not core.is_compiled_with_rocm(): @@ -82,6 +83,11 @@ class TestDygraphSimpleNet(unittest.TestCase): for dtype in dtype_list: self.simple_net_float32(is_sparse, dtype) + def test_simple_net(self): + with _test_eager_guard(): + self.func_simple_net() + self.func_simple_net() + def simple_net_float32(self, is_sparse, dtype): places = [fluid.CPUPlace()] if core.is_compiled_with_cuda(): diff --git a/python/paddle/fluid/tests/unittests/test_imperative_selected_rows_to_lod_tensor.py b/python/paddle/fluid/tests/unittests/test_imperative_selected_rows_to_lod_tensor.py index 8b2e61f8d2a04a2792d361b9db3f191134d74631..eaf63436ae088f2d7e2403b02a14cc3029f2a9a3 100644 --- a/python/paddle/fluid/tests/unittests/test_imperative_selected_rows_to_lod_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_imperative_selected_rows_to_lod_tensor.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# 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. @@ -25,6 +25,7 @@ from paddle.fluid.dygraph.base import to_variable from test_imperative_base import new_program_scope import numpy as np import six +from paddle.fluid.framework import _test_eager_guard class SimpleNet(fluid.Layer): @@ -80,7 +81,7 @@ class SimpleNet(fluid.Layer): class TestDygraphSimpleNet(unittest.TestCase): - def test_simple_net(self): + def func_simple_net(self): for is_sparse in [True, False]: dtype_list = ["float32"] if not core.is_compiled_with_rocm(): @@ -88,6 +89,11 @@ class TestDygraphSimpleNet(unittest.TestCase): for dtype in dtype_list: self.simple_net_float(is_sparse, dtype) + def test_simple_net(self): + with _test_eager_guard(): + self.func_simple_net() + self.func_simple_net() + def simple_net_float(self, is_sparse, dtype): places = [fluid.CPUPlace()] if core.is_compiled_with_cuda():