ONE - On-device Neural Engine
Loading...
Searching...
No Matches
onert::backend::builtin::kernel::WhileLayer Class Reference

#include <WhileLayer.h>

Collaboration diagram for onert::backend::builtin::kernel::WhileLayer:

Public Member Functions

 WhileLayer (const std::vector< backend::IPortableTensor * > input_tensors, const std::vector< backend::IPortableTensor * > output_tensors, const ir::SubgraphIndex &cond_subg_index, const ir::SubgraphIndex &body_subg_index, exec::IExecutors *executors, const ir::ModelIndex &model_index, basic::DynamicMemoryManager *dyn_memory_manager, const std::shared_ptr< ExternalContext > &external_context)
 
void run () override
 
- Public Member Functions inherited from onert::exec::IFunction
virtual ~IFunction ()=default
 
virtual void prepare ()
 

Detailed Description

Definition at line 38 of file WhileLayer.h.

Constructor & Destructor Documentation

◆ WhileLayer()

onert::backend::builtin::kernel::WhileLayer::WhileLayer ( const std::vector< backend::IPortableTensor * >  input_tensors,
const std::vector< backend::IPortableTensor * >  output_tensors,
const ir::SubgraphIndex cond_subg_index,
const ir::SubgraphIndex body_subg_index,
exec::IExecutors executors,
const ir::ModelIndex model_index,
basic::DynamicMemoryManager dyn_memory_manager,
const std::shared_ptr< ExternalContext > &  external_context 
)

Definition at line 35 of file WhileLayer.cc.

42 : _cond_subg_index{cond_subg_index}, _body_subg_index{body_subg_index},
43 _input_tensors{input_tensors}, _output_tensors{output_tensors}, _executors{executors},
44 _model_index{model_index}, _dyn_memory_manager{dyn_memory_manager},
45 _external_context{external_context}
46{
47 // At this point, executors may not have executors of cond subg and body subg
48}

Member Function Documentation

◆ run()

void onert::backend::builtin::kernel::WhileLayer::run ( )
overridevirtual

Implements onert::exec::IFunction.

Definition at line 50 of file WhileLayer.cc.

51{
52 // Copy "_input_tensors" -> "cond subg inputs"
53 // Run cond subg
54 // Start loop while output of cond subg is ture
55 // // Copy "_input_tensors" -> "body subg inputs" in the first iteration, then copy "body subg
56 // outputs" -> "body subg inputs" in the second or more iterations
57 // // Run body subg
58 // // Copy "body subg outputs" -> "cond subg inputs"
59 // // Run cond subg
60 // If there is no loop copy "_input_tensors" -> "_dst_tensors", else copy "cond subg inputs" ->
61 // "_dst_tensors"
62 auto cond_exec = _executors->at(_model_index, _cond_subg_index);
63 auto body_exec = _executors->at(_model_index, _body_subg_index);
64
65 // Need a temp tensor to hold the cond subgraph output
66 assert(cond_exec->outputSize() == 1);
67 auto cond_output_tensor = [&]() {
68 auto tensor = std::make_unique<Tensor>(cond_exec->outputInfo(0), _dyn_memory_manager);
69 tensor->set_dynamic();
70 tensor->setBuffer(_dyn_memory_manager->allocate(tensor.get(), tensor->total_size()));
71 return tensor;
72 }();
73
74 VERBOSE(While) << "Call to $" << _cond_subg_index << " (cond)" << std::endl;
75 const auto &options = _executors->entryExecutor()->currentOptions();
76 cond_exec->execute(_input_tensors, {cond_output_tensor.get()}, options);
77 VERBOSE(While) << "Return from $" << _cond_subg_index << std::endl;
78
79 auto getResultCond = [](backend::ITensor *tensor) -> bool {
80 bool ret = false;
81 tensor->access([&](ITensor &tensor) { ret = *reinterpret_cast<bool *>(tensor.buffer()); });
82 return ret;
83 };
84
85 std::vector<ITensor *> op_inputs(_input_tensors.begin(), _input_tensors.end());
86 std::vector<ITensor *> op_outputs(_output_tensors.begin(), _output_tensors.end());
87 std::vector<ir::PermuteType> permute_types;
88 // Layout in graph is always NHWC, so layout is not changed
89 for (uint32_t i = 0; i < op_outputs.size(); i++)
90 permute_types.emplace_back(ir::PermuteType::COPY);
91 // Copying body inputs to outputs when the loop body is never executed
92 if (!getResultCond(cond_output_tensor.get()))
93 {
94 PermuteLayer copy_body_inputs_to_op_outputs{op_inputs, op_outputs, permute_types,
95 _external_context};
96 copy_body_inputs_to_op_outputs.run();
97 return;
98 }
99
100 // Need some temp tensors to hold the body subgraph output
101 std::vector<std::unique_ptr<Tensor>> temp_outputs_o;
102 std::vector<IPortableTensor *> temp_outputs;
103 for (uint32_t i = 0; i < body_exec->outputSize(); i++)
104 {
105 auto tensor = std::make_unique<Tensor>(body_exec->outputInfo(i), _dyn_memory_manager);
106 tensor->set_dynamic();
107 tensor->setBuffer(_dyn_memory_manager->allocate(tensor.get(), tensor->total_size()));
108 temp_outputs.push_back(tensor.get());
109 temp_outputs_o.push_back(std::move(tensor));
110 }
111
112 std::vector<ITensor *> body_outputs(temp_outputs.begin(), temp_outputs.end());
113 PermuteLayer copy_body_outputs_to_op_outputs{body_outputs, op_outputs, permute_types,
114 _external_context};
115
116 const auto body_execute_with_op_inputs = [&]() {
117 VERBOSE(While) << "Call to $" << _body_subg_index << " (body)" << std::endl;
118 body_exec->execute(_input_tensors, temp_outputs, options);
119 VERBOSE(While) << "Return from $" << _body_subg_index << std::endl;
120 };
121
122 const auto body_execute_with_body_outputs = [&]() {
123 VERBOSE(While) << "Call to $" << _body_subg_index << " (body)" << std::endl;
124 body_exec->execute(_output_tensors, temp_outputs, options);
125 VERBOSE(While) << "Return from $" << _body_subg_index << std::endl;
126 };
127
128 std::function<void()> body_execute = body_execute_with_op_inputs;
129 const auto cond_execute = [&]() {
130 VERBOSE(While) << "Call to $" << _cond_subg_index << " (cond)" << std::endl;
131 cond_exec->execute(_output_tensors, {cond_output_tensor.get()}, options);
132 VERBOSE(While) << "Return from $" << _cond_subg_index << std::endl;
133 };
134
135 // Loop while Cond subgraph's output is true
136 while (getResultCond(cond_output_tensor.get()))
137 {
138 body_execute();
139 copy_body_outputs_to_op_outputs.run();
140 cond_execute();
141 body_execute = body_execute_with_body_outputs;
142 }
143
144 // Clean-up the temp tensors
145 _dyn_memory_manager->deallocate(cond_output_tensor.get());
146 for (auto &&tensor : temp_outputs)
147 {
148 _dyn_memory_manager->deallocate(tensor);
149 }
150}
std::shared_ptr< Allocator > allocate(const ITensor *tensor, uint32_t capacity)
IExecutor * entryExecutor() const
Definition IExecutors.h:60
virtual IExecutor * at(const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index) const =0
Return executor of index.
#define VERBOSE(name, lv)
Definition Log.h:71
virtual const ExecutionOptions & currentOptions() const =0
Return current execution configuration.

References onert::backend::basic::DynamicMemoryManager::allocate(), onert::exec::IExecutors::at(), onert::ir::COPY, onert::exec::IExecutor::currentOptions(), onert::backend::basic::DynamicMemoryManager::deallocate(), onert::exec::IExecutors::entryExecutor(), and VERBOSE.

Referenced by package.infer.session::inference().


The documentation for this class was generated from the following files: