eager_utils.h 10.6 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
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/framework/tensor.h"
22
#include "paddle/fluid/jit/base_function.h"
23
#include "paddle/fluid/platform/place.h"
24 25
#include "paddle/phi/common/backend.h"
#include "paddle/phi/common/data_type.h"
26
#include "paddle/phi/common/int_array.h"
27
#include "paddle/phi/common/scalar.h"
28
#include "paddle/phi/core/dense_tensor.h"
29
#include "paddle/phi/core/selected_rows.h"
30 31 32
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
namespace paddle {
33
class CustomOpKernelContext;
0
0x45f 已提交
34 35 36
namespace framework {
class Scope;
}
37 38
namespace pybind {

39 40 41 42
#define RETURN_PY_NONE \
  Py_INCREF(Py_None);  \
  return Py_None;

43
int TensorDtype2NumpyDtype(phi::DataType dtype);
44

W
wanghuancoder 已提交
45 46
bool IsEagerTensor(PyObject* obj);

47 48 49 50 51 52
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 已提交
53
size_t CastPyArg2AttrSize_t(PyObject* obj, ssize_t arg_pos);
54 55
float CastPyArg2AttrFloat(PyObject* obj, ssize_t arg_pos);
std::string CastPyArg2AttrString(PyObject* obj, ssize_t arg_pos);
56 57
paddle::CustomOpKernelContext CastPyArg2CustomOpKernelContext(PyObject* obj,
                                                              ssize_t arg_pos);
58
paddle::experimental::Tensor CastPyArg2Tensor(PyObject* obj, ssize_t arg_pos);
J
Jiabin Yang 已提交
59 60
std::shared_ptr<imperative::VarBase> CastPyArg2VarBase(PyObject* obj,
                                                       ssize_t arg_pos);
61 62
std::vector<paddle::experimental::Tensor> CastPyArg2VectorOfTensor(
    PyObject* obj, ssize_t arg_pos);
63
platform::Place CastPyArg2Place(PyObject* obj, ssize_t arg_pos);
64
framework::Tensor CastPyArg2FrameworkTensor(PyObject* obj, ssize_t arg_pos);
65 66
std::vector<framework::LoDTensor> CastPyArg2VectorOfTensorBase(PyObject* obj,
                                                               ssize_t arg_pos);
67
std::vector<int> CastPyArg2VectorOfInt(PyObject* obj, size_t arg_pos);
W
wanghuancoder 已提交
68 69 70
std::vector<size_t> CastPyArg2VectorOfSize_t(PyObject* obj, size_t arg_pos);
std::vector<std::vector<size_t>> CastPyArg2VectorOfVectorOfSize_t(
    PyObject* obj, size_t arg_pos);
J
Jiabin Yang 已提交
71 72
framework::proto::VarType::Type CastPyArg2ProtoType(PyObject* obj,
                                                    ssize_t arg_pos);
73 74 75
std::unordered_map<std::wstring, int> CastPyArg2Vocab(PyObject* obj,
                                                      ssize_t arg_pos);
std::vector<std::string> CastPyArg2Strings(PyObject* obj, ssize_t arg_pos);
76 77
std::shared_ptr<jit::BaseFunction> CastPyArg2BaseFunction(PyObject* obj,
                                                          ssize_t arg_pos);
78

79
PyObject* ToPyObject(int value);
80
PyObject* ToPyObject(uint32_t value);
81 82
PyObject* ToPyObject(bool value);
PyObject* ToPyObject(int64_t value);
W
wanghuancoder 已提交
83
PyObject* ToPyObject(size_t value);
84 85 86 87
PyObject* ToPyObject(float value);
PyObject* ToPyObject(double value);
PyObject* ToPyObject(const char* value);
PyObject* ToPyObject(const std::string& value);
W
wanghuancoder 已提交
88 89
PyObject* ToPyObject(const paddle::experimental::Tensor& value,
                     bool return_py_none_if_not_initialize = false);
90
PyObject* ToPyObject(const paddle::experimental::Tensor& value,
91
                     PyObject* args,
92 93
                     const std::map<ssize_t, ssize_t>& inplace_var_idx_map);
PyObject* ToPyObject(PyObject* args, ssize_t arg_idx);
94 95 96
PyObject* ToPyObject(const std::vector<bool>& value);
PyObject* ToPyObject(const std::vector<int>& value);
PyObject* ToPyObject(const std::vector<int64_t>& value);
W
wanghuancoder 已提交
97
PyObject* ToPyObject(const std::vector<size_t>& value);
98 99
PyObject* ToPyObject(const std::vector<float>& value);
PyObject* ToPyObject(const std::vector<double>& value);
W
wanghuancoder 已提交
100
PyObject* ToPyObject(const std::vector<std::vector<size_t>>& value);
101 102
PyObject* ToPyObject(const std::vector<paddle::experimental::Tensor>& value,
                     bool return_py_none_if_not_initialize = false);
103
PyObject* ToPyObject(const platform::Place& value);
104
PyObject* ToPyObject(const framework::LoDTensor* value);
105
PyObject* ToPyObject(const phi::SelectedRows* value);
J
Jiabin Yang 已提交
106
PyObject* ToPyObject(const paddle::framework::proto::VarType::Type& dtype);
107
PyObject* ToPyObject(const paddle::framework::proto::VarType& type);
W
wanghuancoder 已提交
108
PyObject* ToPyObject(const void* value);
109 110
PyObject* ToPyObject(
    const std::unordered_map<std::string, std::vector<std::string>>& value);
111
PyObject* ToPyObject(const std::unordered_map<std::wstring, int>& value);
112

113
template <typename Tuple, size_t N>
114
struct TupleTensorResult {
115
  static void Run(const Tuple& out, PyObject* result) {
116
    TupleTensorResult<Tuple, N - 1>::Run(out, result);
117 118
    PyTuple_SET_ITEM(result, N - 1, ToPyObject(std::get<N - 1>(out)));
  }
119

120 121 122
  static void Run(const Tuple& out,
                  PyObject* result,
                  PyObject* args,
123 124 125 126
                  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)) {
127
      PyTuple_SET_ITEM(
128
          result, N - 1, ToPyObject(args, inplace_var_idx_map.at(N - 1)));
129 130 131 132
    } else {
      PyTuple_SET_ITEM(result, N - 1, ToPyObject(std::get<N - 1>(out)));
    }
  }
133 134 135
};

template <typename Tuple>
136
struct TupleTensorResult<Tuple, 1> {
137 138 139
  static void Run(const Tuple& out, PyObject* result) {
    PyTuple_SET_ITEM(result, 0, ToPyObject(std::get<0>(out)));
  }
140

141 142 143
  static void Run(const Tuple& out,
                  PyObject* result,
                  PyObject* args,
144 145 146
                  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)));
147 148 149 150
    } else {
      PyTuple_SET_ITEM(result, 0, ToPyObject(std::get<0>(out)));
    }
  }
151 152 153 154 155 156 157
};

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

158
  TupleTensorResult<decltype(out), sizeof...(Args)>::Run(out, result);
159 160 161 162

  return result;
}

163
template <typename... Args>
164 165
PyObject* ToPyObject(const std::tuple<Args...>& out,
                     PyObject* args,
166
                     const std::map<ssize_t, ssize_t>& inplace_var_idx_map) {
167 168 169 170
  // For inplace op, directly return the input PyObject of the inplace tensor.
  // [Parameter]
  // out: Outputs tuple after executing op.
  // args: Input PyObject.
171 172 173 174 175
  // 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
176 177 178 179
  // inplace PyObject.
  auto len = sizeof...(Args);
  PyObject* result = PyTuple_New(len);

180
  TupleTensorResult<decltype(out), sizeof...(Args)>::Run(
181
      out, result, args, inplace_var_idx_map);
182 183 184 185

  return result;
}

186 187 188 189
paddle::experimental::Scalar CastPyArg2Scalar(PyObject* obj,
                                              const std::string& op_type,
                                              ssize_t arg_pos);

190 191 192 193
paddle::experimental::Scalar CastNumpy2Scalar(PyObject* obj,
                                              const std::string& op_type,
                                              ssize_t arg_pos);

194 195 196
paddle::experimental::IntArray CastPyArg2IntArray(PyObject* obj,
                                                  const std::string& op_type,
                                                  ssize_t arg_pos);
197

198 199
paddle::Place CastPyArg2Place(PyObject* obj,
                              const std::string& op_type,
200
                              ssize_t arg_pos);
201

202 203
paddle::DataType CastPyArg2DataType(PyObject* obj,
                                    const std::string& op_type,
204
                                    ssize_t arg_pos);
205

206
paddle::optional<paddle::experimental::Tensor> GetOptionalTensorFromArgs(
207 208 209 210 211
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable = false);
212

213 214
paddle::experimental::Tensor& GetTensorFromArgs(const std::string& op_type,
                                                const std::string& arg_name,
215 216
                                                PyObject* args,
                                                ssize_t arg_idx,
217
                                                bool dispensable = false);
218

219
std::vector<paddle::experimental::Tensor> GetTensorListFromArgs(
220 221 222 223 224
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable = false);
225

226 227 228 229 230
paddle::experimental::Tensor* GetTensorPtrFromArgs(const std::string& op_type,
                                                   const std::string& arg_name,
                                                   PyObject* args,
                                                   ssize_t arg_idx,
                                                   bool dispensable = false);
231

232
std::vector<paddle::experimental::Tensor*> GetTensorPtrListFromArgs(
233 234 235 236 237
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable = false);
238

W
wanghuancoder 已提交
239 240 241 242 243 244 245 246
std::vector<paddle::experimental::Tensor*> GetTensorPtrListFromPyObject(
    PyObject* obj);

std::vector<paddle::experimental::Tensor> GetTensorListFromPyObject(
    PyObject* obj);

paddle::experimental::Tensor& GetTensorFromPyObject(PyObject* obj);

J
Jiabin Yang 已提交
247
// end of Slice related methods
248

0
0x45f 已提交
249
std::vector<paddle::framework::Scope*> GetScopePtrListFromArgs(
250 251 252 253 254
    const std::string& op_type,
    const std::string& arg_name,
    PyObject* args,
    ssize_t arg_idx,
    bool dispensable);
J
Jiabin Yang 已提交
255

256 257 258 259 260 261 262 263 264 265 266 267
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};
};

268 269
}  // namespace pybind
}  // namespace paddle