ONE - On-device Neural Engine
Loading...
Searching...
No Matches
onert::backend::basic Namespace Reference

Namespaces

namespace  train
 

Data Structures

class  Allocator
 Class to allocate memory. More...
 
struct  Block
 Structure to have memory offset and size. More...
 
class  BumpPlanner
 Class to plan memory by bump way. More...
 
class  DynamicMemoryManager
 
class  DynamicTensorManager
 Class to manage dynamic tensor and its memory. More...
 
class  ExternalTensor
 Class that uses data from external memory that is not managed by a backend instead of allocating and copying the data. (ex. constant data from model file) ExternalTensor's data pointer points to an address of memory such as where memory is already allocated, or mmapped area. This is meaning that ExternalTensor can take all of types' ir::Data. To support this, assume below things no padding, always NHWC layout, constant tensor and not dynamic. More...
 
class  FirstFitPlanner
 Class to plan memory by firstfit way. More...
 
struct  IMemoryPlanner
 Interface to plan memory. More...
 
class  KernelGeneratorBase
 
class  MemoryManager
 
class  MemoryPlannerFactory
 
class  StaticTensorManager
 
class  Tensor
 
class  TensorBuilder
 
class  WICPlanner
 Class to plan memory by Weighted Interval Color algorithm. More...
 

Typedefs

using TensorRegistry = PortableTensorRegistryTemplate< basic::Tensor >
 

Functions

template<typename T_TensorBuilder >
void planTensors (const std::shared_ptr< T_TensorBuilder > &tensor_builder, const ir::Graph &graph, const util::Set< ir::OperandIndex > &external_operands, const std::vector< onert::ir::OperationIndex > &op_order)
 
template<typename T_TensorBuilder >
util::Set< ir::OperandIndexregister_source_memory_tensors (const std::shared_ptr< T_TensorBuilder > &tensor_builder, const ir::Graph &graph, const util::Set< ir::OperandIndex > &external_operands, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operand_idx)
 
template<typename T_TensorBuilder >
ITensorRegistrygenTensors (const std::shared_ptr< T_TensorBuilder > &tensor_builder, const ir::Graph &graph, const util::Set< ir::OperandIndex > &external_operands, const std::shared_ptr< ITensorRegistry > &tensor_registry, const std::vector< onert::ir::OperationIndex > &op_order, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operand_idx)
 
template<typename T_BackendContext >
ITensorRegistrygenTensors (T_BackendContext &ctx)
 
void initSharedMemoryConsts (const ir::Operands &operands, const util::Set< ir::OperandIndex > &external_operands, TensorRegistry *tensor_registry, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operands_map)
 
void initConsts (const ir::Operands &operands, const util::Set< ir::OperandIndex > &external_operands, ITensorRegistry *tensor_registry, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operands_map)
 
void initConsts (BackendContext &ctx)
 

Typedef Documentation

◆ TensorRegistry

Function Documentation

◆ genTensors() [1/2]

template<typename T_TensorBuilder >
ITensorRegistry * onert::backend::basic::genTensors ( const std::shared_ptr< T_TensorBuilder > &  tensor_builder,
const ir::Graph graph,
const util::Set< ir::OperandIndex > &  external_operands,
const std::shared_ptr< ITensorRegistry > &  tensor_registry,
const std::vector< onert::ir::OperationIndex > &  op_order,
const ir::OperandIndexMap< ir::OperandIndex > &  shared_memory_operand_idx 
)

Definition at line 201 of file BackendContextHelpers.h.

207{
208 const auto registered_source_ind = register_source_memory_tensors(
209 tensor_builder, graph, external_operands, shared_memory_operand_idx);
210 graph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
211 if (external_operands.contains(ind))
212 return;
213 if (registered_source_ind.contains(ind)) // skip tensors already registered
214 return;
215 tensor_builder->registerTensorInfo(ind, obj.info());
216 });
217
218 // TODO Get compiler options from compiler, and use it rather than getting it from Env
219 if (util::getConfigString(util::config::EXECUTOR) == "Linear")
220 {
221 basic::planTensors(tensor_builder, graph, external_operands, op_order);
222 }
223 else
224 {
225 // For the executors that does not have fixed linear execution order:
226 // To make tensors never be deallocated, this is a workaround to use static memory planner
227 graph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &) {
228 if (tensor_builder->isRegistered(ind))
229 tensor_builder->notifyFirstUse(ind);
230 });
231 }
232
233 tensor_builder->allocate();
234
235 return tensor_registry.get();
236}
bool contains(const Element &e) const
Get whether a given element exists in the set.
Definition Set.h:96
util::Set< ir::OperandIndex > register_source_memory_tensors(const std::shared_ptr< T_TensorBuilder > &tensor_builder, const ir::Graph &graph, const util::Set< ir::OperandIndex > &external_operands, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operand_idx)

References onert::util::Set< Element >::contains(), onert::util::getConfigString(), planTensors(), and register_source_memory_tensors().

Referenced by onert::backend::cpu::BackendContext::genTensors(), onert::backend::ruy::BackendContext::genTensors(), onert::backend::trix::BackendContext::genTensors(), onert::backend::xnnpack::BackendContext::genTensors(), onert::backend::builtin::BackendContext::genTensors(), and genTensors().

◆ genTensors() [2/2]

template<typename T_BackendContext >
ITensorRegistry * onert::backend::basic::genTensors ( T_BackendContext &  ctx)

Definition at line 238 of file BackendContextHelpers.h.

239{
240 return genTensors(ctx.tensor_builder, *ctx.graph(), ctx.external_operands(), ctx.tensor_registry,
241 ctx.data().op_order, {});
242}
ITensorRegistry * genTensors(const std::shared_ptr< T_TensorBuilder > &tensor_builder, const ir::Graph &graph, const util::Set< ir::OperandIndex > &external_operands, const std::shared_ptr< ITensorRegistry > &tensor_registry, const std::vector< onert::ir::OperationIndex > &op_order, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operand_idx)

References genTensors().

◆ initConsts() [1/2]

void onert::backend::basic::initConsts ( BackendContext ctx)
inline

Definition at line 300 of file BackendContextHelpers.h.

301{
302 initConsts(ctx.graph()->operands(), ctx.external_operands(), ctx.tensor_registry.get(), {});
303}
std::shared_ptr< ITensorRegistry > tensor_registry
const ir::Graph * graph() const
const util::Set< ir::OperandIndex > & external_operands() const
const Operands & operands() const override
Definition Graph.h:112
void initConsts(const ir::Operands &operands, const util::Set< ir::OperandIndex > &external_operands, ITensorRegistry *tensor_registry, const ir::OperandIndexMap< ir::OperandIndex > &shared_memory_operands_map)

References onert::backend::BackendContext::external_operands(), onert::backend::BackendContext::graph(), initConsts(), onert::ir::Graph::operands(), and onert::backend::BackendContext::tensor_registry.

◆ initConsts() [2/2]

void onert::backend::basic::initConsts ( const ir::Operands operands,
const util::Set< ir::OperandIndex > &  external_operands,
ITensorRegistry tensor_registry,
const ir::OperandIndexMap< ir::OperandIndex > &  shared_memory_operands_map 
)
inline

Definition at line 270 of file BackendContextHelpers.h.

274{
275 operands.iterate([&](const ir::OperandIndex &ind, const ir::Operand &operand) {
276 if (external_operands.contains(ind) || !operand.isConstant())
277 return;
278 const bool has_const_shared_source =
279 shared_memory_operands_map.find(ind) != std::end(shared_memory_operands_map) &&
280 operands.at(shared_memory_operands_map.at(ind)).isConstant();
281 if (has_const_shared_source)
282 return; // tensors with shared memory are processed in initSharedMemoryConsts
283
284 auto tensor = tensor_registry->getNativeITensor(ind);
285 assert(tensor != nullptr);
286
287 VERBOSE(FillOperandData) << "Fill data for " << ind << std::endl;
288
289 auto data = operand.shareData();
290 assert(data && data->base());
291 ExternalTensor *ext_tensor = dynamic_cast<ExternalTensor *>(tensor);
292
293 if (ext_tensor == nullptr)
294 throw std::runtime_error{"This tensor is not external tensor"};
295
296 ext_tensor->setData(data);
297 });
298}
Class that uses data from external memory that is not managed by a backend instead of allocating and ...
Definition Tensor.h:152
void setData(const std::shared_ptr< ir::Data > data)
set Data to be shared from external so that this ExternalTensor will not be allocated on CPU backend
Definition Tensor.h:170
bool isConstant(void) const
Get true if Operand is const, otherwise false a.
Definition Operand.h:79
std::shared_ptr< Data > shareData(void) const
Definition Operand.h:73
void iterate(const std::function< void(const Index &, const Object &)> &fn) const
Iterate over the container with given function.
const Object & at(const Index &index) const
Get the object that is associated with the given index.
#define VERBOSE(name, lv)
Definition Log.h:71
virtual ITensor * getNativeITensor(const ir::OperandIndex &)=0
Returns pointer of ITensor among native tensors.

References onert::util::ObjectManager< Index, Object >::at(), onert::util::Set< Element >::contains(), onert::backend::ITensorRegistry::getNativeITensor(), onert::ir::Operand::isConstant(), onert::util::ObjectManager< Index, Object >::iterate(), onert::backend::basic::ExternalTensor::setData(), onert::ir::Operand::shareData(), and VERBOSE.

Referenced by onert::backend::cpu::BackendContext::genKernels(), onert::backend::ruy::BackendContext::genKernels(), onert::backend::trix::BackendContext::genKernels(), onert::backend::xnnpack::BackendContext::genKernels(), onert::backend::builtin::BackendContext::genKernels(), and initConsts().

◆ initSharedMemoryConsts()

void onert::backend::basic::initSharedMemoryConsts ( const ir::Operands operands,
const util::Set< ir::OperandIndex > &  external_operands,
TensorRegistry tensor_registry,
const ir::OperandIndexMap< ir::OperandIndex > &  shared_memory_operands_map 
)
inline

Definition at line 245 of file BackendContextHelpers.h.

249{
250 operands.iterate([&](const ir::OperandIndex &ind, const ir::Operand &) {
251 if (external_operands.contains(ind))
252 return;
253 const auto shared_mem_it = shared_memory_operands_map.find(ind);
254 if (shared_mem_it == std::end(shared_memory_operands_map))
255 return; // no shared memory source
256 if (!operands.at(shared_mem_it->second).isConstant())
257 return; // source operand not a constant
258
259 VERBOSE(FillOperandData) << "Fill shared data for " << ind << std::endl;
260
261 const auto &source_operand_ind = operands.at(shared_mem_it->second);
262 auto memory_source_data = source_operand_ind.shareData();
263 assert(memory_source_data && memory_source_data->base());
264 auto tensor = tensor_registry->getNativeTensor(ind);
265 assert(tensor != nullptr);
266 tensor->setBuffer(const_cast<uint8_t *>(memory_source_data->base()));
267 });
268}
T_Tensor * getNativeTensor(const ir::OperandIndex &ind)

References onert::util::ObjectManager< Index, Object >::at(), onert::util::Set< Element >::contains(), onert::backend::PortableTensorRegistryTemplate< T_Tensor >::getNativeTensor(), onert::util::ObjectManager< Index, Object >::iterate(), and VERBOSE.

Referenced by onert::backend::cpu::BackendContext::genKernels().

◆ planTensors()

template<typename T_TensorBuilder >
void onert::backend::basic::planTensors ( const std::shared_ptr< T_TensorBuilder > &  tensor_builder,
const ir::Graph graph,
const util::Set< ir::OperandIndex > &  external_operands,
const std::vector< onert::ir::OperationIndex > &  op_order 
)

Definition at line 39 of file BackendContextHelpers.h.

42{
46
47 // Prepare scanning
48 graph.operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
49 if (external_operands.contains(ind))
50 return;
51
52 // TODO Check if we need to handle unused tensors
53
54 uses_map[ind] = obj.getUses().size();
55 def_map[ind] = obj.getDef().valid() ? 1 : 0;
56
57 if (obj.isConstant())
58 constants.append(ind);
59
60 if (!tensor_builder->isRegistered(ind))
61 {
62 // These tensors do not exist in any (No use and def)
63 const auto &info = obj.info();
64 tensor_builder->registerTensorInfo(ind, info);
65 }
66 });
67
68 // Start scanning to do notify{First|Last}Use for each tensor
69
70 // If a tensor is a constant, increase the use of the tensor and allocate it first.
71 // Increasing use count here makes the tensor never be deallocated, i.e it they will be
72 // deallocated last.
73 for (const auto &ind : constants)
74 {
75 uses_map[ind]++;
76 tensor_builder->notifyFirstUse(ind);
77 }
78
79 for (const auto &[ind, def_count] : def_map)
80 {
81 if (def_count == 0)
82 tensor_builder->notifyFirstUse(ind);
83 }
84
85 // This is a workaround to keep the operands over the execution
86 // (the operands look like they are unused)
87 std::vector<ir::OperandIndex> operands_last_until_end;
88 for (const auto &[ind, use_count] : uses_map)
89 {
90 if (use_count == 0)
91 operands_last_until_end.push_back(ind);
92 }
93
94 // At each operation,
95 // 1. Scan DEF of outputs. If the DEF, allocate it
96 // 2. Scan DEF of inputs. If variable tensor, allocate it
97 // 3. Scan USE of inputs. Decrease the USE and deallocate if the USE is 0
98 for (const auto &op_ind : op_order)
99 {
100 const auto &op = graph.operations().at(op_ind);
101 auto op_inputs = op.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED;
102 auto op_outputs = op.getOutputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED;
103
104 // Define outputs
105 for (const auto &ind : op_outputs)
106 {
107 if (external_operands.contains(ind))
108 continue;
109 if (!tensor_builder->isRegistered(ind))
110 continue;
111 assert(def_map.find(ind) != def_map.end());
112 if (def_map[ind])
113 {
114 def_map[ind] = 0;
115 tensor_builder->notifyFirstUse(ind);
116 }
117 }
118
119 // Scan variable tensors
120 // This tensor has features like constant. But OperandInfo and LowerInfo treat them as
121 // non-constant because of less memory usage by memory planning in here
122 for (const auto &ind : op_inputs)
123 {
124 if (external_operands.contains(ind))
125 continue;
126 if (!tensor_builder->isRegistered(ind))
127 continue;
128 const auto &operand = graph.operands().at(ind);
129 if (operand.info().isVariable())
130 {
131 // The variable tensor with buffer is not supported yet
132 assert(operand.data() == nullptr);
133 assert(operand.getUses().size() == 1 && !operand.getDef().valid());
134 assert(uses_map[ind] == 1 && def_map[ind] == 0);
135 tensor_builder->notifyFirstUse(ind);
136 }
137 }
138
139 for (const auto &ind : op_inputs)
140 {
141 if (external_operands.contains(ind))
142 continue;
143 if (!tensor_builder->isRegistered(ind))
144 continue;
145 assert(uses_map.find(ind) != uses_map.end());
146 assert(uses_map[ind] > 0);
147 uses_map[ind]--;
148 if (uses_map[ind] == 0)
149 {
150 // plan for deallocation of static tensornode
151 tensor_builder->notifyLastUse(ind);
152 }
153 }
154 }
155
156 for (const auto &ind : operands_last_until_end)
157 {
158 tensor_builder->notifyLastUse(ind);
159 }
160
161 // Dispose and validate
162 for (const auto &ind : constants)
163 {
164 --uses_map[ind];
165 if (uses_map[ind] == 0) // To prevent notifyLastUse from being called twice
166 {
167 tensor_builder->notifyLastUse(ind);
168 }
169 }
170
171 assert(
172 std::all_of(uses_map.begin(), uses_map.end(),
173 [](std::pair<const ir::OperandIndex, uint32_t> it) { return it.second == 0; }));
174
175 assert(
176 std::all_of(def_map.begin(), def_map.end(),
177 [](std::pair<const ir::OperandIndex, uint32_t> it) { return it.second == 0; }));
178}
void append(const OperandIndex &index)
volatile const char info[]
std::unordered_map< OperandIndex, T > OperandIndexMap

References onert::ir::OperandIndexSequence::append(), onert::util::Set< Element >::contains(), onert::ir::DUPLICATED, info, and onert::ir::UNDEFINED.

Referenced by genTensors().

◆ register_source_memory_tensors()

template<typename T_TensorBuilder >
util::Set< ir::OperandIndex > onert::backend::basic::register_source_memory_tensors ( const std::shared_ptr< T_TensorBuilder > &  tensor_builder,
const ir::Graph graph,
const util::Set< ir::OperandIndex > &  external_operands,
const ir::OperandIndexMap< ir::OperandIndex > &  shared_memory_operand_idx 
)

Definition at line 181 of file BackendContextHelpers.h.

185{
186 // process source tensors that share memory at first
187 util::Set<ir::OperandIndex> registered_source_ind;
188 for (const auto &[_, source_ind] : shared_memory_operand_idx)
189 {
190 if (external_operands.contains(source_ind))
191 continue;
192 if (tensor_builder->isRegistered(source_ind)) // some tensors can have the same source
193 continue;
194 tensor_builder->registerTensorInfo(source_ind, graph.operands().at(source_ind).info());
195 registered_source_ind.add(source_ind);
196 }
197 return registered_source_ind;
198}
Class for set of custom element &.
Definition Set.h:39
void add(const Element &e)
Add a given element to the set.
Definition Set.h:70

References onert::util::Set< Element >::add(), and onert::util::Set< Element >::contains().

Referenced by genTensors().