eager_properties.cc 8.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* 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. */
// disable numpy compile error
#include <Python.h>

#include <string>
#include <vector>

17
#include "paddle/fluid/eager/accumulation/accumulation_node.h"
18
#include "paddle/fluid/eager/api/all.h"
19
#include "paddle/fluid/eager/api/utils/tensor_utils.h"
20 21 22 23 24 25 26 27
#include "paddle/fluid/eager/autograd_meta.h"
#include "paddle/fluid/eager/utils.h"
#include "paddle/fluid/memory/allocation/allocator.h"
#include "paddle/fluid/memory/memcpy.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/pybind/eager.h"
#include "paddle/fluid/pybind/eager_utils.h"
#include "paddle/fluid/pybind/exception.h"
28 29 30
#include "paddle/phi/common/data_type.h"
#include "paddle/phi/core/compat/convert_utils.h"
#include "paddle/phi/core/dense_tensor.h"
31 32 33 34 35
#pragma GCC diagnostic ignored "-Wwrite-strings"

namespace paddle {
namespace pybind {

36
extern PyTypeObject* p_tensor_type;
37

38 39
PyObject* tensor_properties_get_name(TensorObject* self, void* closure) {
  EAGER_TRY
40 41 42 43 44 45 46
  // NOTE(dev): [why not use egr::Controller::Instance::GernerateUniqueName()?]
  // Beacause Controller must holder a tracer, but 'tensor.name' maybe called
  // everywhere such as static mode in @to_static, which means tracer is None.
  static egr::UniqueNameGenerator name_generator;
  if (self->tensor.name().empty()) {
    self->tensor.set_name(name_generator.Generate());
  }
47
  return ToPyObject(self->tensor.name());
48 49 50
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

51 52
PyObject* tensor_properties_get_type(TensorObject* self, void* closure) {
  EAGER_TRY
53 54 55 56
  if (!self->tensor.defined()) {
    // be same to old dygraph
    return ToPyObject(paddle::framework::proto::VarType::LOD_TENSOR);
  }
57
  if (self->tensor.is_dense_tensor()) {
58
    return ToPyObject(paddle::framework::proto::VarType::LOD_TENSOR);
59 60
  } else if (self->tensor.is_selected_rows()) {
    return ToPyObject(paddle::framework::proto::VarType::SELECTED_ROWS);
61
  } else {
62
    RETURN_PY_NONE
63 64 65 66
  }
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

W
wanghuancoder 已提交
67 68 69 70 71 72
PyObject* tensor_properties_is_leaf(TensorObject* self, void* closure) {
  EAGER_TRY
  return ToPyObject(egr::egr_utils_api::IsLeafTensor(self->tensor));
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

73 74 75
int tensor_properties_set_name(TensorObject* self, PyObject* value,
                               void* closure) {
  EAGER_TRY
76
  self->tensor.set_name(CastPyArg2AttrString(value, 0));
77
  return 0;
0
0x45f 已提交
78
  EAGER_CATCH_AND_THROW_RETURN_NEG
79 80
}

81 82 83
PyObject* tensor_properties_get_stop_gradient(TensorObject* self,
                                              void* closure) {
  EAGER_TRY
84
  auto meta = egr::EagerUtils::autograd_meta(&self->tensor);
85 86 87 88
  return ToPyObject(meta->StopGradient());
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

89 90
PyObject* tensor_properties_get_grad(TensorObject* self, void* closure) {
  EAGER_TRY
91 92
  VLOG(6) << "Get grad for tensor: " << self->tensor.name();
  auto meta = egr::EagerUtils::nullable_autograd_meta(self->tensor);
93
  if (meta && meta->Grad().initialized()) {
94
    return ToPyObject(meta->Grad());
95
  } else {
96
    RETURN_PY_NONE
97
  }
98 99 100
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

101 102 103
int tensor_properties_set_grad(TensorObject* self, PyObject* value,
                               void* closure) {
  EAGER_TRY
104
  auto src = CastPyArg2Tensor(value, 0);
105
  PADDLE_ENFORCE(
106
      egr::egr_utils_api::IsLeafTensor(self->tensor),
107
      paddle::platform::errors::Fatal("Only leaf Tensor can be set grad."));
108 109 110 111 112 113 114 115

  paddle::experimental::Tensor* grad =
      egr::EagerUtils::mutable_grad(self->tensor);
  PADDLE_ENFORCE(grad != nullptr,
                 paddle::platform::errors::Fatal(
                     "Detected NULL grad"
                     "Please check if you have manually cleared"
                     "the grad inside autograd_meta"));
C
Chen Weihang 已提交
116
  grad->copy_(src, self->tensor.place(), true);
117
  return 0;
0
0x45f 已提交
118
  EAGER_CATCH_AND_THROW_RETURN_NEG
119 120
}

121 122 123
int tensor_properties_set_stop_gradient(TensorObject* self, PyObject* value,
                                        void* closure) {
  EAGER_TRY
124
  auto meta = egr::EagerUtils::autograd_meta(&self->tensor);
125
  meta->SetStopGradient(CastPyArg2AttrBoolean(value, 0));
126 127 128
  if (!meta->GradNode()) {
    meta->SetGradNode(std::make_shared<egr::GradNodeAccumulation>(meta));
  }
129
  return 0;
0
0x45f 已提交
130
  EAGER_CATCH_AND_THROW_RETURN_NEG
131 132
}

133 134
PyObject* tensor_properties_get_persistable(TensorObject* self, void* closure) {
  EAGER_TRY
135
  auto meta = egr::EagerUtils::autograd_meta(&self->tensor);
136 137 138 139
  return ToPyObject(meta->Persistable());
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

140 141 142
int tensor_properties_set_persistable(TensorObject* self, PyObject* value,
                                      void* closure) {
  EAGER_TRY
143
  auto meta = egr::EagerUtils::autograd_meta(&self->tensor);
144 145
  meta->SetPersistable(CastPyArg2AttrBoolean(value, 0));
  return 0;
0
0x45f 已提交
146
  EAGER_CATCH_AND_THROW_RETURN_NEG
147 148
}

149 150
PyObject* tensor_properties_get_shape(TensorObject* self, void* closure) {
  EAGER_TRY
151
  std::vector<int64_t> value;
152 153 154 155
  if (!self->tensor.defined()) {
    return ToPyObject(value);
  }
  auto ddim = self->tensor.shape();
156 157 158 159 160 161 162 163 164 165
  size_t rank = static_cast<size_t>(ddim.size());
  value.resize(rank);
  for (size_t i = 0; i < rank; i++) {
    value[i] = ddim[i];
  }

  return ToPyObject(value);
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

166 167
PyObject* tensor_properties_get_place(TensorObject* self, void* closure) {
  EAGER_TRY
C
Chen Weihang 已提交
168
  return ToPyObject(self->tensor.place());
169 170 171
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

172 173
PyObject* tensor_properties_get_place_str(TensorObject* self, void* closure) {
  EAGER_TRY
174
  std::stringstream ostr;
C
Chen Weihang 已提交
175
  ostr << self->tensor.place();
176 177 178 179
  return ToPyObject(ostr.str());
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

180 181
PyObject* tensor_properties_get_dtype(TensorObject* self, void* closure) {
  EAGER_TRY
182 183 184 185
  if (!self->tensor.defined()) {
    // be same to old dygraph
    return ToPyObject(framework::proto::VarType::FP32);
  }
186 187
  return ToPyObject(
      paddle::framework::TransToProtoVarType(self->tensor.type()));
188 189 190 191
  EAGER_CATCH_AND_THROW_RETURN_NULL
}

struct PyGetSetDef variable_properties[] = {
192 193 194 195 196 197 198 199 200 201
    {"grad", (getter)tensor_properties_get_grad,
     (setter)tensor_properties_set_grad, nullptr, nullptr},
    {"name", (getter)tensor_properties_get_name,
     (setter)tensor_properties_set_name, nullptr, nullptr},
    {"stop_gradient", (getter)tensor_properties_get_stop_gradient,
     (setter)tensor_properties_set_stop_gradient, nullptr, nullptr},
    {"persistable", (getter)tensor_properties_get_persistable,
     (setter)tensor_properties_set_persistable, nullptr, nullptr},
    {"shape", (getter)tensor_properties_get_shape, nullptr, nullptr, nullptr},
    // {"is_leaf", (getter)tensor_properties_get_is_leaf, nullptr,
202 203
    // nullptr,
    //  nullptr},
204 205
    {"place", (getter)tensor_properties_get_place, nullptr, nullptr, nullptr},
    {"_place_str", (getter)tensor_properties_get_place_str, nullptr, nullptr,
206
     nullptr},
207 208
    {"dtype", (getter)tensor_properties_get_dtype, nullptr, nullptr, nullptr},
    {"type", (getter)tensor_properties_get_type, nullptr, nullptr, nullptr},
W
wanghuancoder 已提交
209
    {"is_leaf", (getter)tensor_properties_is_leaf, nullptr, nullptr, nullptr},
210 211
    {nullptr, nullptr, nullptr, nullptr, nullptr}};

J
Jack Zhou 已提交
212 213 214 215 216 217 218 219 220 221
// variable_properties for core.eager.StringTensor
struct PyGetSetDef string_tensor_variable_properties[] = {
    {"name", (getter)tensor_properties_get_name,
     (setter)tensor_properties_set_name, nullptr, nullptr},
    {"shape", (getter)tensor_properties_get_shape, nullptr, nullptr, nullptr},
    {"place", (getter)tensor_properties_get_place, nullptr, nullptr, nullptr},
    {"_place_str", (getter)tensor_properties_get_place_str, nullptr, nullptr,
     nullptr},
    {nullptr, nullptr, nullptr, nullptr, nullptr}};

222 223
}  // namespace pybind
}  // namespace paddle