1515#include " paddle/fluid/eager/grad_tensor_holder.h"
1616#include " paddle/fluid/imperative/gradient_accumulator.h"
1717
18+ #include " paddle/fluid/eager/api/generated/eager_generated/forwards/dygraph_functions.h"
1819#include " paddle/fluid/framework/convert_utils.h"
1920#include " paddle/fluid/framework/var_type.h"
2021#include " paddle/phi/kernels/funcs/math_function.h"
@@ -26,9 +27,9 @@ void GradTensorHolder::SetBufferSlotRankZeros(size_t slot_id, size_t rank) {
2627 paddle::experimental::zeros_like (buffer_[slot_id][rank]);
2728}
2829
29- void GradTensorHolder::add ( size_t slot_id, size_t rank,
30- const paddle::experimental::Tensor& t,
31- bool fill_one) {
30+ void GradTensorHolder::CopyValueFromTensor (
31+ size_t slot_id, size_t rank, const paddle::experimental::Tensor& t,
32+ bool fill_one) {
3233 // TODO(jiabin): We need to deal with empty input_buffer with slot size not
3334 // empty;
3435 PADDLE_ENFORCE (slot_id < buffer_.size (),
@@ -50,44 +51,15 @@ void GradTensorHolder::add(size_t slot_id, size_t rank,
5051 slot_id, buffer_[slot_id].size (), rank));
5152 if (!fill_one) {
5253 paddle::experimental::Tensor& buffer_tensor = buffer_[slot_id][rank];
53- // TODO(jiabin): Code bellow is ugly to divide which inner var we used,
54- // remove framework::Variable
55- // related code later.
56- // This if statement is trying to test neither phi::Tensor nor
57- // framework::Variable is initialized.
5854 if ((!buffer_tensor.defined () || !buffer_tensor.initialized ())) {
59- // Simply copy tensor->impl
60- buffer_tensor = t;
55+ // Perform deep copy here
56+ buffer_tensor.copy_ (t, t.inner_place (), false );
57+ buffer_tensor.set_autograd_meta (t.mutable_autograd_meta ());
58+
6159 } else {
62- // Accumulation
63- PADDLE_ENFORCE_EQ (t.initialized (), true ,
64- paddle::platform::errors::Fatal (
65- " We can only accumulate initialized tensor, but we "
66- " got tensor: %s is empty please check you network "
67- " and make sure it creates grads." ,
68- t.name ()));
69- if (t.is_dense_tensor ()) {
70- if (buffer_tensor.is_dense_tensor ()) {
71- paddle::imperative::TensorAdd<paddle::experimental::Tensor>(
72- t, &buffer_tensor);
73- } else {
74- // TODO(jiabin): Support Other TensorBase later
75- paddle::experimental::Tensor new_buffer (
76- std::make_shared<phi::DenseTensor>(), " tmp_accumulator" );
77- paddle::imperative::SelectedRowsAddTensor (buffer_tensor, t,
78- &new_buffer);
79- buffer_tensor.set_impl (new_buffer.impl ());
80- }
81- } else {
82- // TODO(jiabin): Support Other TensorBase later
83- if (buffer_tensor.is_dense_tensor ()) {
84- paddle::imperative::SelectedRowsAddToTensor (t, &buffer_tensor);
85- } else {
86- buffer_tensor =
87- std::move (*paddle::imperative::SelectedRowsMerge<
88- paddle::experimental::Tensor>(t, buffer_tensor));
89- }
90- }
60+ PADDLE_THROW (paddle::platform::errors::Fatal (
61+ " Cannot copy grad_tensors' value to grad tensor holders,"
62+ " input buffer has already been initialized." ));
9163 }
9264 } else {
9365 // Create new tensor->impl and fill it with 1.0
@@ -98,4 +70,72 @@ void GradTensorHolder::add(size_t slot_id, size_t rank,
9870 }
9971}
10072
73+ void GradTensorHolder::add (size_t slot_id, size_t rank,
74+ const paddle::experimental::Tensor& t) {
75+ // TODO(jiabin): We need to deal with empty input_buffer with slot size not
76+ // empty;
77+ PADDLE_ENFORCE (slot_id < buffer_.size (),
78+ paddle::platform::errors::Fatal (
79+ " Invalid slot_id for GradTensorHolder::add() "
80+ " which exceeds size of buffer" ));
81+ VLOG (6 ) << " Add Tensor for buffer_ slot: " << slot_id
82+ << " , size: " << buffer_[slot_id].size ();
83+ if (buffer_[slot_id].empty ()) {
84+ VLOG (6 ) << " Pass add Tensor for buffer_ slot: " << slot_id
85+ << " since its buffer_ is empty " ;
86+ return ;
87+ }
88+ PADDLE_ENFORCE (
89+ rank < buffer_[slot_id].size (),
90+ paddle::platform::errors::Fatal (
91+ " Invalid rank for GradTensorHolder::add() which exceeds size "
92+ " of buffer slot %d, got slot size is: %d rank is: %d" ,
93+ slot_id, buffer_[slot_id].size (), rank));
94+
95+ paddle::experimental::Tensor& buffer_tensor = buffer_[slot_id][rank];
96+ // TODO(jiabin): Code bellow is ugly to divide which inner var we used,
97+ // remove framework::Variable
98+ // related code later.
99+ // This if statement is trying to test neither phi::Tensor nor
100+ // framework::Variable is initialized.
101+ if ((!buffer_tensor.defined () || !buffer_tensor.initialized ())) {
102+ // Simply copy tensor->impl
103+ buffer_tensor = t;
104+ } else {
105+ // Accumulation
106+ PADDLE_ENFORCE_EQ (t.initialized (), true ,
107+ paddle::platform::errors::Fatal (
108+ " We can only accumulate initialized tensor, but we "
109+ " got tensor: %s is empty please check you network "
110+ " and make sure it creates grads." ,
111+ t.name ()));
112+ if (t.is_dense_tensor ()) {
113+ if (buffer_tensor.is_dense_tensor ()) {
114+ buffer_tensor = add_final_state_dygraph_function (t, buffer_tensor);
115+
116+ } else {
117+ // TODO(jiabin): Support Other TensorBase later
118+ // TODO(zhanlve): Replace SelectedRowsAddTensor with
119+ // add_dygraph_function once it's supported
120+ paddle::experimental::Tensor new_buffer (
121+ std::make_shared<phi::DenseTensor>(), " tmp_accumulator" );
122+ paddle::imperative::SelectedRowsAddTensor (buffer_tensor, t,
123+ &new_buffer);
124+ buffer_tensor.set_impl (new_buffer.impl ());
125+ }
126+ } else {
127+ // TODO(jiabin): Support Other TensorBase later
128+ // TODO(zhanlve): Replace SelectedRowsAddTensor with add_dygraph_function
129+ // once it's supported
130+ if (buffer_tensor.is_dense_tensor ()) {
131+ paddle::imperative::SelectedRowsAddToTensor (t, &buffer_tensor);
132+ } else {
133+ buffer_tensor =
134+ std::move (*paddle::imperative::SelectedRowsMerge<
135+ paddle::experimental::Tensor>(t, buffer_tensor));
136+ }
137+ }
138+ }
139+ }
140+
101141} // namespace egr
0 commit comments