[microNPU] Add the infrastructure for lookup table and TANH#9547
Conversation
| def create_op_with_lut(self, call): | ||
| """Extract the parameters and attributes from the NPU operator and create | ||
| a new operator with LUT. | ||
| ---------- |
There was a problem hiding this comment.
Nit: missing Parameters and I think we need spacing for these doc strings?
| lut_activations = ["TANH", "LUT"] | ||
|
|
||
| if ( | ||
| call.op.name == "contrib.ethosu.identity" |
There was a problem hiding this comment.
Should there be a check here to make sure call is an op?
There was a problem hiding this comment.
From my digging of the code, it looks like tvm.relay.expr.Call always has an op attribute, so the equality check shouldn't fail with an error (but correct me if I'm wrong there)
There was a problem hiding this comment.
I think that while it will always have an op attribute, op may not be a tvm.ir.Op and could, for example, be a Function. See here:
Line 269 in 52edc9a
There was a problem hiding this comment.
Ok yes, I added the op type check :)
|
|
||
| @relay.transform.function_pass(opt_level=1, name="LutOptimizer") | ||
| class LUTsOptimizer(Pass): | ||
| """Register LutOptimizer as a relay pass.""" |
There was a problem hiding this comment.
Nit: LUTsOptimizer and the same for name=LUTsOptimizer above.
| Parameters | ||
| ---------- | ||
| func : tvm.relay.function.Function | ||
| The function to apply the layout optimization pass to. |
There was a problem hiding this comment.
| The function to apply the layout optimization pass to. | |
| The function to apply the optimization pass for multiple LUTs to. |
| Returns | ||
| ------- | ||
| mod : tvm.IRModule | ||
| New module with augmented layouts. |
There was a problem hiding this comment.
| New module with augmented layouts. | |
| New module with optimized LUTs. |
| pass | ||
|
|
||
|
|
||
| def round_away_zero(f): |
There was a problem hiding this comment.
Could we reuse round_away_zero from util.py?
There was a problem hiding this comment.
Ah nice, I didn't know it was there, thanks for pointing this out! Changed it to use the one from util.py
| input_zp = int(dequantize_args[2].data.asnumpy()) | ||
|
|
||
| lut_values = find_tanh_values(input_scale, input_zp, output_scale, output_zp) | ||
| lut = relay.const(lut_values, dtype="uint8") |
There was a problem hiding this comment.
Just curious, can LUT be any other dtype?
There was a problem hiding this comment.
Currently, the values are calculated for an int8 activation and then cast into uint8 due to that can of worms dtype problem in the tir_to_cs_translator.py
There was a problem hiding this comment.
Nice, glad to see a fix for that issue will improve something else :)
| ifm_shape = (1, 55, 55, 3) | ||
|
|
||
| def create_tflite_graph(): | ||
| tf.config.run_functions_eagerly(True) |
There was a problem hiding this comment.
Do we need to enable eager execution?
There was a problem hiding this comment.
No we don't :D Removed it!
| new_args = [ethosu_op.args[n] for n in range(len(ethosu_op.args) - 1)] | ||
| new_args.append(lut) |
There was a problem hiding this comment.
| new_args = [ethosu_op.args[n] for n in range(len(ethosu_op.args) - 1)] | |
| new_args.append(lut) | |
| new_args = ethosu_op.args[:-1] + [lut] |
| a new NPU operator. | ||
| Parameters | ||
| ---------- | ||
| call : tvm.relay.expr.Call | ||
| The current call node being visited. | ||
| Returns | ||
| ------- |
There was a problem hiding this comment.
| a new NPU operator. | |
| Parameters | |
| ---------- | |
| call : tvm.relay.expr.Call | |
| The current call node being visited. | |
| Returns | |
| ------- | |
| a new NPU operator. | |
| Parameters | |
| ---------- | |
| call : tvm.relay.expr.Call | |
| The current call node being visited. | |
| Returns | |
| ------- |
| """Visit relay nodes in the given module. | ||
| Parameters |
There was a problem hiding this comment.
| """Visit relay nodes in the given module. | |
| Parameters | |
| """Visit relay nodes in the given module. | |
| Parameters |
|
Thanks @lhutton1 and @NicolaLancellotti for the reviews! :) |
Some activation functions like TANH and SIGMOID are implemented by calculating the values based on the QNN parameters and recording the values into a lookup table (LUT). This patch adds the LUT functionality alongside with the TANH activation function and the tests. Change-Id: Ibe49759fd02724af869826663ff0babd352e5894
|
Thanks all! |
Some activation functions like TANH and SIGMOID are implemented
by calculating the values based on the QNN parameters and
recording the values into a lookup table (LUT).
This patch adds the LUT functionality alongside with the TANH
activation function and the tests.