eager_utils.h 13.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/* 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. */
#pragma once

13 14 15 16 17
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif

18
#include <Python.h>
19 20 21 22
// Avoid a problem with copysign defined in pyconfig.h on Windows.
#ifdef copysign
#undef copysign
#endif
23

24
#include "paddle/fluid/eager/grad_node_info.h"
25
#include "paddle/fluid/eager/hooks.h"
26
#include "paddle/fluid/framework/lod_tensor.h"
27
#include "paddle/fluid/framework/lod_tensor_array.h"
28
#include "paddle/fluid/framework/string_array.h"
29
#include "paddle/fluid/framework/tensor.h"
30
#include "paddle/fluid/jit/function.h"
31
#include "paddle/fluid/platform/place.h"
32 33
#include "paddle/phi/common/backend.h"
#include "paddle/phi/common/data_type.h"
34
#include "paddle/phi/common/int_array.h"
35
#include "paddle/phi/common/scalar.h"
36
#include "paddle/phi/core/dense_tensor.h"
37
#include "paddle/phi/core/selected_rows.h"
38
#include "paddle/utils/pybind.h"
39 40
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
L
LiYuRio 已提交
41 42 43 44 45
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_attr.h"
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif

46
namespace paddle {
47
class CustomOpKernelContext;
0
0x45f 已提交
48 49 50
namespace framework {
class Scope;
}
51 52
namespace pybind {

53
namespace py = ::pybind11;
54

55
int TensorDtype2NumpyDtype(phi::DataType dtype);
56

57 58 59 60 61 62
bool PyObject_CheckLongOrConvertToLong(PyObject** obj);
bool PyObject_CheckFloatOrConvertToFloat(PyObject** obj);
bool PyObject_CheckStr(PyObject* obj);
bool CastPyArg2AttrBoolean(PyObject* obj, ssize_t arg_pos);
int CastPyArg2AttrInt(PyObject* obj, ssize_t arg_pos);
int64_t CastPyArg2AttrLong(PyObject* obj, ssize_t arg_pos);
W
wanghuancoder 已提交
63
size_t CastPyArg2AttrSize_t(PyObject* obj, ssize_t arg_pos);
64 65
float CastPyArg2AttrFloat(PyObject* obj, ssize_t arg_pos);
std::string CastPyArg2AttrString(PyObject* obj, ssize_t arg_pos);
J
Jiabin Yang 已提交
66 67
std::shared_ptr<imperative::VarBase> CastPyArg2VarBase(PyObject* obj,
                                                       ssize_t arg_pos);
68 69
std::vector<paddle::Tensor> CastPyArg2VectorOfTensor(PyObject* obj,
                                                     ssize_t arg_pos);
70
platform::Place CastPyArg2Place(PyObject* obj, ssize_t arg_pos);
71
phi::DenseTensor CastPyArg2FrameworkTensor(PyObject* obj, ssize_t arg_pos);
72 73
std::vector<phi::DenseTensor> CastPyArg2VectorOfTensorBase(PyObject* obj,
                                                           ssize_t arg_pos);
74
std::vector<int> CastPyArg2VectorOfInt(PyObject* obj, size_t arg_pos);
75
std::vector<int64_t> CastPyArg2VectorOfInt64(PyObject* obj, size_t arg_pos);
W
wanghuancoder 已提交
76
std::vector<size_t> CastPyArg2VectorOfSize_t(PyObject* obj, size_t arg_pos);
77
std::vector<float> CastPyArg2VectorOfFloat(PyObject* obj, size_t arg_pos);
W
wanghuancoder 已提交
78 79
std::vector<std::vector<size_t>> CastPyArg2VectorOfVectorOfSize_t(
    PyObject* obj, size_t arg_pos);
J
Jiabin Yang 已提交
80 81
framework::proto::VarType::Type CastPyArg2ProtoType(PyObject* obj,
                                                    ssize_t arg_pos);
82
paddle::framework::Vocab CastPyArg2Vocab(PyObject* obj, ssize_t arg_pos);
83 84
std::vector<std::string> CastPyArg2VectorOfString(PyObject* obj,
                                                  ssize_t arg_pos);
85 86
std::shared_ptr<jit::Function> CastPyArg2JitFunction(PyObject* obj,
                                                     ssize_t arg_pos);
87
void SetPythonStack();
88

89
PyObject* ToPyObject(int value);
90
PyObject* ToPyObject(uint32_t value);
91 92
PyObject* ToPyObject(bool value);
PyObject* ToPyObject(int64_t value);
W
wanghuancoder 已提交
93
PyObject* ToPyObject(size_t value);
94 95 96 97
PyObject* ToPyObject(float value);
PyObject* ToPyObject(double value);
PyObject* ToPyObject(const char* value);
PyObject* ToPyObject(const std::string& value);
98
PyObject* ToPyObject(const paddle::Tensor& value,
99
                     PyObject* args,
100 101
                     const std::map<ssize_t, ssize_t>& inplace_var_idx_map);
PyObject* ToPyObject(PyObject* args, ssize_t arg_idx);
102 103 104
PyObject* ToPyObject(const std::vector<bool>& value);
PyObject* ToPyObject(const std::vector<int>& value);
PyObject* ToPyObject(const std::vector<int64_t>& value);
W
wanghuancoder 已提交
105
PyObject* ToPyObject(const std::vector<size_t>& value);
106 107
PyObject* ToPyObject(const std::vector<float>& value);
PyObject* ToPyObject(const std::vector<double>& value);
W
wanghuancoder 已提交
108
PyObject* ToPyObject(const std::vector<std::vector<size_t>>& value);
109 110 111
PyObject* ToPyObject(const std::vector<paddle::Tensor>& value,
                     bool return_py_none_if_not_initialize = false);
PyObject* ToPyObject(const std::vector<std::vector<paddle::Tensor>>& value,
112
                     bool return_py_none_if_not_initialize = false);
113
PyObject* ToPyObject(const platform::Place& value);
114
PyObject* ToPyObject(const phi::DenseTensor* value);
L
LiYuRio 已提交
115
#ifdef PADDLE_WITH_DISTRIBUTE
116
PyObject* ToPyObject(const phi::distributed::DistTensor* value);
L
LiYuRio 已提交
117 118 119
PyObject* ToPyObject(
    const phi::distributed::auto_parallel::TensorDistAttr* value);
#endif
120
PyObject* ToPyObject(const phi::SelectedRows* value);
J
Jiabin Yang 已提交
121
PyObject* ToPyObject(const paddle::framework::proto::VarType::Type& dtype);
122
PyObject* ToPyObject(const paddle::framework::proto::VarType& type);
W
wanghuancoder 已提交
123
PyObject* ToPyObject(const void* value);
124
PyObject* ToPyObject(const std::unordered_map<int, int>& value);
125 126
PyObject* ToPyObject(
    const std::unordered_map<std::string, std::vector<std::string>>& value);
127
PyObject* ToPyObject(const paddle::framework::Vocab& value);
128

129 130
PyObject* ToPyObject(egr::GradNodeBase* grad_node);

131 132 133 134 135 136 137 138 139 140 141
class PyTensorHook : public egr::TensorHook {
 public:
  explicit PyTensorHook(PyObject* func) : py_func_(func) {
    Py_INCREF(py_func_);
  }

  ~PyTensorHook() {
    py::gil_scoped_acquire gil;
    Py_DECREF(py_func_);
  }

142
  paddle::Tensor operator()(const paddle::Tensor& var) override;
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

 private:
  PyObject* py_func_;
};

class PyVoidHook : public egr::VoidHook {
 public:
  explicit PyVoidHook(PyObject* func) : py_func_(func) { Py_INCREF(py_func_); }

  ~PyVoidHook() {
    py::gil_scoped_acquire gil;
    Py_DECREF(py_func_);
  }

  void operator()() override;

 private:
  PyObject* py_func_;
};

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
class PyObjectHolder : public egr::PyObjectHolderBase {
 public:
  PyObjectHolder() { ptr_ = nullptr; }
  explicit PyObjectHolder(PyObject* ptr);
  ~PyObjectHolder() override;
  void* get() override;
  void reset(void* ptr) override;
  void inc_ref() override;
  void dec_ref() override;

 private:
  PyObject* ptr_{nullptr};
};

class PackHook : public egr::PackHookBase {
 public:
  explicit PackHook(PyObject* hook);

  ~PackHook();

  std::shared_ptr<egr::PyObjectHolderBase> operator()(
184
      const paddle::Tensor& tensor) override;
185 186 187 188 189 190 191 192 193 194 195 196 197

  void* operator()(void* py_tensor) override;

 private:
  PyObject* hook_;
};

class UnPackHook : public egr::UnPackHookBase {
 public:
  explicit UnPackHook(PyObject* hook);

  ~UnPackHook();

198
  paddle::Tensor operator()(
199 200 201 202 203 204 205
      std::shared_ptr<egr::PyObjectHolderBase> packed_value) override;

  void* operator()(void* packed_value, void* other) override;

 private:
  PyObject* hook_;
};
206
template <typename Tuple, size_t N>
207
struct TupleTensorResult {
208
  static void Run(const Tuple& out, PyObject* result) {
209
    TupleTensorResult<Tuple, N - 1>::Run(out, result);
210 211
    PyTuple_SET_ITEM(result, N - 1, ToPyObject(std::get<N - 1>(out)));
  }
212

213 214 215
  static void Run(const Tuple& out,
                  PyObject* result,
                  PyObject* args,
216 217 218 219
                  const std::map<ssize_t, ssize_t>& inplace_var_idx_map) {
    TupleTensorResult<Tuple, N - 1>::Run(
        out, result, args, inplace_var_idx_map);
    if (!inplace_var_idx_map.empty() && inplace_var_idx_map.count(N - 1)) {
220
      PyTuple_SET_ITEM(
221
          result, N - 1, ToPyObject(args, inplace_var_idx_map.at(N - 1)));
222 223 224 225
    } else {
      PyTuple_SET_ITEM(result, N - 1, ToPyObject(std::get<N - 1>(out)));
    }
  }
226 227 228
};

template <typename Tuple>
229
struct TupleTensorResult<Tuple, 1> {
230 231 232
  static void Run(const Tuple& out, PyObject* result) {
    PyTuple_SET_ITEM(result, 0, ToPyObject(std::get<0>(out)));
  }
233

234 235 236
  static void Run(const Tuple& out,
                  PyObject* result,
                  PyObject* args,
237 238 239
                  const std::map<ssize_t, ssize_t>& inplace_var_idx_map) {
    if (!inplace_var_idx_map.empty() && inplace_var_idx_map.count(0)) {
      PyTuple_SET_ITEM(result, 0, ToPyObject(args, inplace_var_idx_map.at(0)));
240 241 242 243
    } else {
      PyTuple_SET_ITEM(result, 0, ToPyObject(std::get<0>(out)));
    }
  }
244 245 246 247 248 249 250
};

template <typename... Args>
PyObject* ToPyObject(const std::tuple<Args...>& out) {
  auto len = sizeof...(Args);
  PyObject* result = PyTuple_New(len);

251
  TupleTensorResult<decltype(out), sizeof...(Args)>::Run(out, result);
252 253 254 255

  return result;
}

256
template <typename... Args>
257 258
PyObject* ToPyObject(const std::tuple<Args...>& out,
                     PyObject* args,
259
                     const std::map<ssize_t, ssize_t>& inplace_var_idx_map) {
260 261 262 263
  // For inplace op, directly return the input PyObject of the inplace tensor.
  // [Parameter]
  // out: Outputs tuple after executing op.
  // args: Input PyObject.
264 265 266 267 268
  // inplace_var_idx_map: Index of Tensors in inplace_map, e.g. {{value_idx,
  // arg_idx}}.
  // - value_idx: Index of inplace tensor in outputs tuple. Used to find the
  // output inplace tensor.
  // - arg_idx: Index of inplace PyObject in input args. Used to find the input
269 270 271 272
  // inplace PyObject.
  auto len = sizeof...(Args);
  PyObject* result = PyTuple_New(len);

273
  TupleTensorResult<decltype(out), sizeof...(Args)>::Run(
274
      out, result, args, inplace_var_idx_map);
275 276 277 278

  return result;
}

279 280 281 282
paddle::experimental::Scalar CastPyArg2Scalar(PyObject* obj,
                                              const std::string& op_type,
                                              ssize_t arg_pos);

283 284 285 286
paddle::experimental::Scalar CastNumpy2Scalar(PyObject* obj,
                                              const std::string& op_type,
                                              ssize_t arg_pos);

287 288 289 290
std::vector<phi::Scalar> CastPyArg2ScalarArray(PyObject* obj,
                                               const std::string& op_type,
                                               ssize_t arg_pos);

291 292 293
paddle::experimental::IntArray CastPyArg2IntArray(PyObject* obj,
                                                  const std::string& op_type,
                                                  ssize_t arg_pos);
294

295 296
paddle::Place CastPyArg2Place(PyObject* obj,
                              const std::string& op_type,
297
                              ssize_t arg_pos);
298

299 300
paddle::DataType CastPyArg2DataType(PyObject* obj,
                                    const std::string& op_type,
301
                                    ssize_t arg_pos);
302

L
LiYuRio 已提交
303 304 305 306 307
#ifdef PADDLE_WITH_DISTRIBUTE
std::shared_ptr<phi::distributed::auto_parallel::TensorDistAttr>
CastPyArg2DistAttr(PyObject* obj, ssize_t arg_pos);
#endif

308
paddle::optional<paddle::Tensor> GetOptionalTensorFromArgs(
309 310 311 312 313
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable = false);
314

315 316 317 318 319
paddle::Tensor& GetTensorFromArgs(const std::string& op_type,
                                  const std::string& arg_name,
                                  PyObject* args,
                                  ssize_t arg_idx,
                                  bool dispensable = false);
320

321
paddle::optional<std::vector<paddle::Tensor>> GetOptionalTensorListFromArgs(
322 323 324 325 326
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable = false);
327

328 329 330 331 332 333 334 335 336 337 338
std::vector<paddle::Tensor> GetTensorListFromArgs(const std::string& op_type,
                                                  const std::string& arg_name,
                                                  PyObject* args,
                                                  ssize_t arg_idx,
                                                  bool dispensable = false);

paddle::Tensor* GetTensorPtrFromArgs(const std::string& op_type,
                                     const std::string& arg_name,
                                     PyObject* args,
                                     ssize_t arg_idx,
                                     bool dispensable = false);
339

340
std::vector<paddle::Tensor*> GetTensorPtrListFromArgs(
341 342 343 344 345
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable = false);
346

347
std::vector<paddle::Tensor*> GetTensorPtrListFromPyObject(PyObject* obj);
W
wanghuancoder 已提交
348

349 350 351
std::vector<paddle::Tensor> GetTensorListFromPyObject(PyObject* obj,
                                                      bool allow_none = false);
paddle::Tensor& UnSafeGetTensorFromPyObject(PyObject* obj);
W
wanghuancoder 已提交
352

J
Jiabin Yang 已提交
353
// end of Slice related methods
354

0
0x45f 已提交
355
std::vector<paddle::framework::Scope*> GetScopePtrListFromArgs(
356 357 358 359 360
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable);
J
Jiabin Yang 已提交
361

362 363 364 365 366 367 368 369 370 371 372 373
class eager_gil_scoped_release {
 public:
  eager_gil_scoped_release() { tstate = PyEval_SaveThread(); }
  ~eager_gil_scoped_release() {
    if (!tstate) return;
    PyEval_RestoreThread(tstate);
  }

 private:
  PyThreadState* tstate{nullptr};
};

374 375
}  // namespace pybind
}  // namespace paddle