19#include <mio_circle/Reader.h>
36 for (
auto iter = vec->
begin(); iter != vec->
end(); iter++)
38 if (iter != vec->
begin())
45 const circle::TensorType &type)
47 if (data_ptr ==
nullptr)
50 os <<
" └── buffer" << std::endl;
51 os <<
" ├── index : " << buff_idx << std::endl;
52 size_t buff_size = data_ptr->
size();
53 os <<
" ├── size : " << buff_size << std::endl;
57 case circle::TensorType_UINT8:
59 const uint8_t *buff_data_ui8 =
reinterpret_cast<const uint8_t *
>(data_ptr->
data());
60 for (uint32_t idx = 0; idx < buff_size /
sizeof(uint8_t); idx++)
62 os << static_cast<const uint32_t>(buff_data_ui8[idx]) <<
", ";
66 case circle::TensorType_INT32:
68 const int32_t *buff_data_i32 =
reinterpret_cast<const int32_t *
>(data_ptr->
data());
69 for (uint32_t idx = 0; idx < buff_size /
sizeof(int32_t); idx++)
71 os << buff_data_i32[idx] <<
", ";
75 case circle::TensorType_INT64:
77 const int64_t *buff_data_i64 =
reinterpret_cast<const int64_t *
>(data_ptr->
data());
78 for (uint32_t idx = 0; idx < buff_size /
sizeof(int64_t); idx++)
80 os << buff_data_i64[idx] <<
", ";
84 case circle::TensorType_FLOAT32:
86 const float *buff_data_f32 =
reinterpret_cast<const float *
>(data_ptr->
data());
87 for (uint32_t idx = 0; idx < buff_size /
sizeof(float); idx++)
89 os << buff_data_f32[idx] <<
", ";
94 throw std::runtime_error(
"NYI tensor type : " + std::to_string(type));
108 auto buffers = reader.
buffers();
110 for (uint32_t subgraph_idx = 0; subgraph_idx < num_subgraph; subgraph_idx++)
114 auto tensors = reader.
tensors();
115 for (
const auto &tensor : *tensors)
117 const auto tensor_name = tensor->name();
118 std::string tensor_name_str = tensor_name ? tensor_name->str() :
"no_name";
119 os << std::string(70,
'-') << std::endl;
120 os <<
"[" << tensor_name_str <<
"]" << std::endl;
121 auto buff_idx = tensor->buffer();
122 auto buff_data_ptr = reader.
buffers()->
Get(buff_idx)->data();
123 auto quant_param = tensor->quantization();
124 std::string print_format = (!buff_data_ptr && !quant_param) ?
"└──" :
"├──";
127 auto shape = tensor->shape();
128 os <<
" " + print_format +
" shape : (";
129 ::print_comma_sepearted(os, shape);
130 os <<
")" << std::endl;
135 std::string print_format1 = buff_data_ptr ?
"├──" :
"└──";
136 std::string print_format2 = buff_data_ptr ?
"│" :
" ";
137 os <<
" " + print_format1 +
" quantization" << std::endl;
138 auto min = quant_param->min();
139 auto max = quant_param->max();
140 auto scale = quant_param->scale();
141 auto zero_point = quant_param->zero_point();
142 auto quantized_dimension = quant_param->quantized_dimension();
144 os <<
" " + print_format2 +
" ├── min : ";
145 ::print_comma_sepearted(os, min);
147 os <<
" " + print_format2 +
" ├── max : ";
148 ::print_comma_sepearted(os, max);
150 os <<
" " + print_format2 +
" ├── scale : ";
151 ::print_comma_sepearted(os, scale);
153 os <<
" " + print_format2 +
" ├── zero_point : ";
154 ::print_comma_sepearted(os, zero_point);
156 os <<
" " + print_format2 +
" └── quantized_dimension : " << quantized_dimension;
161 print_buffer(os, buff_idx, buff_data_ptr, tensor->type());
173std::string
mangle(
const std::string &name)
175 std::string ret{name};
176 std::replace(ret.begin(), ret.end(),
'/',
'_');
180H5::PredType hdf5_dtype_cast(
const circle::TensorType &circle_type)
184 case circle::TensorType_UINT8:
186 return H5::PredType::NATIVE_UINT8;
188 case circle::TensorType_INT8:
190 return H5::PredType::NATIVE_INT8;
192 case circle::TensorType_INT16:
194 return H5::PredType::NATIVE_INT16;
196 case circle::TensorType_INT32:
198 return H5::PredType::NATIVE_INT32;
200 case circle::TensorType_INT64:
202 return H5::PredType::NATIVE_INT64;
204 case circle::TensorType_FLOAT32:
206 return H5::PredType::NATIVE_FLOAT;
209 throw std::runtime_error(
"NYI tensor type : " + std::to_string(circle_type));
224 std::vector<hsize_t> ret;
230 ret.at(0) =
data->size();
234 const uint32_t rank = dims->size();
236 for (uint32_t d = 0; d < rank; d++)
238 if (dims->Get(d) < 0)
239 throw std::runtime_error(
"Dimensions shouldn't be negative");
240 ret.at(d) =
static_cast<hsize_t
>(dims->Get(d));
257void write_vector_data_to_hdf5(H5::H5File &file, std::string &group_name, std::string dataset_name,
259 std::vector<hsize_t> dims)
263 auto dataspace = std::make_unique<H5::DataSpace>(dims.size(), dims.data());
264 auto dataset = std::make_unique<H5::DataSet>(
265 file.createDataSet(group_name +
"/" + dataset_name, type, *dataspace));
266 dataset->write(
data->data(), type);
271void write_scalar_data_to_hdf5(H5::H5File &file, std::string &group_name, std::string dataset_name,
272 const H5::PredType &type, T data)
274 auto dataspace = std::make_unique<H5::DataSpace>(H5S_SCALAR);
275 auto dataset = std::make_unique<H5::DataSet>(
276 file.createDataSet(group_name +
"/" + dataset_name, type, *dataspace));
277 dataset->write(&data, type);
301 const std::string &output_path)
308 H5::H5File file{output_path, H5F_ACC_TRUNC};
310 for (uint32_t subgraph_idx = 0; subgraph_idx < num_subgraph; subgraph_idx++)
314 auto tensors = reader.
tensors();
315 for (
const auto &tensor : *tensors)
318 const auto tensor_name = tensor->name();
319 if (tensor_name ==
nullptr)
321 assert(
false &&
"There is no tensor name");
326 std::string group_name =
::mangle(tensor_name->c_str());
327 std::unique_ptr<H5::Group> tensor_group =
328 std::make_unique<H5::Group>(file.createGroup(group_name));
331 uint32_t buff_idx = tensor->buffer();
332 auto buff_data_ptr = reader.
buffers()->
Get(buff_idx)->data();
335 ::write_vector_data_to_hdf5(file, group_name,
"weights", ::hdf5_dtype_cast(tensor->type()),
337 ::hdf5_dims_cast(buff_data_ptr, tensor->shape()));
341 auto quant_param = tensor->quantization();
344 auto min = quant_param->min();
345 ::write_vector_data_to_hdf5(file, group_name,
"min", H5::PredType::NATIVE_FLOAT, min,
346 ::hdf5_dims_cast(min));
347 auto max = quant_param->max();
348 ::write_vector_data_to_hdf5(file, group_name,
"max", H5::PredType::NATIVE_FLOAT, max,
349 ::hdf5_dims_cast(max));
350 auto scale = quant_param->scale();
351 ::write_vector_data_to_hdf5(file, group_name,
"scale", H5::PredType::NATIVE_FLOAT, scale,
352 ::hdf5_dims_cast(scale));
353 auto zero_point = quant_param->zero_point();
354 ::write_vector_data_to_hdf5(file, group_name,
"zero_point", H5::PredType::NATIVE_INT64,
355 zero_point, ::hdf5_dims_cast(zero_point));
356 auto quantized_dimension = quant_param->quantized_dimension();
357 ::write_scalar_data_to_hdf5(file, group_name,
"quantized_dimension",
358 H5::PredType::NATIVE_INT32, quantized_dimension);
void run(std::ostream &os, const circle::Model *model, const std::string &) override
void run(std::ostream &os, const circle::Model *model, const std::string &output_path) override
return_type Get(uoffset_t i) const
Loads Circle file and provides helpers to access attributes.
const CircleTensors_t * tensors()
uint32_t num_subgraph() const
const CircleBuffers_t * buffers()
bool select_subgraph(uint32_t subgraph)
std::string mangle(const std::string &name)
Construct HDF5-compatible dataset name from a given string.