34ir::OperandInfo createBackwardTensorInfo(
const ir::Operand &operand)
37 return ir::OperandInfo{operand.shape(), operand.typeInfo(), operand.info().memAllocType(),
38 operand.isConstant()};
41void AddBackPropInitializers(
const ir::train::TrainableGraph &tgraph, TensorRegistry &tensor_reg,
44 util::Set<ir::OperandIndex> unvisited;
45 tgraph.operands().iterate([&](
const ir::OperandIndex &index,
const ir::Operand &operand) {
46 if (!tgraph.getInputs().contains(index) && !operand.isConstant())
50 for (
const auto &op_index : tgraph.essentialBackwardOrder())
52 assert(fn_map.find(op_index) != fn_map.end());
54 auto &tn_seq = fn_map.at(op_index);
57 std::vector<BackPropTensor *> back_props;
58 const auto &op = tgraph.operation(op_index);
59 for (
const auto &back_prop_index :
62 assert(op.isRequiredForBackward());
63 if (unvisited.contains(back_prop_index))
65 auto back_prop_tensor = tensor_reg.getBackPropTensor(back_prop_index);
66 assert(back_prop_tensor !=
nullptr);
67 back_props.emplace_back(back_prop_tensor);
68 unvisited.remove(back_prop_index);
71 if (back_props.size() != 0)
73 auto initializer = std::make_unique<ops::BackPropInitializer>(back_props);
74 tn_seq->append(std::move(initializer));
79util::Set<ir::train::TrainingOperandIndex>
80getBackwardTensorList(
const ir::train::TrainableGraph &tgraph,
81 const util::Set<ir::OperandIndex> &external_operands)
83 util::Set<ir::train::TrainingOperandIndex> ret;
86 auto border = tgraph.essentialBackwardOrder();
87 for (
const auto op_index : border)
89 const auto &trainable_op = tgraph.operation(op_index);
90 assert(trainable_op.isRequiredForBackward());
92 for (
const auto &ind :
95 if (external_operands.contains(ind))
100 const auto &training_usedefs = tgraph.trainingUseDefs();
102 const bool not_used = usedefs.getTrainingDefs().empty() && usedefs.getTrainingUses().empty();
106 ret.add(operand_index);
113util::Set<DisposableTensorIndex>
114getDisposableBackPropTensorList(
const ir::train::TrainableGraph &tgraph,
115 const util::Set<ir::OperandIndex> &external_operands)
117 util::Set<DisposableTensorIndex> ret;
119 const auto candidates = getBackwardTensorList(tgraph, external_operands);
120 for (
const auto &backwarding_operand_index : candidates)
122 const auto &operand = tgraph.operands().at(backwarding_operand_index.index());
123 const auto &training_usedefs = tgraph.trainingUseDefs();
124 const auto &usedefs = training_usedefs.at(backwarding_operand_index);
125 const bool is_multiple_defs = usedefs.getTrainingDefs().size() > 1;
126 if (!operand.isConstant() && is_multiple_defs)
127 for (
const auto &def : usedefs.getTrainingDefs())
128 ret.
add(DisposableTensorIndex{def.
index(), backwarding_operand_index.
index()});
137 planForwardTensors();
138 planBackwardTensors();
140 _tensor_builder->allocate();
141 _tensor_builder->allocateBackward();
143 auto fn_map = generateFunctionMap();
152 assert(tensor !=
nullptr);
154 VERBOSE(FillOperandData) <<
"Fill data for " << ind << std::endl;
160 if (trainable_tensor ==
nullptr)
161 throw std::runtime_error{
"This tensor is not trainable tensor"};
180 planLayerScopeTensors(fn_map);
181 _tensor_builder->allocateLayerScope();
186void BackendContext::planForwardTensors()
196 _tensor_builder->registerTensorInfo(index, obj.info());
199 const auto ctx_data =
data();
200 TensorPlanner tensor_planner{*ctx_data->tgraph.get(), ctx_data->external_operands};
201 tensor_planner.planTrainableTensors(_tensor_builder.get());
202 tensor_planner.planNonConstTensors(_tensor_builder.get());
205void BackendContext::planBackwardTensors()
209 auto tensor_builder = _tensor_builder;
212 for (
const auto &operand_index : operand_indices)
217 assert(operand_index.valid());
219 assert(!operand_index.is_forward());
220 const auto &operand = tgraph.operands().at(operand_index.index());
221 tensor_builder->registerBackwardTensorInfo(operand_index.index(),
222 createBackwardTensorInfo(operand));
225 const auto disposable_indices = getDisposableBackPropTensorList(tgraph,
external_operands());
226 for (
const auto &disposable_index : disposable_indices)
228 const auto &operand = tgraph.operands().at(disposable_index.operand_index());
229 tensor_builder->registerDisposableBackwardTensorInfo(disposable_index,
230 createBackwardTensorInfo(operand));
234 const auto ctx_data =
data();
235 TensorPlanner tensor_planner{*ctx_data->tgraph.get(), ctx_data->external_operands};
236 tensor_planner.planGradientTensors(tensor_builder.get());
237 tensor_planner.planBackPropTensors(tensor_builder.get());
238 tensor_planner.planDisposableBackPropTensors(tensor_builder.get());
245 for (
const auto &op_ind :
_tdata->op_order)
248 ret.emplace(op_ind, std::move(fn_seq));
252 const auto &tgraph = *
_tdata->tgraph;
253 auto tensor_reg = nnfw::misc::polymorphic_downcast<TensorRegistry *>(
_tensor_registry.get());
254 AddBackPropInitializers(tgraph, *tensor_reg, ret);
259void BackendContext::planLayerScopeTensors([[maybe_unused]]
const FunctionMap &fn_map)
264 std::optional<LayerScopeTensors> &&tensors) {
265 if (not tensors.has_value())
268 auto ls_tensors = tensors.value();
269 for (
auto i = 0u; i < ls_tensors.size(); ++i)
271 LayerScopeTensorIndex tensor_idx(op_idx, i);
272 _tensor_builder->registerLayerScopeTensor(tensor_idx, ls_tensors[i]);
274 VERBOSE(BackendContext) <<
"(idx:" << tensor_idx <<
") registered" << std::endl;
279 for (
auto &pair : fn_map)
281 const auto &op_idx = pair.first;
282 auto &fn_seq = pair.second;
284 const ir::IOperation *op = &
ops.at(op_idx);
285 const auto trainable_op =
dynamic_cast<const ir::train::TrainableOperation *
>(op);
286 assert(trainable_op !=
nullptr);
288 if (not trainable_op->isRequiredForBackward())
291 VERBOSE(BackendContext) <<
"register layerscope tensor for " << trainable_op->name()
294 fn_seq->iterate([&](exec::train::ITrainableFunction &fn) {
295 register_tensors(op_idx, (&fn)->registerLayerScopeTensors());
299 const auto ctx_data =
data();
300 TensorPlanner tensor_planner{*ctx_data->tgraph.get(), ctx_data->external_operands};
301 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