| 85 | } |
| 86 | |
| 87 | void OperatorNodeBase::execute(ExecEnv& env) { |
| 88 | if (owner_graph()->options().imperative_proxy_graph) { |
| 89 | do_execute(env); |
| 90 | return; |
| 91 | } |
| 92 | |
| 93 | owner_graph()->event().signal_inplace<event::OprExecStart>(this, &env); |
| 94 | |
| 95 | // dispatch waiting commands |
| 96 | for (auto&& wspec : input_waiting_spec()) { |
| 97 | auto runner = [this, ps = &wspec]() { |
| 98 | for (VarNode* i : ps->dev_ready) { |
| 99 | auto&& event = VarNodeMemManager::var_node_cn_sync_manager(i) |
| 100 | ->busy_wait_set_ready_and_get_event(); |
| 101 | ps->comp_node.device_wait_event(event); |
| 102 | } |
| 103 | owner_graph()->event().signal_inplace<event::AfterWait>( |
| 104 | ps->comp_node, this); |
| 105 | }; |
| 106 | // always maintain var sync order, so we dispatch without execution mask |
| 107 | env.dispatch_on_comp_node_with_mask(wspec.comp_node, runner, nullptr); |
| 108 | } |
| 109 | |
| 110 | // allocate output with dynamic storage |
| 111 | ComputingGraphImpl::downcast(owner_graph()) |
| 112 | ->var_node_mem_manager() |
| 113 | .alloc_var_node_mem_dynamic(env, this); |
| 114 | |
| 115 | // find shape-dep inputs: |
| 116 | // shape/value deps whose static infer source is missing are added to |
| 117 | // DEV_COMP_ORDER dep by topo sorter, so it is guaranteed that static infer |
| 118 | // would success here. For host-value deps, opr would query |
| 119 | // static_infer_manager so the value would be up-to-date; however for shape |
| 120 | // deps, oprs would access the shape directly, so we need to insert some |
| 121 | // code here to ensure it is up-to-date. |
| 122 | if (!ComputingGraphImpl::downcast(owner_graph())->eager_eval_manager().enabled()) { |
| 123 | VarNodeArray vars_to_set; |
| 124 | auto cg = ComputingGraphImpl::downcast(owner_graph()); |
| 125 | auto step_cur = cg->opr_step_num_in_cur_comp_seq(this).val(); |
| 126 | mgb_assert(step_cur < std::numeric_limits<size_t>::max()); |
| 127 | using DT = NodeProp::DepType; |
| 128 | CompNode uniq_cn; // all outputs should be on the same comp node |
| 129 | for (auto&& i : node_prop().dep_map()) { |
| 130 | if ((i.second & DT::SHAPE) && !(i.second & DT::DEV_VALUE)) { |
| 131 | auto var = i.first; |
| 132 | if (!uniq_cn.valid()) { |
| 133 | uniq_cn = output(0)->comp_node(); |
| 134 | for (auto i : output()) { |
| 135 | mgb_assert( |
| 136 | uniq_cn == i->comp_node(), |
| 137 | "opr that has shape dep should be on a " |
| 138 | "single comp node; opr=%s{%s}", |
| 139 | cname(), dyn_typeinfo()->name); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | auto vs = cg->opr_step_num_in_cur_comp_seq(var->owner_opr()); |
| 144 | if (!vs.valid() || step_cur < vs.val() || var->comp_node() != uniq_cn) { |