ONE - On-device Neural Engine
Loading...
Searching...
No Matches
record_minmax::RecordMinMax Class Reference

#include <RecordMinMax.h>

Public Types

enum  DataSetFormat {
  UNKNOWN , RANDOM , H5 , DIRECTORY ,
  LIST_FILE
}
 

Public Member Functions

 RecordMinMax (uint32_t num_threads, std::unique_ptr< MinMaxComputer > &&minmax_computer)
 
 ~RecordMinMax ()=default
 
void initialize (const std::string &input_model_path)
 
void setDataSetFormat (DataSetFormat format)
 
DataSetFormat getDataSetFormat () const
 
void setInputDataPath (const std::string &input_data_path)
 
void profileData ()
 
void profileDataInParallel (const std::string &input_data_path)
 
void saveModel (const std::string &output_model_path)
 

Detailed Description

Definition at line 37 of file RecordMinMax.h.

Member Enumeration Documentation

◆ DataSetFormat

Enumerator
UNKNOWN 
RANDOM 
H5 
DIRECTORY 
LIST_FILE 

Definition at line 40 of file RecordMinMax.h.

Constructor & Destructor Documentation

◆ RecordMinMax()

record_minmax::RecordMinMax::RecordMinMax ( uint32_t  num_threads,
std::unique_ptr< MinMaxComputer > &&  minmax_computer 
)
inlineexplicit

Definition at line 49 of file RecordMinMax.h.

50 : _threads_size(num_threads), _minmax_computer(std::move(minmax_computer))
51 {
52 assert(_threads_size > 0);
53 assert(_minmax_computer != nullptr);
54 }

◆ ~RecordMinMax()

record_minmax::RecordMinMax::~RecordMinMax ( )
default

Member Function Documentation

◆ getDataSetFormat()

DataSetFormat record_minmax::RecordMinMax::getDataSetFormat ( ) const
inline

Definition at line 66 of file RecordMinMax.h.

66{ return _data_set_format; }

Referenced by profileData().

◆ initialize()

void record_minmax::RecordMinMax::initialize ( const std::string &  input_model_path)

Definition at line 75 of file RecordMinMax.cpp.

76{
77 assert(_threads_size > 0);
78
79 luci::ImporterEx importer;
80 _module = importer.importVerifyModule(input_model_path);
81
82 if (_module == nullptr)
83 {
84 throw std::runtime_error("Failed to load '" + input_model_path + "'");
85 }
86
87 // Create and initialize interpreters and observers
88 _interpreters.resize(_threads_size);
89 _observers.resize(_threads_size);
90
91 for (uint32_t thread_idx = 0; thread_idx < _threads_size; ++thread_idx)
92 {
93 auto interpreter = std::make_unique<luci_interpreter::Interpreter>(_module.get());
94 auto observer = std::make_unique<MinMaxObserver>();
95
96 interpreter->attachObserver(observer.get());
97
98 _observers[thread_idx] = std::move(observer);
99 _interpreters[thread_idx] = std::move(interpreter);
100 }
101}
std::unique_ptr< Module > importVerifyModule(const std::string &input_path) const

References luci::ImporterEx::importVerifyModule().

Referenced by entry().

◆ profileData()

void record_minmax::RecordMinMax::profileData ( )

Definition at line 190 of file RecordMinMax.cpp.

191{
192 assert(getDataSetFormat() != DataSetFormat::UNKNOWN); // FIX_CALLER_UNLESS
193
194 const auto input_nodes = loco::input_nodes(_module->graph());
195 for (auto input_node : input_nodes)
196 {
197 const auto *input_cnode = loco::must_cast<const luci::CircleInput *>(input_node);
198 checkInputDimension(input_cnode);
199 }
200
201 const auto num_inputs = input_nodes.size();
202
203 auto iter = createIterator();
204
205 bool check_type_shape = iter->check_type_shape();
206
207 if (not iter->hasNext())
208 throw std::runtime_error("The input data file does not contain any record.");
209
210 uint32_t record_idx = 0;
211 while (iter->hasNext())
212 {
213 const auto &record = iter->next();
214
215 if (num_inputs != record.size())
216 throw std::runtime_error("Wrong number of inputs.");
217
218 std::cout << "Recording " << record_idx << "'th data" << std::endl;
219
220 // Write input data to interpreter
221 for (uint32_t input_idx = 0; input_idx < num_inputs; input_idx++)
222 {
223 const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[input_idx]);
224 assert(input_node->index() == input_idx);
225
226 const auto input_data = record.at(input_idx);
227
228 if (check_type_shape)
229 {
230 // Check the type and the shape of the input data is valid
231 verifyTypeShape(input_node, input_data.dtype, input_data.shape);
232 }
233
234 getInterpreter()->writeInputTensor(input_node, input_data.data.data(),
235 input_data.data.size());
236 }
237
238 getInterpreter()->interpret();
239
240 record_idx++;
241 }
242
243 std::cout << "Recording finished. Number of recorded data: " << record_idx << std::endl;
244
245 _minmax_computer->update_qparam(getObserver()->minMaxData()->getMap());
246}
void index(const loco::GraphInputIndex &index)
void writeInputTensor(const luci::CircleInput *input_node, const void *data, size_t data_size)
DataSetFormat getDataSetFormat() const
void verifyTypeShape(const luci::CircleInput *input_node, const DataType &dtype, const Shape &shape)
list input_data
Definition infer.py:29
std::vector< Node * > input_nodes(const Graph *)
Definition Graph.cpp:71
CircleInput * input_node(loco::Graph *g, const loco::GraphInputIndex &index)
Find a Pull node with a given input index.
void checkInputDimension(const luci::CircleInput *input)
Definition Utils.cpp:29

References record_minmax::checkInputDimension(), getDataSetFormat(), luci::CircleInput::index(), loco::input_nodes(), luci_interpreter::Interpreter::interpret(), UNKNOWN, and luci_interpreter::Interpreter::writeInputTensor().

Referenced by entry().

◆ profileDataInParallel()

void record_minmax::RecordMinMax::profileDataInParallel ( const std::string &  input_data_path)

Definition at line 248 of file RecordMinMax.cpp.

249{
250 LOGGER(l);
251
252 assert(_interpreters.size() == _threads_size);
253 assert(_observers.size() == _threads_size);
254
255 const long h5_file_size = getH5FileSize(input_data_path);
256
257 if (h5_file_size > h5_max_size_bytes)
258 throw std::runtime_error("H5 file size is too large for parallel recording");
259
260 WholeOutput whole_output;
261 try
262 {
263 whole_output = importH5Data(input_data_path);
264 }
265 catch (const std::bad_alloc &e)
266 {
267 throw std::runtime_error("Out of memory during h5 data load.");
268 }
269
270 const auto num_records = whole_output.size();
271 const auto input_nodes = loco::input_nodes(_module->graph());
272
273 // Start parallel part
274 INFO(l) << _threads_size << " concurrent threads are supported." << std::endl;
275
276 const auto run_threads = num_records < _threads_size ? num_records : _threads_size;
277
278 const auto records_batch = static_cast<uint32_t>(num_records / run_threads);
279
280 auto interpret_batch = [&whole_output, &input_nodes](int first_record, int last_record,
282 for (int record_index = first_record; record_index < last_record; ++record_index)
283 {
284 for (uint32_t input_idx = 0; input_idx < input_nodes.size(); input_idx++)
285 {
286 const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[input_idx]);
287
288 const auto &cur_input_data = whole_output[record_index][input_idx];
289 interpreter->writeInputTensor(input_node, cur_input_data.data(), cur_input_data.size());
290 }
291 interpreter->interpret();
292 }
293 };
294
295 std::vector<std::thread> threads;
296 for (uint32_t t = 0; t < run_threads; ++t)
297 {
298 if (t < run_threads - 1)
299 {
300 threads.emplace_back(interpret_batch, records_batch * t, records_batch * (t + 1),
301 _interpreters[t].get());
302 }
303 else
304 {
305 threads.emplace_back(interpret_batch, records_batch * t, num_records, _interpreters[t].get());
306 }
307 }
308
309 for (uint32_t i = 0; i < run_threads; ++i)
310 threads.at(i).join();
311
312 // End parallel part
313
314 // Copy all min, max values to one min/max map
315 MinMaxMap main_min_max_map;
316
317 for (const auto &obs : _observers)
318 {
319 const auto cur_minmax_map = obs->minMaxData()->getMap();
320 for (auto &iter : *cur_minmax_map)
321 {
322 const auto node = iter.first;
323 const auto &minmax = iter.second;
324
325 main_min_max_map.appendMinMaxVector(node, minmax);
326 }
327 }
328
329 std::cout << "Recording finished. Number of recorded data: " << num_records << std::endl;
330
331 _minmax_computer->update_qparam(main_min_max_map.getMap());
332}
#define LOGGER(name)
Definition Log.h:65
#define INFO(name)
Definition Log.h:68
KnobTrait< K >::ValueType get(void)
std::vector< Output > WholeOutput

References record_minmax::MinMaxMap::appendMinMaxVector(), record_minmax::MinMaxMap::getMap(), INFO, loco::input_nodes(), and LOGGER.

Referenced by entry().

◆ saveModel()

void record_minmax::RecordMinMax::saveModel ( const std::string &  output_model_path)

Definition at line 334 of file RecordMinMax.cpp.

335{
336 // Export to output Circle file
337 luci::CircleExporter exporter;
338
339 luci::CircleFileExpContract contract(_module.get(), output_model_path);
340
341 if (!exporter.invoke(&contract))
342 {
343 throw std::runtime_error("Failed to export '" + output_model_path + "'");
344 }
345}
bool invoke(Contract *) const

References luci::CircleExporter::invoke().

Referenced by entry().

◆ setDataSetFormat()

void record_minmax::RecordMinMax::setDataSetFormat ( DataSetFormat  format)
inline

Definition at line 60 of file RecordMinMax.h.

61 {
62 assert(format != DataSetFormat::UNKNOWN); // FIX_CALLER UNLESS
63 _data_set_format = format;
64 }

References UNKNOWN.

Referenced by entry().

◆ setInputDataPath()

void record_minmax::RecordMinMax::setInputDataPath ( const std::string &  input_data_path)
inline

Definition at line 68 of file RecordMinMax.h.

68{ _input_data_path = input_data_path; }

Referenced by entry().


The documentation for this class was generated from the following files: