MCPcopy Create free account
hub / github.com/MegEngine/MegEngine / MGB_IMPL_OPR_GRAD

Function MGB_IMPL_OPR_GRAD

src/jit/impl/executor_opr.cpp:483–626  ·  view source on GitHub ↗

anonymous namespace

Source from the content-addressed store, hash-verified

481};
482} // anonymous namespace
483MGB_IMPL_OPR_GRAD(JITExecutor) {
484 VarNodeArray grad_inputs;
485 for (auto input : opr.input())
486 grad_inputs.push_back(input);
487 mgb_assert(out_grad[0]);
488 grad_inputs.push_back(opr.output(0));
489 grad_inputs.push_back(out_grad[0]);
490 auto fwd_igraph_ptr = opr.internal_graph_ptr();
491 auto output_ph = JITPlaceholder::make(
492 fwd_igraph_ptr->output(), fwd_igraph_ptr->placeholders().size());
493 auto og_ph = JITPlaceholder::make(
494 out_grad[0], fwd_igraph_ptr->placeholders().size() + 1);
495 auto loss = opr::VirtualLoss::make({fwd_igraph_ptr->output()}, {og_ph});
496 auto gx = cg::grad(
497 loss, fwd_igraph_ptr->placeholders()[wrt_idx]->output(0), false, false);
498 if (!gx.node()) {
499 return nullptr;
500 }
501 if (gx.node()->owner_opr()->same_type<opr::InvalidGrad>()) {
502 return opr::InvalidGrad::make(opr, wrt_idx);
503 }
504 // early return if grad expression is single node
505 for (size_t i = 0; i < fwd_igraph_ptr->placeholders().size(); ++i) {
506 if (gx.node() == fwd_igraph_ptr->placeholders()[i]->output(0)) {
507 return grad_inputs[i];
508 }
509 }
510 if (gx.node() == og_ph.node()) {
511 return out_grad[0];
512 }
513 if (gx.node() == fwd_igraph_ptr->output()) {
514 return opr.output(0);
515 }
516 if (auto imm = gopt::try_cast_as_op<opr::ImmutableTensor>(gx.node()->owner_opr())) {
517 HostTensorND hval{grad_inputs[0]->comp_node()};
518 hval.copy_from(imm->value()).sync();
519 return opr::ImmutableTensor::make(*imm->owner_graph(), hval).node();
520 }
521
522 // replace output var in internal graph with output placeholder, so
523 // we could forward opr.output(computeed by forward JITExecutor) into
524 // placeholder to avoid redundant computation
525 InternalGraphRewriter rewriter{gx.node()};
526 rewriter.iter([&rewriter, &fwd_igraph_ptr, &output_ph](cg::OperatorNodeBase* opr) {
527 if (opr == fwd_igraph_ptr->output()->owner_opr()) {
528 rewriter.replace_var(opr->output(0), output_ph.node());
529 return;
530 }
531 rewriter.auto_replace_outputs(opr);
532 });
533
534 auto expand_into_origin_graph = [&rewriter](
535 cg::OperatorNodeBase* opr,
536 const VarNodeArray& grad_inputs) {
537 if (auto ph = gopt::try_cast_as_op<JITPlaceholder>(opr)) {
538 rewriter.replace_var(opr->output(0), grad_inputs.at(ph->input_id()));
539 return;
540 }

Callers

nothing calls this directly

Calls 15

gradFunction · 0.85
is_const_var_valueFunction · 0.85
backMethod · 0.80
shape_inferMethod · 0.80
has_dimshuffleMethod · 0.80
makeFunction · 0.50
reduce_sumFunction · 0.50
inputMethod · 0.45
push_backMethod · 0.45
outputMethod · 0.45
sizeMethod · 0.45
nodeMethod · 0.45

Tested by

no test coverage detected