ONE - On-device Neural Engine
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 197 of file BackendContextHelpers.h.

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

◆ genTensors() [2/2]

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

Definition at line 234 of file BackendContextHelpers.h.

235{
236 return genTensors(ctx.tensor_builder, *ctx.graph(), ctx.external_operands(), ctx.tensor_registry,
237 ctx.data().op_order, {});
238}
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 296 of file BackendContextHelpers.h.

297{
298 initConsts(ctx.graph()->operands(), ctx.external_operands(), ctx.tensor_registry.get(), {});
299}
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:110
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 266 of file BackendContextHelpers.h.

270{
271 operands.iterate([&](const ir::OperandIndex &ind, const ir::Operand &operand) {
272 if (external_operands.contains(ind) || !operand.isConstant())
273 return;
274 const bool has_const_shared_source =
275 shared_memory_operands_map.find(ind) != std::end(shared_memory_operands_map) &&
276 operands.at(shared_memory_operands_map.at(ind)).isConstant();
277 if (has_const_shared_source)
278 return; // tensors with shared memory are processed in initSharedMemoryConsts
279
280 auto tensor = tensor_registry->getNativeITensor(ind);
281 assert(tensor != nullptr);
282
283 VERBOSE(FillOperandData) << "Fill data for " << ind << std::endl;
284
285 auto data = operand.shareData();
286 assert(data && data->base());
287 ExternalTensor *ext_tensor = dynamic_cast<ExternalTensor *>(tensor);
288
289 if (ext_tensor == nullptr)
290 throw std::runtime_error{"This tensor is not external tensor"};
291
292 ext_tensor->setData(data);
293 });
294}
Class that uses data from external memory that is not managed by a backend instead of allocating and ...
Definition Tensor.h:148
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:166
bool isConstant(void) const
Get true if Operand is const, otherwise false a.
Definition Operand.h:77
std::shared_ptr< Data > shareData(void) const
Definition Operand.h:71
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::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 241 of file BackendContextHelpers.h.

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

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

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

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

Referenced by genTensors().