| 17 | using OutputMode = LoopDesc::OutputMode; |
| 18 | |
| 19 | TEST(TestOprLoopRecordInternal, ImpureOprRNG) { |
| 20 | constexpr int LOOP_TIME = 3; |
| 21 | constexpr size_t SIZE = 23; |
| 22 | HostTensorGenerator<> gen; |
| 23 | HostTensorGenerator<dtype::Float32, RandomDistribution::UNIFORM> genx{1e-3, 1.5}; |
| 24 | |
| 25 | auto host_x = genx({SIZE}), host_loss_p = gen({SIZE}); |
| 26 | auto graph = ComputingGraph::make(); |
| 27 | auto x = opr::Host2DeviceCopy::make(*graph, host_x); |
| 28 | |
| 29 | auto desc_maker = [&](LoopDesc& desc) { |
| 30 | auto xl = desc.add_input_assignable(x.fill_retain_dtype(1.f)), |
| 31 | rand = opr::UniformRNG::make(opr::GetVarShape::make(xl)); |
| 32 | desc.assign(xl, xl * opr::pow(desc.add_input(x), rand * 2)); |
| 33 | desc.add_output(xl, OutputMode::LAST); |
| 34 | desc.set_loop_condition(desc.get_counter_var() < LOOP_TIME); |
| 35 | }; |
| 36 | auto y = opr::Loop::make(desc_maker)[0]; |
| 37 | auto loss = opr::Dot::make(y, opr::Host2DeviceCopy::make(*graph, host_loss_p)), |
| 38 | gx = cg::grad(loss, x); |
| 39 | HostTensorND host_gx, host_y; |
| 40 | auto func = graph->compile( |
| 41 | {make_callback_copy(y, host_y), make_callback_copy(gx, host_gx)}); |
| 42 | func->execute(); |
| 43 | |
| 44 | HostTensorND host_rand; |
| 45 | func = graph->compile({make_callback_copy( |
| 46 | opr::UniformRNG::make(opr::GetVarShape::make(x)), host_rand)}); |
| 47 | HostTensorND gx_expect, y_expect; |
| 48 | gx_expect.copy_from(*host_x); |
| 49 | y_expect.copy_from(*host_x); |
| 50 | auto pgx = gx_expect.ptr<float>(); |
| 51 | memset(pgx, 0, sizeof(float) * SIZE); |
| 52 | for (int i = 0; i < LOOP_TIME; ++i) { |
| 53 | func->execute(); |
| 54 | auto pr = host_rand.ptr<float>(); |
| 55 | for (size_t j = 0; j < SIZE; ++j) { |
| 56 | pgx[j] += pr[j] * 2; |
| 57 | } |
| 58 | } |
| 59 | auto py = y_expect.ptr<float>(), plp = host_loss_p->ptr<float>(); |
| 60 | for (size_t i = 0; i < SIZE; ++i) { |
| 61 | float x = py[i], e = pgx[i]; |
| 62 | py[i] = std::pow(x, e); |
| 63 | pgx[i] = plp[i] * e * std::pow(x, e - 1); |
| 64 | } |
| 65 | |
| 66 | MGB_ASSERT_TENSOR_EQ(y_expect, host_y); |
| 67 | MGB_ASSERT_TENSOR_EQ(gx_expect, host_gx); |
| 68 | } |
| 69 | |
| 70 | // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}} |
nothing calls this directly
no test coverage detected