| 202 | } |
| 203 | |
| 204 | TEST_F(TestGoptExpandVirtualGradPass, GradWrt) { |
| 205 | graph->options().graph_opt_level = 0; |
| 206 | auto x = mkvar("x", {2, 3}); |
| 207 | SymbolVar wrt; |
| 208 | auto get_grad = [&wrt](const opr::SetGrad& g) -> SymbolVar { |
| 209 | auto w = gopt::GraphOptimizer::var_replace_lookup(wrt.node()); |
| 210 | return cg::grad(cg::current_grad_target(*g.owner_graph()), w, false); |
| 211 | }; |
| 212 | wrt = opr::SetGrad::make(x * 2 + 1, get_grad) * 3 + 1; |
| 213 | |
| 214 | auto gx = opr::VirtualGrad::make(opr::reduce_sum(wrt, wrt.make_scalar(1)), x); |
| 215 | |
| 216 | SymbolVar gx_opt; |
| 217 | unpack_vector( |
| 218 | gopt::GraphOptimizer{} |
| 219 | .add_pass<gopt::ArithFusePass>() |
| 220 | .add_pass<gopt::ExpandVirtualGradPass>() |
| 221 | .verbosity(2) |
| 222 | .apply({{gx}}) |
| 223 | .endpoint_vars(), |
| 224 | gx_opt); |
| 225 | |
| 226 | HostTensorND host_gx; |
| 227 | auto func = graph->compile({make_callback_copy(gx_opt, host_gx)}); |
| 228 | func->execute(); |
| 229 | ASSERT_EQ(x.shape(), host_gx.shape()); |
| 230 | |
| 231 | auto pgx = host_gx.ptr<float>(); |
| 232 | for (size_t i = 0, it = host_gx.shape().total_nr_elems(); i < it; ++i) { |
| 233 | ASSERT_EQ(2.f, pgx[i]); |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | TEST_F(TestGoptExpandVirtualGradPass, VarReplaceLookup) { |
| 238 | HostTensorGenerator<> gen; |
nothing calls this directly
no test coverage detected