| 48 | namespace { |
| 49 | |
| 50 | void test_basic_fwd_with_grad(bool dyn) { |
| 51 | HostTensorGenerator<> gen; |
| 52 | |
| 53 | auto host_x = gen({23}); |
| 54 | auto host_loop_time = |
| 55 | std::make_shared<HostTensorND>(host_x->comp_node(), dtype::Int32()); |
| 56 | auto graph = ComputingGraph::make(); |
| 57 | auto x = opr::Host2DeviceCopy::make(*graph, host_x); |
| 58 | |
| 59 | auto d = [dyn](SymbolVar var) -> SymbolVar { |
| 60 | if (dyn) |
| 61 | var = opr::MarkDynamicVar::make(var).node(); |
| 62 | return var; |
| 63 | }; |
| 64 | |
| 65 | auto desc_maker = [&, loop_time = opr::Host2DeviceCopy::make( |
| 66 | *graph, host_loop_time)](LoopDesc& loop_desc) { |
| 67 | auto xl = loop_desc.add_input_assignable(x).rename("xl"), |
| 68 | x0 = d(loop_desc.add_input(x)).rename("x0"), |
| 69 | xu = (opr::pow(d(xl), xl.make_scalar(0.9f)) * x0).rename("xu"); |
| 70 | loop_desc.assign(xl, xu); |
| 71 | loop_desc.add_output(xu, OutputMode::LAST); |
| 72 | auto cnt = d(loop_desc.get_counter_var()); |
| 73 | loop_desc.set_loop_condition(cnt < loop_desc.add_input(loop_time) - 1); |
| 74 | }; |
| 75 | |
| 76 | auto y = opr::Loop::make(desc_maker, 3)[0], |
| 77 | loss = opr::reduce_sum(y, y.make_scalar(1)), gx = cg::grad(loss, x); |
| 78 | HostTensorND host_y, host_gx; |
| 79 | auto func = graph->compile( |
| 80 | {make_callback_copy(y, host_y), make_callback_copy(gx, host_gx)}); |
| 81 | |
| 82 | int& loop_time = host_loop_time->resize({1}).ptr<int>()[0]; |
| 83 | for (size_t sz : {12, 24}) { |
| 84 | *host_x = *gen({sz}); |
| 85 | auto px = host_x->ptr<float>(); |
| 86 | for (size_t i = 0; i < sz; ++i) |
| 87 | px[i] = std::abs(px[i]); |
| 88 | |
| 89 | for (loop_time = 1; loop_time <= 50; ++loop_time) { |
| 90 | func->execute(); |
| 91 | ASSERT_EQ(host_x->shape(), host_y.shape()); |
| 92 | ASSERT_EQ(host_x->shape(), host_gx.shape()); |
| 93 | |
| 94 | auto py = host_y.ptr<float>(), pgx = host_gx.ptr<float>(); |
| 95 | |
| 96 | float dpow = 1; |
| 97 | for (int i = 0; i < loop_time; ++i) |
| 98 | dpow = dpow * 0.9f + 1.f; |
| 99 | for (size_t i = 0; i < sz; ++i) { |
| 100 | auto x = px[i], y = py[i], gx = pgx[i]; |
| 101 | MGB_ASSERT_FLOAT_NEAR(std::pow(x, dpow), y, 1e-5) << loop_time; |
| 102 | MGB_ASSERT_FLOAT_NEAR(dpow * std::pow(x, (dpow - 1.f)), gx, 1e-5) |
| 103 | << loop_time; |
| 104 | } |
| 105 | } |
| 106 | } |
| 107 | } |
no test coverage detected