| 781 | } |
| 782 | |
| 783 | void ChannelImpl::do_apply_op(const ApplyOp& cmd, std::string reason) { |
| 784 | using namespace ranges; |
| 785 | using namespace ranges::views; |
| 786 | auto& state = get_worker_state(); |
| 787 | bool profiling_device = |
| 788 | Profiler::is_profiling() && Profiler::get_option("profile_device", 0); |
| 789 | uint64_t apply_id = cmd.id; |
| 790 | SmallVector<TensorPtr> inputs; |
| 791 | inputs.reserve(cmd.inputs.size()); |
| 792 | // refcnt == 1, owners: [TensorInfo::ptr] |
| 793 | for (auto i : cmd.inputs) { |
| 794 | mgb_assert(i->ptr, "Invalid input tensor ptr!"); |
| 795 | // refcnt ++, owners: [i->ptr, tensor_inputs] |
| 796 | // tensor_inputs.push_back(i->ptr); |
| 797 | inputs.push_back(i->ptr); |
| 798 | } |
| 799 | if (state.options.enable_dtr_auto_drop && |
| 800 | state.options.dtr_eviction_threshold > 0) { |
| 801 | auto_evict(0); |
| 802 | } |
| 803 | auto apply_on_physical_tensor = |
| 804 | [&](auto&& self, const OpDef& def, SmallVector<TensorPtr>&& inputs, |
| 805 | SmallVector<LogicalTensorDesc>& output_descs, |
| 806 | const bool& validated) -> SmallVector<TensorPtr> { |
| 807 | if (def.trait()->make_forward_graph) { |
| 808 | auto apply_functor = [&](std::shared_ptr<OpDef> op, |
| 809 | SmallVector<TensorPtr> inputs, |
| 810 | size_t nr_outputs) -> SmallVector<TensorPtr> { |
| 811 | auto opname = op->trait()->make_name(*op); |
| 812 | imperative_log_profile_begin(opname.c_str()); |
| 813 | auto outputs = self(self, *op, std::move(inputs), output_descs, false); |
| 814 | imperative_log_profile_end(opname.c_str()); |
| 815 | return outputs; |
| 816 | }; |
| 817 | auto const_functor = [&](TensorPtr value) -> TensorPtr { return value; }; |
| 818 | // apply recursivily |
| 819 | SmallVector<LogicalTensorDesc> input_descs; |
| 820 | for (auto&& input : inputs) { |
| 821 | input_descs.push_back({{{}, input->dtype()}, input->comp_node()}); |
| 822 | } |
| 823 | auto forward_graph = OpDef::make_forward_graph(def, input_descs); |
| 824 | auto outputs = forward_graph.apply<TensorPtr>( |
| 825 | inputs, apply_functor, const_functor); |
| 826 | return outputs; |
| 827 | } |
| 828 | // Check Input Layout |
| 829 | // Get the input layout constraints, and if the constraint is not satisfied |
| 830 | // inplace update the layout and blob to make the tensor contiguous |
| 831 | auto&& constraints = OpDef::get_input_layout_constraint(def, inputs); |
| 832 | for (size_t idx = 0; idx < inputs.size(); ++idx) { |
| 833 | auto&& layout_checker = constraints[idx]; |
| 834 | if (layout_checker) { |
| 835 | inputs[idx]->to_contiguous_inplace(layout_checker); |
| 836 | } |
| 837 | } |
| 838 | auto outputs = OpDef::apply_on_physical_tensor( |
| 839 | def, std::move(inputs), output_descs, validated); |
| 840 | for (auto& o : outputs) { |
nothing calls this directly
no test coverage detected