10cf9ed3a719c0782695154d5a0bca260001cec15A. Unique TensorFlower/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 21c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 31c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerLicensed under the Apache License, Version 2.0 (the "License"); 41c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFloweryou may not use this file except in compliance with the License. 51c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerYou may obtain a copy of the License at 61c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 71c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower http://www.apache.org/licenses/LICENSE-2.0 81c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 91c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerUnless required by applicable law or agreed to in writing, software 101c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerdistributed under the License is distributed on an "AS IS" BASIS, 111c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerSee the License for the specific language governing permissions and 131c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerlimitations under the License. 141c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower==============================================================================*/ 151c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 161c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower#include "tensorflow/python/lib/core/py_func.h" 171c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 18edaf3b342db4afa1c872da541fb0ac176a4e8ef9A. Unique TensorFlower#include <array> 19edaf3b342db4afa1c872da541fb0ac176a4e8ef9A. Unique TensorFlower 201c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower#include "numpy/arrayobject.h" 21f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal#include "tensorflow/c/eager/c_api.h" 2287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal#include "tensorflow/c/eager/c_api_internal.h" 23f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal#include "tensorflow/c/tf_status_helper.h" 24e85d3df92deb9d717befdf173966a2913ac2aea0Geoffrey Irving#include "tensorflow/core/framework/allocation_description.pb.h" 251c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower#include "tensorflow/core/framework/op_kernel.h" 261c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower#include "tensorflow/core/lib/core/errors.h" 271c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower#include "tensorflow/core/lib/core/threadpool.h" 28252bb90ca2dd412ca2fd2908faf1a25d6ef618cfJosh Levenberg#include "tensorflow/core/platform/macros.h" 29ded61708dbc7f5615119a3623c8fe7f112882e0fJosh Levenberg#include "tensorflow/core/platform/mutex.h" 30b2f0bc2e230dcd690e7cf34e5425f0f499d9557bJosh Levenberg#include "tensorflow/core/platform/types.h" 31f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal#include "tensorflow/python/eager/pywrap_tfe.h" 32a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower#include "tensorflow/python/lib/core/ndarray_tensor_bridge.h" 337921d01ec8fed3e5c62264b99b09440ea09796feAllen Lavoie#include "tensorflow/python/lib/core/py_util.h" 34f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal#include "tensorflow/python/lib/core/safe_ptr.h" 35d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie 36dc0427d4865f99a227f0c05e2c84987b5ad7f527A. Unique TensorFlower#include <Python.h> 371c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 381c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowernamespace tensorflow { 391c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowernamespace { 401c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 41f93c48dc061d23495a4425fcad17d55159cb02b1A. Unique TensorFlowerstatic mutex mu(LINKER_INITIALIZED); 421c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerstatic PyObject* py_trampoline GUARDED_BY(mu) = nullptr; 431c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 441c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower// Returns the py_trampoline that is used to pass the control to the 451c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower// python runtime. 461c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerPyObject* GetPyTrampoline() { 471c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower mutex_lock l(mu); 481c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower return py_trampoline; 491c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower} 501c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 511c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower// A call to the registered python function. 521c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerstruct PyCall { 531c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower // Passed to python runtime to call the python function registered 541c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower // with this "token". 551c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower string token; 561c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 5787a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // The device on which Tensors are stored; only used for EagerPyFunc. 5887a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal Device* device; 5987a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal 6087a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // True if and only if the op has been placed on a GPU. 6187a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal bool gpu; 6287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal 63f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal // True if the call is associated with an EagerPyFunc. 64f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal bool eager; 65f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal 66b1413783a47bbf94dfbdd6e31d0e4a765a966d41Benoit Steiner // Inputs and outputs of this function invocation. 671c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower std::vector<Tensor> ins; 681c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower std::vector<Tensor> out; 691c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower}; 701c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 711c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower// Givens the 'call', prepares the token and inputs as a python tuple 721c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower// that is appropriate for calling the trampoline. 73f37380b064948fb6dd45feef0e8d93130c2f9884Akshay AgrawalStatus MakeArgTuple(const PyCall* call, PyObject** tuple) { 741c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower int64 n = call->ins.size(); 751c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower PyObject* lst = PyList_New(n); 761c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower CHECK(lst); 771c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower for (int64 i = 0; i < n; ++i) { 78f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal PyObject* arg = nullptr; 791c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower const Tensor& t = call->ins[i]; 80f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal if (call->eager) { 8187a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal if (call->gpu) { 8287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal arg = EagerTensorFromHandle(new TFE_TensorHandle(t, call->device)); 8387a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal } else { 8487a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // TFE_TensorHandle assumes that CPU is identified by `nullptr`. 8587a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal arg = EagerTensorFromHandle(new TFE_TensorHandle(t, nullptr)); 8687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal } 87f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal if (arg == nullptr) { 88f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal return errors::Internal("Unable to procure EagerTensor from Tensor."); 89f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } 90f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } else { 91f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal Status s = ConvertTensorToNdarray(t, &arg); 92f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal if (!s.ok()) { 93f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal Py_DECREF(lst); 94f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal return s; 95f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } 961c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 97f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal PyList_SetItem(lst, i, arg); 981c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 9987a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal *tuple = Py_BuildValue("(sON)", call->token.c_str(), 10087a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal call->gpu ? Py_True : Py_False, lst); 1011c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower CHECK(*tuple); 1021c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower return Status::OK(); 1031c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower} 1041c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 105a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower// Returns the corresponding tf dtype in 'tf' for numpy data type 106a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower// 'np'. Returns an error if the type is not supported by this 107a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower// module. 108a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlowerStatus NumericNpDTypeToTfDType(const int np, DataType* tf) { 109a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower switch (np) { 110a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_FLOAT16: 111a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_HALF; 112a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 113a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_FLOAT32: 114a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_FLOAT; 115a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 116a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_FLOAT64: 117a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_DOUBLE; 118a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 119a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_INT32: 120a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_INT32; 121a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 122a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_UINT8: 123a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_UINT8; 124a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 125a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_INT8: 126a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_INT8; 127a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 128a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_INT16: 129a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_INT16; 130a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 131a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_INT64: 132a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_INT64; 133a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 134a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_BOOL: 135a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_BOOL; 136a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 137a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_COMPLEX64: 138a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_COMPLEX64; 139a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 140a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_COMPLEX128: 141a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *tf = DT_COMPLEX128; 142a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 143a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower default: 144a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return errors::Unimplemented("Unsupported numpy type ", np); 145a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 146a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return Status::OK(); 147a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower} 148a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 149cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlowerbool IsSingleNone(PyObject* obj) { 150cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower if (!PyArray_Check(obj)) { 151cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower return false; 152cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower } 153cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower PyArrayObject* array_obj = reinterpret_cast<PyArrayObject*>(obj); 154cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower if (PyArray_NDIM(array_obj) != 0 || PyArray_SIZE(array_obj) != 1) { 155cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower return false; 156cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower } 157edaf3b342db4afa1c872da541fb0ac176a4e8ef9A. Unique TensorFlower std::array<npy_intp, 0> indices; 158d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie char* item_ptr = 159d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie static_cast<char*>(PyArray_GetPtr(array_obj, indices.data())); 160cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower PyObject* item = PyArray_GETITEM(array_obj, item_ptr); 161cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower CHECK(item); 162cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower return item == Py_None; 163cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower} 164cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower 165f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal// Retrieves a Tensor from `eager_tensor` and stores it in `output_tensor`. 16687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawalvoid ExtractTensorFromEagerTensor(const PyObject* eager_tensor, 16787a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal Tensor* output_tensor) { 16887a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal *output_tensor = EagerTensor_Handle(eager_tensor)->t; 169f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal} 170f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal 1711c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower// Calls the registered py function through the trampoline. 172c154d4719eea88e694f4c06bcb1249dbac0f7877Derek MurrayStatus DoCallPyFunc(PyCall* call, bool* out_log_on_error) { 173c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray *out_log_on_error = true; 1741c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower PyObject* trampoline = GetPyTrampoline(); 1751c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower if (trampoline == nullptr) { 1761c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower return errors::InvalidArgument( 1771c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower "Missing py trampoline. Most likely, it is a link error."); 1781c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 1791c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower // Prepare the argument. 1801c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower PyObject* args = nullptr; 1811c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower TF_RETURN_IF_ERROR(MakeArgTuple(call, &args)); 1821c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower CHECK(args); 1831c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 1841c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower // Invokes the trampoline. 1851c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower PyObject* result = PyEval_CallObject(trampoline, args); 1861c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower Py_DECREF(args); 1871c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower if (result == nullptr) { 188bf20a3a53296c0cc4a2c03e2d0b9a81703b7e8d6A. Unique TensorFlower if (PyErr_Occurred()) { 189d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo if (PyErr_ExceptionMatches(PyExc_ValueError) || 190d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo PyErr_ExceptionMatches(PyExc_TypeError)) { 1917921d01ec8fed3e5c62264b99b09440ea09796feAllen Lavoie return errors::InvalidArgument(PyExceptionFetch()); 192d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo } else if (PyErr_ExceptionMatches(PyExc_StopIteration)) { 193c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray *out_log_on_error = false; 1947921d01ec8fed3e5c62264b99b09440ea09796feAllen Lavoie return errors::OutOfRange(PyExceptionFetch()); 195d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo } else if (PyErr_ExceptionMatches(PyExc_MemoryError)) { 1967921d01ec8fed3e5c62264b99b09440ea09796feAllen Lavoie return errors::ResourceExhausted(PyExceptionFetch()); 197d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo } else if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { 1987921d01ec8fed3e5c62264b99b09440ea09796feAllen Lavoie return errors::Unimplemented(PyExceptionFetch()); 199d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo } else { 200d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo // TODO(ebrevdo): Check if exception is an OpError and use the 201d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo // OpError.error_code property to map it back in the Status. 2027921d01ec8fed3e5c62264b99b09440ea09796feAllen Lavoie return errors::Unknown(PyExceptionFetch()); 203d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo } 204d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo } else { 205d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo return errors::Internal("Failed to run py callback ", call->token, 206d1026cf28991318c4551e691aa03927eaf4ff157Eugene Brevdo ": see error log."); 207bf20a3a53296c0cc4a2c03e2d0b9a81703b7e8d6A. Unique TensorFlower } 2081c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 2091c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 210f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal // Process the return values and convert them to TF Tensors. 21187a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal Status s = Status::OK(); 2121c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower if (PyList_Check(result)) { 21387a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // `result` is a Python list; if this operation is an `EagerPyFunc`, then 21487a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // every item in the list must be an `EagerTensor`; otherwise, every element 21587a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // must be a NumPy array. 2161c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower call->out.clear(); 2171c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower for (int i = 0; i < PyList_Size(result); ++i) { 2181c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower Tensor t; 219f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal if (call->eager) { 22087a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal const PyObject* item = PyList_GetItem(result, i); 22187a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal if (EagerTensor_CheckExact(item)) { 22287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal ExtractTensorFromEagerTensor(item, &t); 22387a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal } else { 22487a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal s = errors::FailedPrecondition( 22587a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal "Expected EagerTensor, found PyObject of type: ", 22687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal Py_TYPE(item)->tp_name); 22787a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal } 228f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } else { 229f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal s = ConvertNdarrayToTensor(PyList_GetItem(result, i), &t); 230f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } 231f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal 2321c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower if (!s.ok()) { 2331c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower break; 2341c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 2351c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower call->out.push_back(t); 2361c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 237f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } else if (EagerTensor_CheckExact(result) || result == Py_None) { 23887a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // result is an `EagerTensor` or `None`. 239f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal DCHECK(call->eager); 240f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal Tensor t; 241f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal if (result != Py_None) { 24287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal ExtractTensorFromEagerTensor(result, &t); 24387a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal call->out.push_back(t); 244f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal } 2451c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } else if (PyArray_Check(result)) { 24687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // `result` is a NumPy array. 247f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal DCHECK(!call->eager); 248cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower if (!IsSingleNone(result)) { 249cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower Tensor t; 250cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower s = ConvertNdarrayToTensor(result, &t); 251cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower if (s.ok()) { 252cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower call->out.push_back(t); 253cabaef0f964c3639f6fe20dd218b1d692b7d632eA. Unique TensorFlower } 2541c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 2551c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } else { 25687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal s = errors::Internal("Unexpected PyObject was returned: ", 2572b3395a7a997f229e19b8b3fb75bd9d1430ca2fbA. Unique TensorFlower Py_TYPE(result)->tp_name); 2581c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 2591c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower Py_DECREF(result); 2601c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower return s; 2611c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower} 2621c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 2631c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower} // end namespace 2641c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 265a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower// Outside anonymous namespace just to make the friend declaration in 266a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower// tensorflow::Tensor apply. 267a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlowerclass NumpyTensorBuffer : public TensorBuffer { 268a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower public: 269a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower NumpyTensorBuffer(PyArrayObject* array, size_t len, void* data) 270a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower : array_(array), len_(len), data_(data) {} 271a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 272a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower ~NumpyTensorBuffer() override { 273a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower // Note: The session::run wrapper is responsible for freeing this while 274a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower // holding the GIL. 275a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower DelayedNumpyDecref(data_, len_, array_); 276a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 277a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 278a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower void* data() const override { return data_; } 279a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower size_t size() const override { return len_; } 280a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower TensorBuffer* root_buffer() override { return this; } 281a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower void FillAllocationDescription(AllocationDescription* proto) const override { 282a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower tensorflow::int64 rb = size(); 283a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower proto->set_requested_bytes(rb); 284a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower proto->set_allocator_name(tensorflow::cpu_allocator()->Name()); 285a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 286a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Tensor MakeTensor(DataType dtype, const TensorShape& shape) { 287a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower CHECK_EQ(len_, shape.num_elements() * DataTypeSize(dtype)); 288a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return Tensor(dtype, shape, this); 289a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 290a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 291a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower // Prevents input forwarding from overwriting this buffer. 292a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower bool OwnsMemory() const override { return false; } 293a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 294a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower private: 295a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyArrayObject* array_; 296a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower size_t len_; 297a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower void* data_; 298a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower}; 2994c85b12dfffe371e6a75e39dd08573c88f960558Alexandre Passos 3007e538db04d9ecf2432f8f0c7bf2d6d5c1f994e1aA. Unique TensorFlowerStatus ConvertNdarrayToTensor(PyObject* obj, Tensor* ret) { 301a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyArrayObject* input = reinterpret_cast<PyArrayObject*>(obj); 302a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower DataType dtype = DT_INVALID; 303a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower TensorShape shape; 304a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower for (int i = 0; i < PyArray_NDIM(input); ++i) { 305a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower shape.AddDim(PyArray_SHAPE(input)[i]); 306a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 307a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower const int np_type = PyArray_TYPE(input); 308a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower switch (np_type) { 309a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_OBJECT: { 310a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower dtype = DT_STRING; 311a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Tensor t(dtype, shape); 312a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower auto tflat = t.flat<string>(); 313a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyObject** input_data = reinterpret_cast<PyObject**>(PyArray_DATA(input)); 314a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower for (int i = 0; i < tflat.dimension(0); ++i) { 315a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower char* el; 316a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Py_ssize_t el_size; 317a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower if (PyBytes_AsStringAndSize(input_data[i], &el, &el_size) == -1) { 31817ba3a69f4c3509711a3da5eff3cb6be99e0936dDerek Murray#if PY_MAJOR_VERSION >= 3 31917ba3a69f4c3509711a3da5eff3cb6be99e0936dDerek Murray el = PyUnicode_AsUTF8AndSize(input_data[i], &el_size); 320d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie#else 321d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie el = nullptr; 322d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie if (PyUnicode_Check(input_data[i])) { 323d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie PyObject* unicode = PyUnicode_AsUTF8String(input_data[i]); 324d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie if (unicode) { 325d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie if (PyString_AsStringAndSize(unicode, &el, &el_size) == -1) { 326d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie Py_DECREF(unicode); 327d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie el = nullptr; 328d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie } 329d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie } 330d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie } 33117ba3a69f4c3509711a3da5eff3cb6be99e0936dDerek Murray#endif 332d9f93c42a50b1f1401d9c186eac0ae8dc9093c3bJianwei Xie if (!el) { 33317ba3a69f4c3509711a3da5eff3cb6be99e0936dDerek Murray return errors::Unimplemented("Unsupported object type ", 33417ba3a69f4c3509711a3da5eff3cb6be99e0936dDerek Murray input_data[i]->ob_type->tp_name); 33517ba3a69f4c3509711a3da5eff3cb6be99e0936dDerek Murray } 336a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 337a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower tflat(i) = string(el, el_size); 338a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 339a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *ret = t; 340a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 341a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 342a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower case NPY_STRING: { 343a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower dtype = DT_STRING; 344a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Tensor t(dtype, shape); 345a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower auto tflat = t.flat<string>(); 346a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower char* input_data = PyArray_BYTES(input); 347a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Py_ssize_t el_size = PyArray_ITEMSIZE(input); 348a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower for (int i = 0; i < tflat.dimension(0); ++i) { 349a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower tflat(i) = string(input_data + i * el_size, el_size); 350a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 351a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *ret = t; 352a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower break; 353a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 354a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower default: { 355a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower TF_RETURN_IF_ERROR(NumericNpDTypeToTfDType(PyArray_TYPE(input), &dtype)); 356a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower CHECK(DataTypeCanUseMemcpy(dtype)); 357a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower if (reinterpret_cast<intptr_t>(PyArray_DATA(input)) % 358a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower EIGEN_MAX_ALIGN_BYTES != 359a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 0) { 360a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Tensor t(dtype, shape); 361a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower StringPiece p = t.tensor_data(); 362a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower memcpy(const_cast<char*>(p.data()), PyArray_DATA(input), p.size()); 363a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *ret = t; 364a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } else { 365a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower // Incref the array as the calling context will decref it when we 366a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower // return and we want to keep a handle to this memory. 367a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Py_INCREF(input); 368a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower NumpyTensorBuffer* buf = new NumpyTensorBuffer( 369a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower input, shape.num_elements() * DataTypeSize(dtype), 370a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyArray_DATA(input)); 371a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *ret = buf->MakeTensor(dtype, shape); 372a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower buf->Unref(); 373a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 374a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 3757e538db04d9ecf2432f8f0c7bf2d6d5c1f994e1aA. Unique TensorFlower } 376a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return Status::OK(); 3777e538db04d9ecf2432f8f0c7bf2d6d5c1f994e1aA. Unique TensorFlower} 3787e538db04d9ecf2432f8f0c7bf2d6d5c1f994e1aA. Unique TensorFlower 379a5a8558feb9417359e30a991ab5e01cf17194473Alexandre Passos// Creates a numpy array in 'ret' which either aliases the content of 't' or has 380a5a8558feb9417359e30a991ab5e01cf17194473Alexandre Passos// a copy. 3818baea485d6c3fafff8fd2d14cb0367318efcbd14Sherry MooreStatus ConvertTensorToNdarray(const Tensor& t, PyObject** ret) { 382a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower int typenum = -1; 383a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower TF_RETURN_IF_ERROR(TF_DataType_to_PyArray_TYPE( 384a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower static_cast<TF_DataType>(t.dtype()), &typenum)); 385a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyArray_Descr* descr = PyArray_DescrFromType(typenum); 386a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower CHECK(descr); 387a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower std::vector<npy_intp> dims; 388a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower dims.reserve(t.dims()); 389a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower for (int i = 0; i < t.dims(); ++i) { 390a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower dims.push_back(t.dim_size(i)); 391a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 392a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Tensor* copy = new Tensor(t); 393a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower if (ArrayFromMemory(dims.size(), dims.data(), 394a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower const_cast<char*>(copy->tensor_data().data()), t.dtype(), 395a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower [copy]() { delete copy; }, ret) 396a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower .ok()) { 397a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return Status::OK(); 398a5a8558feb9417359e30a991ab5e01cf17194473Alexandre Passos } 399a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower delete copy; 400a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower 401a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyObject* obj = PyArray_Empty(dims.size(), dims.data(), descr, 0); 402a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower if (obj == nullptr) { 403a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return errors::Internal("Failed to allocate np array: ", 404a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower t.shape().DebugString()); 405a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 406a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyArrayObject* np_array = reinterpret_cast<PyArrayObject*>(obj); 407a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower if (typenum == NPY_OBJECT) { 408a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower CHECK_EQ(DT_STRING, t.dtype()); 409a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower auto tflat = t.flat<string>(); 410a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower PyObject** out = reinterpret_cast<PyObject**>(PyArray_DATA(np_array)); 411a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower for (int i = 0; i < tflat.dimension(0); ++i) { 412a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower const string& el = tflat(i); 413a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower out[i] = PyBytes_FromStringAndSize(el.data(), el.size()); 414a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower if (out[i] == nullptr) { 415a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower for (int j = 0; j < i; ++j) { 416a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Py_DECREF(out[j]); 417a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 418a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower Py_DECREF(obj); 419a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return errors::Internal("Failed to allocate a copy of string ", i); 420a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 421a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 422a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } else { 423a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower CHECK(DataTypeCanUseMemcpy(t.dtype())); 424a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower StringPiece p = t.tensor_data(); 425a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower memcpy(PyArray_DATA(np_array), p.data(), p.size()); 426a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower } 427a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower *ret = PyArray_Return(np_array); 428a2182c4a3d0f6dc29042cd6116964a3f5241b5b0A. Unique TensorFlower return Status::OK(); 4298baea485d6c3fafff8fd2d14cb0367318efcbd14Sherry Moore} 4308baea485d6c3fafff8fd2d14cb0367318efcbd14Sherry Moore 4311c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowervoid InitializePyTrampoline(PyObject* trampoline) { 4321c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower mutex_lock l(mu); 4331c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower if (py_trampoline == nullptr) { 4341c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower py_trampoline = trampoline; 4351c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower Py_INCREF(py_trampoline); 4361c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } else { 4371c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower LOG(WARNING) << "InitializeCallback should only be called once"; 4381c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 4391c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower} 4401c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 441f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlowerclass PyFuncOp : public OpKernel { 4421c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower public: 443f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower explicit PyFuncOp(OpKernelConstruction* ctx) : OpKernel(ctx) { 4441c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower OP_REQUIRES_OK(ctx, ctx->GetAttr("token", &token_)); 445f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal eager_ = type_string() == "EagerPyFunc"; 44687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal gpu_ = ctx->device_type().type_string() == DEVICE_GPU; 4471c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 4481c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 449f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower void Compute(OpKernelContext* ctx) override { 450f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower PyCall call; 451f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower call.token = token_; 45287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal call.gpu = gpu_; 453f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal call.eager = eager_; 45487a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal if (call.eager) { 45587a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // Eager's C API uses `Device`, whereas `OpKernelContext` stores a 45687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // `DeviceBase`; attempt to downcast. 45787a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal call.device = dynamic_cast<Device*>(ctx->device()); 45887a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal if (call.device == nullptr) { 45987a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal ctx->CtxFailureWithWarning( 46087a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal errors::Internal("Unrecognized device class")); 46187a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal } 46287a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal } 46387a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal 4641c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower for (int i = 0; i < ctx->num_inputs(); ++i) { 465f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower call.ins.push_back(ctx->input(i)); 466f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower } 467f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower 468f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower PyGILState_STATE py_threadstate; 469f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower py_threadstate = PyGILState_Ensure(); 470c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray bool log_on_error; 471c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray Status s = DoCallPyFunc(&call, &log_on_error); 472e4532d20973c4c00854492362665317551661c18A. Unique TensorFlower // Sometimes py_funcs can be called without a session and leak memory. This 473e4532d20973c4c00854492362665317551661c18A. Unique TensorFlower // ensures we clear the decref cache so this doesn't happen. 474e4532d20973c4c00854492362665317551661c18A. Unique TensorFlower ClearDecrefCache(); 475f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower PyGILState_Release(py_threadstate); 476f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower 477f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower // Ensures that GIL is released even when !s.ok(). 478c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray if (!s.ok()) { 479c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray if (log_on_error) { 480c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray ctx->CtxFailureWithWarning(s); 481c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray } else { 482c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray ctx->CtxFailure(s); 483c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray } 484c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray return; 485c154d4719eea88e694f4c06bcb1249dbac0f7877Derek Murray } 486f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower 487f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower OP_REQUIRES(ctx, static_cast<int32>(call.out.size()) == ctx->num_outputs(), 488f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower errors::InvalidArgument(token_, " returns ", call.out.size(), 489f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower " values, but expects to see ", 490f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower ctx->num_outputs(), " values.")); 491f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower for (size_t i = 0; i < call.out.size(); ++i) { 492f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower const auto& t = call.out[i]; 493f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower OP_REQUIRES( 494f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower ctx, t.dtype() == output_type(i), 495f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower errors::InvalidArgument(i, "-th value returned by ", token_, " is ", 496f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower DataTypeString(t.dtype()), ", but expects ", 497f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower DataTypeString(output_type(i)))); 498f139c2b3f1298fe63afb31f7956f0e27cf7935f6A. Unique TensorFlower ctx->set_output(i, t); 4991c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 5001c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower } 5011c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 5021c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower private: 5031c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower string token_; 5041c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 50587a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal // True if and only if this op has been placed on a GPU. 50687a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal bool gpu_; 50787a3c967973641d3b0d2a16d17add184ed967392Akshay Agrawal 508f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal // True if and only if this op should execute the python function eagerly, 509f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal // i.e., if and only if the eager attribute is set. 510f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal bool eager_; 511f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal 5121c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower TF_DISALLOW_COPY_AND_ASSIGN(PyFuncOp); 5131c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower}; 514f37380b064948fb6dd45feef0e8d93130c2f9884Akshay Agrawal 5151c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlowerREGISTER_KERNEL_BUILDER(Name("PyFunc").Device(DEVICE_CPU), PyFuncOp); 5162c5b766688d7217886d76b05989475d86869ca21A. Unique TensorFlowerREGISTER_KERNEL_BUILDER(Name("PyFuncStateless").Device(DEVICE_CPU), PyFuncOp); 517f37380b064948fb6dd45feef0e8d93130c2f9884Akshay AgrawalREGISTER_KERNEL_BUILDER(Name("EagerPyFunc").Device(DEVICE_CPU), PyFuncOp); 51887a3c967973641d3b0d2a16d17add184ed967392Akshay AgrawalREGISTER_KERNEL_BUILDER(Name("EagerPyFunc").Device(DEVICE_GPU), PyFuncOp); 5191c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower 5201c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower} // end namespace tensorflow 521