-
Notifications
You must be signed in to change notification settings - Fork 172
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
Adapt the convertor to tensorrt backend #47
Conversation
onnx_graph = helper.make_graph( | ||
nodes=onnx_nodes, | ||
name=model_name, | ||
initializer=weights, |
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.
TensorRT backend distinguishes weights and tensors, so we have to use initializer
to initialize 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.
Great - so this is consistent with our original plan to add the initializer
in at some point! Very happy to see this
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.
This also solves some problems we are having when trying to use other ONNX convertors
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 have to initialize the tmp
inputs and outputs to the ops too? @nickyfantasy is having issues converting the model to the qualcomm DLC spec
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.
Yeah. initializer
is the officially recommended to initialize parameters, and the issues under onnx/models
show that they may deprecate the Constant op initialization someday.
It should not be the proper way to initialize the tmp
inputs and outputs to the ops. Let's figure out what happened here after Qualcomm prepare related 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.
@kuke I think @nickyfantasy found out why that issue was happening. you are right, it isn't the right way to initialize tmp
inputs/outputs, so we are good.
fluid_onnx/ops.py
Outdated
outputs=outputs['Out'], | ||
scale=1.0 - attrs['dropout_prob']) | ||
return (dropout_op, scale_op) | ||
if __onnx_ver__ == '1.0.1': |
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.
TensorRT doesn't support Scale
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.
Is there a way we could use a version range or max / min comparison instead of hardcoding a specific version? And in the last possible resort where we were going to, perhaps make it a constant at the top?
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 wish I understood what this means fully: "note that our implementation of Dropout does scaling in the training phase", but do we still need to scale given this context
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.
How about we temporarily fix the version number to 1.0.1 right now? because there are several releases, and I have not checked the changes in the definition of operators.
You got the point. Yes, we need to scale the output of Dropout op, otherwise inference wouldn't get right result.
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.
@kuke Okay, no worries, but we would probably need to come back to this, as it will bite as we try to make our ONNX models compatible for various backends.
fluid_onnx/ops.py
Outdated
inputs=inputs['Y'], | ||
outputs=y_flat_out, | ||
axis=attrs['y_num_col_dims']) | ||
if __onnx_ver__ == '1.0.1': |
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 input dim of Flatten
op is limited to equal to 3.
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.
This would be awesome as a comment in the code :)
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
fluid_onnx/ops.py
Outdated
output_node = make_node( | ||
'Reshape', | ||
inputs=matmul_out, | ||
shape=out_shape, |
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.
shape
is an attribute in onnx v1.0.1
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.
Same as above, code comment
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
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 its fair to update the pip requirements file also to 1.0.1.
onnx_graph = helper.make_graph( | ||
nodes=onnx_nodes, | ||
name=model_name, | ||
initializer=weights, |
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.
Great - so this is consistent with our original plan to add the initializer
in at some point! Very happy to see this
onnx_graph = helper.make_graph( | ||
nodes=onnx_nodes, | ||
name=model_name, | ||
initializer=weights, |
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.
This also solves some problems we are having when trying to use other ONNX convertors
@@ -68,13 +72,6 @@ def activation_ops(act_type, operator, block): | |||
act_type, inputs=inputs.values()[0], outputs=outputs.values()[0]) | |||
|
|||
|
|||
def and_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.
Is there a reason for removing this placeholder function?
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.
Oh nvm I realize this is merged into the elementwise
stuff
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.
Yes. It is no longer needed.
fluid_onnx/ops.py
Outdated
@@ -87,36 +84,52 @@ def batch_norm_op(operator, block): | |||
inputs, attrs, outputs = op_io_info(operator) | |||
|
|||
x_shape = block.vars[get_old_name(inputs['X'][0])].shape | |||
reshape_node = None | |||
nodes = () | |||
if len(x_shape) == 2: |
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 couple of us are stuck on why we do it this way. Then using a constant-less version for v1.0.1. Would love if you could add in some comments here - mostly for educating us.
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.
Added the comment about why we need reshape here. And why didn't use Constant
op in branch 1.0.1
? the answer is that in onnx1.0.1 shape is used as an attribute and doesn't need a constant op to feed value.
fluid_onnx/ops.py
Outdated
'momentum': attrs['momentum'] | ||
} | ||
if __onnx_ver__ == u'1.0.1': | ||
kwargs['consumed_inputs'] = [0, 0, 0, 1, 1] |
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.
How did you figure the value of this out? Any reference to papers / code?
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 docs found. If don't set the consumed_inputs
, ONNX will give an error
onnx.onnx_cpp2py_export.checker.ValidationError: Input index 3 must be set to consumed for operator BatchNormalization
So I looked into the code in ONNX 1.0.1, finally find this attribute and its proper usage.
fluid_to_onnx.py
Outdated
onnx_nodes.append(param_node) | ||
weight, val_info = paddle_onnx_weight( | ||
var=var, scope=inference_scope) | ||
weights.append(weight), weights_value_info.append(val_info) |
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.
👍
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.
Oh just do the two appends over two lines, so this doesn't confuse anyone
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
onnx_graph = helper.make_graph( | ||
nodes=onnx_nodes, | ||
name=model_name, | ||
initializer=weights, |
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 have to initialize the tmp
inputs and outputs to the ops too? @nickyfantasy is having issues converting the model to the qualcomm DLC spec
fluid_onnx/ops.py
Outdated
inputs=inputs['Y'], | ||
outputs=y_flat_out, | ||
axis=attrs['y_num_col_dims']) | ||
if __onnx_ver__ == '1.0.1': |
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.
This would be awesome as a comment in the code :)
fluid_onnx/ops.py
Outdated
output_node = make_node( | ||
'Reshape', | ||
inputs=matmul_out, | ||
shape=out_shape, |
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.
Same as above, code comment
'Flatten', | ||
inputs=inputs['Y'], | ||
outputs=y_flat_out, | ||
axis=attrs['y_num_col_dims']) | ||
|
||
# Mat mul | ||
matmul_out = [outputs['Out'][0] + '@matmul_0'] | ||
matmul_node = make_node( | ||
'MatMul', inputs=x_flat_out + y_flat_out, outputs=matmul_out) |
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.
@nickyfantasy is asking if we can use the Mul
op here
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.
Seems cannot, Mul
op is for element-wise production
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.
@varunarora Thanks for the review!
I find that the ONNX release 1.1.2 is far behind the master branch, not the same as I thought. Maybe we'd better only consider v1.0.1 and the latest master branch of ONNX temporarily, and go back to the
compatibility some day in the future.
@@ -68,13 +72,6 @@ def activation_ops(act_type, operator, block): | |||
act_type, inputs=inputs.values()[0], outputs=outputs.values()[0]) | |||
|
|||
|
|||
def and_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.
Yes. It is no longer needed.
from caffe2.python.onnx.backend import Caffe2Backend | ||
rep = Caffe2Backend.prepare(onnx_model, device='CPU') | ||
else: | ||
import onnx_tensorrt.backend as backend |
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.
Great! Appreciate that.
onnx_graph = helper.make_graph( | ||
nodes=onnx_nodes, | ||
name=model_name, | ||
initializer=weights, |
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.
Yeah. initializer
is the officially recommended to initialize parameters, and the issues under onnx/models
show that they may deprecate the Constant op initialization someday.
It should not be the proper way to initialize the tmp
inputs and outputs to the ops. Let's figure out what happened here after Qualcomm prepare related operators.
fluid_to_onnx.py
Outdated
onnx_nodes.append(param_node) | ||
weight, val_info = paddle_onnx_weight( | ||
var=var, scope=inference_scope) | ||
weights.append(weight), weights_value_info.append(val_info) |
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
fluid_onnx/ops.py
Outdated
output_node = make_node( | ||
'Reshape', | ||
inputs=matmul_out, | ||
shape=out_shape, |
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
'Flatten', | ||
inputs=inputs['Y'], | ||
outputs=y_flat_out, | ||
axis=attrs['y_num_col_dims']) | ||
|
||
# Mat mul | ||
matmul_out = [outputs['Out'][0] + '@matmul_0'] | ||
matmul_node = make_node( | ||
'MatMul', inputs=x_flat_out + y_flat_out, outputs=matmul_out) |
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.
Seems cannot, Mul
op is for element-wise production
fluid_onnx/ops.py
Outdated
'momentum': attrs['momentum'] | ||
} | ||
if __onnx_ver__ == u'1.0.1': | ||
kwargs['consumed_inputs'] = [0, 0, 0, 1, 1] |
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 docs found. If don't set the consumed_inputs
, ONNX will give an error
onnx.onnx_cpp2py_export.checker.ValidationError: Input index 3 must be set to consumed for operator BatchNormalization
So I looked into the code in ONNX 1.0.1, finally find this attribute and its proper usage.
fluid_onnx/ops.py
Outdated
@@ -87,36 +84,52 @@ def batch_norm_op(operator, block): | |||
inputs, attrs, outputs = op_io_info(operator) | |||
|
|||
x_shape = block.vars[get_old_name(inputs['X'][0])].shape | |||
reshape_node = None | |||
nodes = () | |||
if len(x_shape) == 2: |
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.
Added the comment about why we need reshape here. And why didn't use Constant
op in branch 1.0.1
? the answer is that in onnx1.0.1 shape is used as an attribute and doesn't need a constant op to feed value.
fluid_onnx/ops.py
Outdated
outputs=outputs['Out'], | ||
scale=1.0 - attrs['dropout_prob']) | ||
return (dropout_op, scale_op) | ||
if __onnx_ver__ == '1.0.1': |
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.
How about we temporarily fix the version number to 1.0.1 right now? because there are several releases, and I have not checked the changes in the definition of operators.
You got the point. Yes, we need to scale the output of Dropout op, otherwise inference wouldn't get right result.
fluid_onnx/ops.py
Outdated
inputs=inputs['Y'], | ||
outputs=y_flat_out, | ||
axis=attrs['y_num_col_dims']) | ||
if __onnx_ver__ == '1.0.1': |
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
Got it. Instead, why don't we just make 1.0.1 as our main version supported. And then do a We can't guarantee support of master, but we can expect 1.0.0 or 1.0.1 as a stable point for all backends. |
@varunarora Thanks! It is good to use 1.0.1 as the stable point. I'll try to test changes and make them work on both 1.0.1 and latest master. We can go back to make the compatibility more elegant in future. |
Resolve #46
The TensorRT backend for onnx only supports
onnx==1.0.1
right now, while we were carrying out experiments on master branch of ONNX and caffe2 backend. Hence, we need to make some adaptions to enable the converted models running with TensorRT backend.Now the conversion's correctness of all the current supported models has been validated on TensorRT, including: