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

#include <MinMaxObserver.h>

Collaboration diagram for record_minmax::MinMaxObserver:

Public Member Functions

 MinMaxObserver ()
 
void postTensorWrite (const luci::CircleNode *node, const luci_interpreter::Tensor *tensor) override
 
const MinMaxMapminMaxData ()
 
- Public Member Functions inherited from luci_interpreter::ExecutionObserver
virtual ~ExecutionObserver ()
 
virtual void preOperatorExecute (const luci::CircleNode *node)
 
virtual void postOperatorExecute (const luci::CircleNode *node)
 

Detailed Description

Definition at line 60 of file MinMaxObserver.h.

Constructor & Destructor Documentation

◆ MinMaxObserver()

record_minmax::MinMaxObserver::MinMaxObserver ( )
inline

Definition at line 63 of file MinMaxObserver.h.

64 {
65 // Do nothing
66 }

Member Function Documentation

◆ minMaxData()

const MinMaxMap * record_minmax::MinMaxObserver::minMaxData ( )
inline

Definition at line 72 of file MinMaxObserver.h.

72{ return &_minmax_data; }

◆ postTensorWrite()

void record_minmax::MinMaxObserver::postTensorWrite ( const luci::CircleNode node,
const luci_interpreter::Tensor tensor 
)
overridevirtual

Reimplemented from luci_interpreter::ExecutionObserver.

Definition at line 30 of file MinMaxObserver.cpp.

32{
33 // CircleOutput does not produce a tensor
34 assert(node->opcode() != luci::CircleOpcode::CIRCLEOUTPUT);
35
36 // Operators with multiple outputs
37 assert(node->opcode() != luci::CircleOpcode::IF);
38 assert(node->opcode() != luci::CircleOpcode::SPLIT);
39 assert(node->opcode() != luci::CircleOpcode::SPLIT_V);
40 assert(node->opcode() != luci::CircleOpcode::TOPK_V2);
41 assert(node->opcode() != luci::CircleOpcode::UNPACK);
42 assert(node->opcode() != luci::CircleOpcode::WHILE);
43
44 if (node->opcode() == luci::CircleOpcode::CIRCLECONST)
45 {
46 // node is not activation. Do nothing.
47 return;
48 }
49
50 if (node->dtype() == DataType::BOOL)
51 {
52 // Bool type tensor is not quantized
53 return;
54 }
55 if (node->dtype() == DataType::S32)
56 {
57 // Integer type tensor is not quantized
58 return;
59 }
60 if (node->dtype() == DataType::S64)
61 {
62 // Integer type tensor is not quantized
63 return;
64 }
65
66 // Only support recording of float32 values
67 if (tensor->element_type() != DataType::FLOAT32)
68 {
69 // Exceptions that should be processed in backends
70 switch (node->opcode())
71 {
72 case luci::CircleOpcode::CAST:
73 // Cast is quantized only if it converts <type> -> float.
74 // Other cases should be processed in backends.
75 case luci::CircleOpcode::RESHAPE:
76 // Reshape changes only shape of input tensor, efficiently is it a no-op.
77 return;
78 default:
79 throw std::runtime_error("Tensor's data type is not float. " + node->name());
80 }
81 }
82
83 const auto data = tensor->data<float>();
84 const auto num_elements = tensor->shape().num_elements();
85
86 std::vector<float> buf(data, data + num_elements);
87
88 float max = std::numeric_limits<float>::lowest();
89 float min = std::numeric_limits<float>::max();
90
91 bool all_nan = true;
92 for (auto number : buf)
93 {
94 if (isnan(number))
95 continue;
96
97 // TODO use metadata hints to detect such cases
98 if (number == std::numeric_limits<float>::lowest())
99 continue;
100
101 all_nan = false;
102
103 if (number > max)
104 max = number;
105
106 if (number < min)
107 min = number;
108 }
109
110 if (all_nan)
111 throw std::runtime_error("All values are NaN(Not a Number)");
112
113 _minmax_data.recordMinMax(node, min, max);
114}
void recordMinMax(const luci::CircleNode *node, float min, float max)
int number
Definition jpeg2hdf5.py:87
uint32_t num_elements(const Shape &shape)
The number of elements of a feature map of a given shape.
Definition Shape.h:59
NodeName name(void) const
virtual CircleOpcode opcode(void) const =0

References luci::CircleNode::name(), luci::CircleNode::opcode(), and record_minmax::MinMaxMap::recordMinMax().


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