| 80 | CompNode _get_device(PyObject* const* args, size_t nargs); |
| 81 | |
| 82 | PyObject* py_apply( |
| 83 | PyObject* self, PyObject* const* args, size_t nargs /* , PyObject* kwnames */) { |
| 84 | try { |
| 85 | // if (kwnames && PyTuple_GET_SIZE(kwnames)) { |
| 86 | // PyErr_SetString(PyExc_TypeError, "keyword argument not allowed"); |
| 87 | // return nullptr; |
| 88 | // } |
| 89 | if (nargs < 2) { |
| 90 | PyErr_SetString( |
| 91 | PyExc_TypeError, |
| 92 | "py_apply expects one Op and at least one tensor " |
| 93 | "as argument"); |
| 94 | return nullptr; |
| 95 | } |
| 96 | |
| 97 | auto* py_op = args[0]; |
| 98 | |
| 99 | ++args; |
| 100 | --nargs; |
| 101 | |
| 102 | auto op = py::handle(py_op).cast<std::shared_ptr<OpDef>>(); |
| 103 | SmallVector<ValueRef, 8> tensors(nargs); |
| 104 | |
| 105 | mgb::CompNode target_cn; |
| 106 | mgb::DType target_dtype; |
| 107 | |
| 108 | auto convert_pyinput_to_tensor = [&](size_t i) -> ValueRef { |
| 109 | if (!target_dtype.valid()) { |
| 110 | target_dtype = npy::dtype_np2mgb_descr(_dtype_promotion(args, nargs)); |
| 111 | target_cn = _get_device(args, nargs); |
| 112 | } |
| 113 | HostTensorND ht(target_cn); |
| 114 | ht = npy::np2tensor(args[i], npy::Meth::copy_into(&ht), target_dtype); |
| 115 | record_py_backtrace(); |
| 116 | //! operand in elemwise can't be None |
| 117 | if (args[i] == Py_None) { |
| 118 | throw py::type_error("the operand is None and is not supported."); |
| 119 | } else if (PyArray_Check(args[i]) || PyList_Check(args[i])) { // non scaler |
| 120 | // py_tuple is not allowed here because of tracing |
| 121 | return imperative::apply( |
| 122 | CreateTensor(CreateTensor::Const, target_cn, ht.layout()), |
| 123 | HostStorage::make(ht.storage()))[0]; |
| 124 | } else { // scaler |
| 125 | return imperative::apply( |
| 126 | CreateTensor(CreateTensor::Const, target_cn, target_dtype, {}), |
| 127 | HostStorage::make(ht.storage()))[0]; |
| 128 | } |
| 129 | }; |
| 130 | |
| 131 | bool is_varnode_apply = false; |
| 132 | for (size_t i = 0; i < nargs; ++i) { |
| 133 | if (PyObject_TypeCheck(args[i], py_varnode_type)) { |
| 134 | is_varnode_apply = true; |
| 135 | } |
| 136 | if (TensorWrapper* tw = TensorWrapper::try_cast(args[i])) { |
| 137 | tensors[i] = tw->m_tensor->data(); |
| 138 | } else if ( |
| 139 | DTypePromoteCfg::convert_input_enabled && |
no test coverage detected