| 89 | OprChecker::OprChecker(std::shared_ptr<OpDef> opdef) : m_op(opdef) {} |
| 90 | |
| 91 | void OprChecker::run(std::vector<InputSpec> inp_keys, std::set<size_t> bypass) { |
| 92 | HostTensorGenerator<> gen; |
| 93 | size_t nr_inps = inp_keys.size(); |
| 94 | SmallVector<HostTensorND> host_inp(nr_inps); |
| 95 | VarNodeArray sym_inp(nr_inps); |
| 96 | auto graph = ComputingGraph::make(); |
| 97 | graph->options().graph_opt_level = 0; |
| 98 | for (size_t i = 0; i < nr_inps; ++i) { |
| 99 | // TODO: remove std::visit for support osx 10.12 |
| 100 | host_inp[i] = std::visit( |
| 101 | [&gen](auto&& arg) -> HostTensorND { |
| 102 | using T = std::decay_t<decltype(arg)>; |
| 103 | if constexpr (std::is_same_v<TensorShape, T>) { |
| 104 | return *gen(arg); |
| 105 | } else { |
| 106 | static_assert(std::is_same_v<HostTensorND, T>); |
| 107 | return arg; |
| 108 | } |
| 109 | }, |
| 110 | inp_keys[i]); |
| 111 | sym_inp[i] = opr::SharedDeviceTensor::make(*graph, host_inp[i]).node(); |
| 112 | } |
| 113 | auto sym_oup = OpDef::apply_on_var_node(*m_op, sym_inp); |
| 114 | size_t nr_oups = sym_oup.size(); |
| 115 | ComputingGraph::OutputSpec oup_spec(nr_oups); |
| 116 | SmallVector<HostTensorND> host_sym_oup(nr_oups); |
| 117 | for (size_t i = 0; i < nr_oups; ++i) { |
| 118 | oup_spec[i] = make_callback_copy(sym_oup[i], host_sym_oup[i]); |
| 119 | } |
| 120 | auto func = graph->compile(oup_spec); |
| 121 | |
| 122 | SmallVector<TensorPtr> imp_physical_inp(nr_inps); |
| 123 | for (size_t i = 0; i < nr_inps; ++i) { |
| 124 | imp_physical_inp[i] = Tensor::make(host_inp[i]); |
| 125 | } |
| 126 | |
| 127 | SmallVector<LogicalTensorDesc> output_descs; |
| 128 | auto imp_oup = OpDef::apply_on_physical_tensor( |
| 129 | *m_op, imp_physical_inp, output_descs, false); |
| 130 | mgb_assert(imp_oup.size() == nr_oups); |
| 131 | |
| 132 | // check input not modified |
| 133 | for (size_t i = 0; i < imp_physical_inp.size(); ++i) { |
| 134 | HostTensorND hv; |
| 135 | hv.copy_from(imp_physical_inp[i]->dev_tensor()).sync(); |
| 136 | MGB_ASSERT_TENSOR_EQ(hv, host_inp[i]); |
| 137 | } |
| 138 | |
| 139 | SmallVector<HostTensorND> host_imp_oup(nr_oups); |
| 140 | for (size_t i = 0; i < nr_oups; ++i) { |
| 141 | host_imp_oup[i].copy_from(imp_oup[i]->dev_tensor()).sync(); |
| 142 | } |
| 143 | |
| 144 | func->execute().wait(); // run last because it may contain inplace operations |
| 145 | |
| 146 | for (size_t i = 0; i < nr_oups; ++i) { |
| 147 | if (bypass.find(i) != bypass.end()) |
| 148 | continue; |
no test coverage detected