38ir::OperandInfo createBackwardTensorInfo(
const ir::Operand &operand)
41 return ir::OperandInfo{operand.shape(), operand.typeInfo(), operand.info().memAllocType(),
42 operand.isConstant()};
45void AddBackPropInitializers(
const ir::train::TrainableGraph &tgraph, TensorRegistry &tensor_reg,
48 util::Set<ir::OperandIndex> unvisited;
49 tgraph.operands().iterate([&](
const ir::OperandIndex &index,
const ir::Operand &operand) {
50 if (!tgraph.getInputs().contains(index) && !operand.isConstant())
54 for (
const auto &op_index : tgraph.essentialBackwardOrder())
56 assert(fn_map.find(op_index) != fn_map.end());
58 auto &tn_seq = fn_map.at(op_index);
61 std::vector<BackPropTensor *> back_props;
62 const auto &op = tgraph.operation(op_index);
63 for (
const auto &back_prop_index :
66 assert(op.isRequiredForBackward());
67 if (unvisited.contains(back_prop_index))
69 auto back_prop_tensor = tensor_reg.getBackPropTensor(back_prop_index);
70 assert(back_prop_tensor !=
nullptr);
71 back_props.emplace_back(back_prop_tensor);
72 unvisited.remove(back_prop_index);
75 if (back_props.size() != 0)
77 auto initializer = std::make_unique<ops::BackPropInitializer>(back_props);
78 tn_seq->append(std::move(initializer));
83util::Set<ir::train::TrainingOperandIndex>
84getBackwardTensorList(
const ir::train::TrainableGraph &tgraph,
85 const util::Set<ir::OperandIndex> &external_operands)
87 util::Set<ir::train::TrainingOperandIndex> ret;
90 auto border = tgraph.essentialBackwardOrder();
91 for (
const auto op_index : border)
93 const auto &trainable_op = tgraph.operation(op_index);
94 assert(trainable_op.isRequiredForBackward());
96 for (
const auto &ind :
99 if (external_operands.contains(ind))
104 const auto &training_usedefs = tgraph.trainingUseDefs();
106 const bool not_used = usedefs.getTrainingDefs().empty() && usedefs.getTrainingUses().empty();
110 ret.add(operand_index);
117util::Set<DisposableTensorIndex>
118getDisposableBackPropTensorList(
const ir::train::TrainableGraph &tgraph,
119 const util::Set<ir::OperandIndex> &external_operands)
121 util::Set<DisposableTensorIndex> ret;
123 const auto candidates = getBackwardTensorList(tgraph, external_operands);
124 for (
const auto &backwarding_operand_index : candidates)
126 const auto &operand = tgraph.operands().at(backwarding_operand_index.index());
127 const auto &training_usedefs = tgraph.trainingUseDefs();
128 const auto &usedefs = training_usedefs.at(backwarding_operand_index);
129 const bool is_multiple_defs = usedefs.getTrainingDefs().size() > 1;
130 if (!operand.isConstant() && is_multiple_defs)
131 for (
const auto &def : usedefs.getTrainingDefs())
132 ret.
add(DisposableTensorIndex{def.
index(), backwarding_operand_index.
index()});
141 planForwardTensors();
142 planBackwardTensors();
144 _tensor_builder->allocate();
145 _tensor_builder->allocateBackward();
147 auto fn_map = generateFunctionMap();
156 assert(tensor !=
nullptr);
158 VERBOSE(FillOperandData) <<
"Fill data for " << ind << std::endl;
164 if (trainable_tensor ==
nullptr)
165 throw std::runtime_error{
"This tensor is not trainable tensor"};
184 planLayerScopeTensors(fn_map);
185 _tensor_builder->allocateLayerScope();
190void BackendContext::planForwardTensors()
200 _tensor_builder->registerTensorInfo(index, obj.info());
203 const auto ctx_data =
data();
204 TensorPlanner tensor_planner{*ctx_data->tgraph.get(), ctx_data->external_operands};
205 tensor_planner.planTrainableTensors(_tensor_builder.get());
206 tensor_planner.planNonConstTensors(_tensor_builder.get());
209void BackendContext::planBackwardTensors()
213 auto tensor_builder = _tensor_builder;
216 for (
const auto &operand_index : operand_indices)
221 assert(operand_index.valid());
223 assert(!operand_index.is_forward());
224 const auto &operand = tgraph.operands().at(operand_index.index());
225 tensor_builder->registerBackwardTensorInfo(operand_index.index(),
226 createBackwardTensorInfo(operand));
229 const auto disposable_indices = getDisposableBackPropTensorList(tgraph,
external_operands());
230 for (
const auto &disposable_index : disposable_indices)
232 const auto &operand = tgraph.operands().at(disposable_index.operand_index());
233 tensor_builder->registerDisposableBackwardTensorInfo(disposable_index,
234 createBackwardTensorInfo(operand));
238 const auto ctx_data =
data();
239 TensorPlanner tensor_planner{*ctx_data->tgraph.get(), ctx_data->external_operands};
240 tensor_planner.planGradientTensors(tensor_builder.get());
241 tensor_planner.planBackPropTensors(tensor_builder.get());
242 tensor_planner.planDisposableBackPropTensors(tensor_builder.get());
249 for (
const auto &op_ind :
_tdata->op_order)
252 ret.emplace(op_ind, std::move(fn_seq));
256 const auto &tgraph = *
_tdata->tgraph;
257 auto tensor_reg = nnfw::misc::polymorphic_downcast<TensorRegistry *>(
_tensor_registry.get());
258 AddBackPropInitializers(tgraph, *tensor_reg, ret);
263void BackendContext::planLayerScopeTensors([[maybe_unused]]
const FunctionMap &fn_map)
268 std::optional<LayerScopeTensors> &&tensors) {
269 if (not tensors.has_value())
272 auto ls_tensors = tensors.value();
273 for (
auto i = 0u; i < ls_tensors.size(); ++i)
275 LayerScopeTensorIndex tensor_idx(op_idx, i);
276 _tensor_builder->registerLayerScopeTensor(tensor_idx, ls_tensors[i]);
278 VERBOSE(BackendContext) <<
"(idx:" << tensor_idx <<
") registered" << std::endl;
283 for (
auto &pair : fn_map)
285 const auto &op_idx = pair.first;
286 auto &fn_seq = pair.second;
288 const ir::IOperation *op = &
ops.at(op_idx);
289 const auto trainable_op =
dynamic_cast<const ir::train::TrainableOperation *
>(op);
290 assert(trainable_op !=
nullptr);
292 if (not trainable_op->isRequiredForBackward())
295 VERBOSE(BackendContext) <<
"register layerscope tensor for " << trainable_op->name()
298 fn_seq->iterate([&](exec::train::ITrainableFunction &fn) {
299 register_tensors(op_idx, (&fn)->registerLayerScopeTensors());
303 const auto ctx_data =
data();
304 TensorPlanner tensor_planner{*ctx_data->tgraph.get(), ctx_data->external_operands};
305 tensor_planner.planLayerScopeTensors(_tensor_builder.get());
void fillBuffer(const std::shared_ptr< ir::Data > &data)
std::shared_ptr< KernelGenerator > kernel_gen
FunctionMap gen() override
std::shared_ptr< ITensorRegistry > tensor_registry()
const TrainableContextData * data() const
std::shared_ptr< ITensorRegistry > _tensor_registry
const ir::train::TrainableGraph * trainable_graph() const
const util::Set< ir::OperandIndex > & external_operands() const
std::unique_ptr< TrainableContextData > _tdata
bool isConstant(void) const
Get true if Operand is const, otherwise false a.
std::shared_ptr< Data > shareData(void) const
const Operations & operations() const override
const Operands & operands() const override
void iterate(const std::function< void(const Index &, const Object &)> &fn) const
Iterate over the container with given function.
#define VERBOSE(name, lv)
loco::GraphInputIndex index(const TFPlaceholder *node)
std::unordered_map< ir::OperationIndex, std::unique_ptr< exec::train::TrainableFnSequence > > FunctionMap
TrainingIndex< OperandIndex > TrainingOperandIndex
Type that provides index of operand for training.
::onert::util::Index< uint32_t, OperationIndexTag > OperationIndex
::onert::util::Index< uint32_t, OperandIndexTag > OperandIndex