-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[microNPU] Add the infrastructure for lookup table and TANH #9547
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ekalda, mostly minor things
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: missing Parameters
and I think we need spacing for these doc strings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lut_activations = ["TANH", "LUT"] | ||
|
||
if ( | ||
call.op.name == "contrib.ethosu.identity" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a check here to make sure call
is an op
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
* - It can be tvm::Op which corresponds to the primitive operators. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: LUTsOptimizer
and the same for name=LUTsOptimizer
above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Parameters | ||
---------- | ||
func : tvm.relay.function.Function | ||
The function to apply the layout optimization pass to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function to apply the layout optimization pass to. | |
The function to apply the optimization pass for multiple LUTs to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Returns | ||
------- | ||
mod : tvm.IRModule | ||
New module with augmented layouts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New module with augmented layouts. | |
New module with optimized LUTs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -123,6 +124,80 @@ def __call__(self, *args, **kwargs): | |||
pass | |||
|
|||
|
|||
def round_away_zero(f): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we reuse round_away_zero
from util.py
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, can LUT be any other dtype?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to enable eager execution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
a new NPU operator. | ||
Parameters | ||
---------- | ||
call : tvm.relay.expr.Call | ||
The current call node being visited. | ||
Returns | ||
------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 | |
------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
"""Visit relay nodes in the given module. | ||
Parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""Visit relay nodes in the given module. | |
Parameters | |
"""Visit relay nodes in the given module. | |
Parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Thanks @lhutton1 and @NicolaLancellotti for the reviews! :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.