-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[ETHOSU][MicroNPU][Pass] Add a pass to replicate pads #14909
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
[ETHOSU][MicroNPU][Pass] Add a pass to replicate pads #14909
Conversation
|
cc @neildhickey, @ekalda, @ilyag-grovety, @Aleksei-grovety @arina-grovety |
ff1fd37 to
7836a42
Compare
|
@tvm-bot rerun |
| if op_pairs[0] == "depthwise": | ||
| weight_shape = [kernel_shape[0], kernel_shape[1], ifm_shape[3], 1] | ||
| weight = tf.constant(np.random.uniform(size=weight_shape), dtype=tf.float32) | ||
| x1 = tf.nn.depthwise_conv2d( | ||
| x, weight, strides=tf_strides, padding=op_padding, dilations=dilation | ||
| ) | ||
| else: | ||
| weight_shape = [kernel_shape[0], kernel_shape[1], ifm_shape[3], 3] | ||
| weight = tf.constant(np.random.uniform(size=weight_shape), dtype=tf.float32) | ||
| x1 = tf.nn.conv2d( | ||
| x, | ||
| weight, | ||
| strides=tf_strides, | ||
| padding=op_padding, | ||
| dilations=dilation, | ||
| ) |
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.
Here the same code as on lines 3706 - 3721, it can be put into a separate function.
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
| "Adds pads so that each conv2d operator has only one consumer" |
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.
Maybe "Adds pads to each conv2d operator so that each pad has only one consumer."?
| new_conv2d_args = [] | ||
| for i, arg in enumerate(call.args): | ||
| if i == 0: | ||
| new_conv2d_args.append(self.visit(new_pad)) |
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_pad is visited twice the first time on line 59.
|
@tvm-bot rerun |
ekalda
left a 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.
Thanks @sergio-grovety, great work! Bar @Aleksei-grovety suggestions, I only had one nit and two more general points:
- This pass is necessary due to how we do pattern matching for Ethos-U and is therefore coupled to Ethos-U integration, so I don't think it makes much sense to have it among generic Relay transformation passes. Maybe move it to somewhere into
ethosunamespace, e.g. into codegen. - Testing - while legalization test is the most important test for this kind of change, I think it would also be good to have a simple lightweight codegen test for this kind of graph topology. Since the pass creates a new conv2d, there is some risk of constants getting messed up, but a simple codegen test should eliminate that risk.
|
|
||
| def __init__(self): | ||
| ExprMutator.__init__(self) | ||
| self.hashes = set() |
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: Maybe add a comment what self.hashes represents
bf520bd to
4678cbf
Compare
|
@tvm-bot rerun |
ekalda
left a 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.
Almost there, one suggestion regarding to testing!
| @pytest.mark.parametrize("accel_type", ACCEL_TYPES) | ||
| @pytest.mark.parametrize("ifm_shape", [(1, 55, 32, 3)]) | ||
| @pytest.mark.parametrize( | ||
| "kernel_shape, activation_function", | ||
| [((3, 3), "RELU"), ((1, 2), "NONE")], | ||
| ) | ||
| @pytest.mark.parametrize("strides, dilation", [((3, 2), (1, 1))]) | ||
| @pytest.mark.parametrize("op_padding", ["SAME", "VALID"]) | ||
| @pytest.mark.parametrize("sep_padding", [(0, 0, 1, 1), (7, 5, 4, 5)]) | ||
| @pytest.mark.parametrize( | ||
| "op_pairs", [("conv2d", "conv2d"), ("depthwise", "depthwise"), ("conv2d", "depthwise")] | ||
| ) |
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 is 128 codegen tests, which would noticeably increase CI time. I think the variations on kernel_shape, activation_function, op_padding and sep_padding are exercised by other tests as well, so these values could be kept constant. Also, if we are parametrizing over one value, it doesn't need to be expressed with parametrize and can be included into the test code.
ekalda
left a 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.
LGTM! Thanks @sergio-grovety, @Aleksei-grovety and @arina-grovety!
|
Thanks all, this is merged now! |
Added a pass to to handle the situation when nn.pad operator has more than one qnn.conv2d consumer.
pad
/ \
Conv2D Conv2D
In this case, because of the peculiarities of pattern parsing, conv2d does not get into the composite for the NPU. Therefore, pads are added so that each has only one consumer.
---------
Co-authored-by: Sergey Smirnov <89378719+sergey-grovety@users.noreply.github.com>
Co-authored-by: Arina <117634809+arina-grovety@users.noreply.github.com>
Co-authored-by: arina.naumova <naumova@grovety.com>
Added a pass to to handle the situation when nn.pad operator has more than one qnn.conv2d consumer.
pad
/ \
Conv2D Conv2D
In this case, because of the peculiarities of pattern parsing, conv2d does not get into the composite for the NPU. Therefore, pads are added so that each has only one consumer.
---------
Co-authored-by: Sergey Smirnov <89378719+sergey-grovety@users.noreply.github.com>
Co-authored-by: Arina <117634809+arina-grovety@users.noreply.github.com>
Co-authored-by: arina.naumova <naumova@grovety.com>
Added a pass to to handle the situation when nn.pad operator has more than one qnn.conv2d consumer.
pad
/ \
Conv2D Conv2D
In this case, because of the peculiarities of pattern parsing, conv2d does not get into the composite for the NPU. Therefore, pads are added so that each has only one consumer.
---------
Co-authored-by: Sergey Smirnov <89378719+sergey-grovety@users.noreply.github.com>
Co-authored-by: Arina <117634809+arina-grovety@users.noreply.github.com>
Co-authored-by: arina.naumova <naumova@grovety.com>
Added a pass to to handle the situation when nn.pad operator has more than one qnn.conv2d consumer.
In this case, because of the peculiarities of pattern parsing, conv2d does not get into the composite for the NPU. Therefore, pads are added so that each has only one consumer.