46 CircleTensorInfo() =
default;
49 void name(
const std::string &name) { _name = name; }
50 const std::string &name(
void)
const {
return _name; }
53 const circle::TensorType &
dtype(
void)
const {
return _dtype; }
54 void dtype(
const circle::TensorType &dtype) { _dtype =
dtype; }
72 bool is_variable(
void)
const {
return _is_variable; }
73 void is_variable(
bool v) { _is_variable = v; }
78 circle::TensorType _dtype{circle::TensorType_FLOAT32};
86 bool _is_variable =
false;
89class CircleTensorContext
92 CircleTensorContext() =
default;
95 void emplace_back(CircleTensorInfo &ti)
97 assert(_names.find(ti.name()) == _names.end());
98 _tis.emplace_back(ti);
99 _names.insert(ti.name());
101 size_t size(
void)
const {
return _tis.size(); }
102 std::vector<CircleTensorInfo>::iterator
begin(
void) {
return _tis.begin(); }
103 std::vector<CircleTensorInfo>::iterator
end(
void) {
return _tis.end(); }
106 bool exist(
const std::string &name)
const {
return _names.find(name) != _names.end(); }
109 std::vector<CircleTensorInfo> _tis;
110 std::set<std::string> _names;
124void allocateCircleTensorInfo(
CircleNode *node, CircleTensorContext &ctx)
141 INFO(l) <<
"[luci] Tensor for " <<
tensor_name <<
": " << tensor_index << std::endl;
143 CircleTensorInfo tensor_info;
159 ctx.emplace_back(tensor_info);
165 MultiOutputDetector(CircleTensorContext &ctx) : _ctx(ctx) {}
171 assert(outs.size() == count);
173 for (
auto out : outs)
175 auto circle_out = loco::must_cast<luci::CircleNode *>(out);
176 allocateCircleTensorInfo(circle_out, _ctx);
196 if (node->merge_outputs())
198 store_outputs(node, 1);
202 store_outputs(node, 2);
209 store_outputs(node, node->numOutputs());
215 store_outputs(node, node->output_count());
221 store_outputs(node, 2);
227 store_outputs(node, 3);
233 store_outputs(node, uint32_t(node->num_split()));
239 store_outputs(node, uint32_t(node->num_split()));
245 store_outputs(node, 2);
251 store_outputs(node, node->num());
257 store_outputs(node, 2);
263 store_outputs(node, node->output_count());
271 CircleTensorContext &_ctx;
274void allocateCircleTensor(
CircleNode *node, CircleTensorContext &ctx)
277 throw std::runtime_error(
"allocateCIrcleTensor Failed : node is nullptr");
283 return circle_node->accept(&d);
298 MultiOutputDetector d(ctx);
299 if (circle_node->accept(&d))
303 allocateCircleTensorInfo(node, ctx);
314 assert(shape.
_rank_known &&
"unknown number of dimensions is not supported");
316 std::vector<int32_t> encoded_shape;
317 encoded_shape.resize(shape.
_dims.size());
318 for (uint32_t i = 0; i < shape.
_dims.size(); ++i)
319 encoded_shape.at(i) = shape.
_dims.at(i) == -1 ? 1 : shape.
_dims.at(i);
327 assert(shape.
_rank_known &&
"unknown number of dimensions is not supported");
330 for (uint32_t i = 0; i < shape.
_dims.size(); ++i)
331 if (shape.
_dims.at(i) == -1)
339 return CreateBuffer(builder);
342template <
typename NodeT>
346 return CreateBuffer(builder);
349template <loco::DataType DT>
355 std::vector<NativeType> raw_data;
356 const uint32_t
size = c->
size<DT>();
357 raw_data.reserve(
size);
358 for (uint32_t i = 0; i <
size; ++i)
360 raw_data.push_back(c->
at<DT>(i));
362 const size_t raw_size =
size *
sizeof(NativeType);
368 buffer_data.resize(raw_size);
369 std::memcpy(buffer_data.data(), raw_data.data(), raw_size);
371 int32_t buffer_index = md.
_buffers.size();
375 return circle::CreateBuffer(builder, 0 , 1 , 1 );
383 auto array_offset = builder.
CreateVector(
reinterpret_cast<uint8_t *
>(raw_data.data()), raw_size);
384 return CreateBuffer(builder, array_offset);
392 const uint32_t count = c->
size<loco::DataType::STRING>();
393 uint32_t raw_size =
sizeof(int32_t) * (count + 2);
394 for (uint32_t i = 0; i < count; ++i)
396 auto &value = c->
at<loco::DataType::STRING>(i);
397 raw_size += value.length();
404 std::vector<uint8_t> raw_data;
405 raw_data.reserve(raw_size);
407 auto *i32d =
reinterpret_cast<int32_t *
>(raw_data.data());
408 int32_t start =
sizeof(int32_t) * (count + 2);
410 std::vector<int32_t> offsets;
414 offsets.push_back(start);
415 for (uint32_t i = 0; i < count; ++i)
417 auto &value = c->
at<loco::DataType::STRING>(i);
420 offsets.push_back(
offset);
423 auto *
data =
reinterpret_cast<uint8_t *
>(i32d);
424 for (uint32_t i = 0; i < count; ++i)
426 int32_t length = offsets[i + 1] - offsets[i];
427 auto &value = c->
at<loco::DataType::STRING>(i);
428 memcpy(
data, value.c_str(), length);
432 auto array_offset = builder.
CreateVector(
reinterpret_cast<uint8_t *
>(raw_data.data()), raw_size);
433 return CreateBuffer(builder, array_offset);
436template <loco::DataType DT>
440 const uint32_t
size = c->
size<DT>();
441 const uint32_t raw_size = (
size + 1) / 2;
442 std::vector<uint8_t> raw_data(raw_size);
444 for (uint32_t i = 0; i < raw_size; ++i)
446 uint32_t sidx = i * 2;
447 uint8_t
data =
static_cast<uint8_t
>(c->
at<DT>(sidx));
448 raw_data[i] =
data & 0x0f;
452 data =
static_cast<uint8_t
>(c->
at<DT>(sidx));
453 raw_data[i] |=
data << 4;
457 auto array_offset = builder.
CreateVector(raw_data.data(), raw_size);
458 return CreateBuffer(builder, array_offset);
467 case loco::DataType::FLOAT32:
468 return encodeOpBufferByDType<loco::DataType::FLOAT32>(builder, md, c);
469 case loco::DataType::S4:
470 return encodeOpBufferPack4bit<loco::DataType::S4>(builder, md, c);
471 case loco::DataType::S8:
472 return encodeOpBufferByDType<loco::DataType::S8>(builder, md, c);
473 case loco::DataType::S16:
474 return encodeOpBufferByDType<loco::DataType::S16>(builder, md, c);
475 case loco::DataType::S32:
476 return encodeOpBufferByDType<loco::DataType::S32>(builder, md, c);
477 case loco::DataType::S64:
478 return encodeOpBufferByDType<loco::DataType::S64>(builder, md, c);
479 case loco::DataType::U4:
480 return encodeOpBufferPack4bit<loco::DataType::U4>(builder, md, c);
481 case loco::DataType::U8:
482 return encodeOpBufferByDType<loco::DataType::U8>(builder, md, c);
483 case loco::DataType::BOOL:
484 return encodeOpBufferByDType<loco::DataType::BOOL>(builder, md, c);
485 case loco::DataType::STRING:
486 return encodeOpBufferByDType<loco::DataType::STRING>(builder, md, c);
503 if (quantparam ==
nullptr)
510 if (quantparam->
min.size() && quantparam->
max.size())
515 if (quantparam->
scale.size() && quantparam->
zerop.size())
521 return circle::CreateQuantizationParameters(builder, min, max, scale, zero_point,
522 circle::QuantizationDetails::QuantizationDetails_NONE,
529 if (sparsityparam ==
nullptr)
532 std::vector<flatbuffers::Offset<circle::DimensionMetadata>> dim_metadata_vec;
534 for (
const auto &it : luci_dim_metadata)
538 auto circle_array_segments_type =
544 auto dim_metadata = circle::CreateDimensionMetadata(
546 circle_array_segments, circle_array_indices_type, circle_array_indices);
547 dim_metadata_vec.emplace_back(dim_metadata);
550 return circle::CreateSparsityParametersDirect(builder, &sparsityparam->
traversal_order,
551 &sparsityparam->
block_map, &dim_metadata_vec);
556 assert(lhs->dtype() == DT);
557 assert(rhs->dtype() == DT);
558 assert(lhs->
size<DT>() == rhs->
size<DT>());
560 for (uint32_t i = 0; i < lhs->
size<DT>(); ++i)
561 if (lhs->
at<DT>(i) != rhs->
at<DT>(i))
568 if (lhs->dtype() != rhs->dtype())
571 if (lhs->rank() != rhs->rank())
574 for (uint32_t i = 0; i < lhs->rank(); ++i)
575 if (!(lhs->dim(i) == rhs->dim(i)))
578 switch (lhs->dtype())
580 case loco::DataType::FLOAT32:
581 return has_same_elements<loco::DataType::FLOAT32>(lhs, rhs);
583 case loco::DataType::S4:
584 return has_same_elements<loco::DataType::S4>(lhs, rhs);
586 case loco::DataType::S8:
587 return has_same_elements<loco::DataType::S8>(lhs, rhs);
589 case loco::DataType::S16:
590 return has_same_elements<loco::DataType::S16>(lhs, rhs);
592 case loco::DataType::S32:
593 return has_same_elements<loco::DataType::S32>(lhs, rhs);
595 case loco::DataType::S64:
596 return has_same_elements<loco::DataType::S64>(lhs, rhs);
598 case loco::DataType::U4:
599 return has_same_elements<loco::DataType::U4>(lhs, rhs);
601 case loco::DataType::U8:
602 return has_same_elements<loco::DataType::U8>(lhs, rhs);
604 case loco::DataType::BOOL:
605 return has_same_elements<loco::DataType::BOOL>(lhs, rhs);
619 for (
auto key_value : md._cached_buffer_id)
621 if (has_same_values(key_value.first, node))
622 return key_value.second;
626 auto buffer = encodeOpBuffer(builder, md, node);
628 auto buffer_id =
static_cast<uint32_t
>(md.
_buffers.size());
640 auto buffer = encodeOpBuffer(builder);
642 auto buffer_id =
static_cast<uint32_t
>(md.
_buffers.size());
655 if (
info.shape_status() == ShapeStatus::VALID)
657 shape_offset = encodeShape(builder,
info.shape());
658 shape_signature_offset = encodeShapeSignature(builder,
info.shape());
661 auto quantparam = encodeQuantizationParameters(builder,
info.quantparam());
663 auto sparsityparam = encodeSparsityParameters(builder,
info.sparsityparam());
665 auto buffer_id = get_buffer_id(builder, md,
info.content());
669 auto is_variable =
info.is_variable();
671 auto tensor_offset = CreateTensor(builder, shape_offset,
info.dtype(), buffer_id, name_offset,
672 quantparam, is_variable, sparsityparam, shape_signature_offset);
673 gd.
_tensors.push_back(tensor_offset);
698 CircleTensorContext tensor_ctx;
702 auto nodes = g->nodes();
703 for (uint32_t n = 0; n < nodes->size(); ++n)
707 allocateCircleTensor(node, tensor_ctx);
712 CircleNode *circle_node = loco::must_cast<luci::CircleNode *>(node);
715 allocateCircleTensor(circle_node, tensor_ctx);
718 for (
const auto &tensor_info : tensor_ctx)
720 exportOpDefinedTensor(tensor_info, builder, md, gd);
726 auto nodes = g->nodes();
727 for (uint32_t n = 0; n < nodes->size(); ++n)
729 auto node = loco::must_cast<luci::CircleNode *>(nodes->at(n));
#define INTERNAL_EXN_V(msg, val)
@ brief throw internal exception with message and value
Helper class to hold data needed in creation of a FlatBuffer. To serialize data, you typically call o...
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Logical unit of computation.
BIDIRECTIONAL_SEQUENCE_LSTM in Circle.
Virtual CIRCLEBIDIRECTIONAL_SEQUENCE_LSTM_OUT in Circle.
Class to build tensor data.
const loco::DataTypeImpl< DT >::Type & at(uint32_t n) const
uint32_t size(void) const
Virtual CIRCLECUSTOMOUT in Circle.
Virtual CIRCLEIFOUT in Circle.
NON_MAX_SUPPRESSION_V4 in Circle.
Virtual NONMAXSUPPRESSIONV4OUT in Circle.
NON_MAX_SUPPRESSION_V5 in Circle.
Virtual NONMAXSUPPRESSIONV5OUT in Circle.
CircleOutputExclude is used to specifying not exported nodes.
CircleNode for Output of the Graph.
Virtual CIRCLESPLITOUT in Circle.
Virtual CIRCLESPLITVOUT in Circle.
Virtual CIRCLETOPKV2OUT in Circle.
Virtual CIRCLEUNIQUEOUT in Circle.
Virtual CIRCLEUNPACKOUT in Circle.
Virtual CircleVariable in Circle for 'variable' Tensor.
Virtual CIRCLEWHILEOUT in Circle.
__global uchar * offset(const Image *img, int x, int y)
volatile const char info[]
void exportOpDefinedTensor(const TFLTensorInfo &info, FlatBufferBuilder &builder, SerializedModelData &gd)
const T * data(const std::vector< T, Alloc > &v)
std::vector< loco::Node * > postorder_traversal(const std::vector< loco::Node * > &roots)
Generate postorder traversal sequence starting from "roots".
std::set< Node * > succs(const Node *node)
Enumerate all the successors of a given node.
std::vector< Node * > output_nodes(Graph *)
flatbuffers::Offset< void > to_circle_sparse_index_vector(flatbuffers::FlatBufferBuilder &fb, const SparseIndexVector &sparse_idx_vec)
bool check_size_limit(const flatbuffers::FlatBufferBuilder &fb, const uint64_t data_size)
void set_tensor_index(loco::Node *node, const CircleTensorIndex &tensor_id)
ShapeDescription to_shape_description(const luci::CircleNode *node)
circle::DimensionType to_circle_dimensiontype(luci::DimensionType type)
const char * tensor_name(const circle::Tensor *tensor)
circle::SparseIndexVector to_circle_sparse_index_vector_type(luci::SparseIndexVectorType type)
int32_t CircleTensorIndex
circle::TensorType to_circle_tensortype(loco::DataType type)
void exportOpDefinedTensors(loco::Graph *g, FlatBufferBuilder &builder, SerializedModelData &md, SerializedGraphData &gd)
create Tensors corresponding to results of all nodes in graph
void clear_tensor_index(loco::Node *node)
void prepareModelData(FlatBufferBuilder &builder, SerializedModelData &md)
one time preparation for SerializedModelData
void clearExportInfo(loco::Graph *g)
clear temporary export information annotated to graph nodes
ShapeStatus
ShapeStatus is to remember circle node shape status.
ShapeIterator end(const Shape &s)
C++ scalar type corresponding to each DataType.
CircleQuantParam * quantparam(void) const
SparsityParam * sparsityparam(void) const
NodeName name(void) const
ShapeStatus shape_status(void) const
virtual T visit(CircleNode *)
Default fallback.
std::vector< float > scale
int32_t quantized_dimension
std::vector< int64_t > zerop
std::vector< flatbuffers::Offset< circle::Tensor > > _tensors
std::map< luci::CircleConst *, uint32_t > _cached_buffer_id
flatbuffers::Offset< circle::Buffer > _empty_buffer
std::vector< flatbuffers::Offset< circle::Buffer > > _buffers
MapBufferData _buffer_data_map
std::vector< uint8_t > BufferData
std::vector< int32_t > _dims
std::vector< DimMetaData > dim_metadata
std::vector< int32_t > block_map
std::vector< int32_t > traversal_order