| 99 | } |
| 100 | |
| 101 | SmallVector<TensorPtr> apply_on_physical_tensor( |
| 102 | const OpDef& def, const SmallVector<TensorPtr>& inputs, |
| 103 | SmallVector<LogicalTensorDesc>& output_descs, const bool& validated) { |
| 104 | auto comp_node = inputs[0]->comp_node(); |
| 105 | auto dtype = inputs[0]->dtype(); |
| 106 | using Mode = Elemwise::Mode; |
| 107 | auto&& op_def = def.cast_final_safe<Elemwise>(); |
| 108 | auto mode = op_def.mode; |
| 109 | TensorShapeArray input_shapes; |
| 110 | input_shapes.reserve(inputs.size()); |
| 111 | for (auto&& input : inputs) { |
| 112 | input_shapes.push_back(input->shape()); |
| 113 | } |
| 114 | // deduce_shape is static and fast |
| 115 | TensorLayout output_layout{dtype}; |
| 116 | // TODO: deduce_layout directly |
| 117 | megdnn::Elemwise::deduce_shape(input_shapes, output_layout); |
| 118 | output_layout.init_contiguous_stride(); |
| 119 | auto output = Tensor::make(output_layout, comp_node); |
| 120 | if (output_layout.is_empty()) { |
| 121 | return {output}; |
| 122 | } |
| 123 | DnnOprCaller<megdnn::Elemwise> dnn_opr(comp_node, op_def.param()); |
| 124 | if (mode == Mode::FUSE_MUL_ADD3 || mode == Mode::FUSE_MUL_ADD4 || |
| 125 | dtype.category() == DTypeCategory::QUANTIZED) { |
| 126 | dnn_opr.call_dnn( |
| 127 | [&](auto&& inputs, auto&& output) { |
| 128 | opr::Elemwise::perform_dnn(comp_node, output, inputs, dnn_opr.op()); |
| 129 | }, |
| 130 | inputs, output); |
| 131 | } else { |
| 132 | dnn_opr.exec(inputs, output); |
| 133 | } |
| 134 | return {output}; |
| 135 | } |
| 136 | |
| 137 | MGB_DEFINE_OPR_CLASS( |
| 138 | ForceInplaceElemwise, |
nothing calls this directly
no test coverage detected