Skip to content

Commit f504223

Browse files
committed
Update for eIQ Neutron SDK 3.1.2
1 parent 2aac17f commit f504223

2 files changed

Lines changed: 17 additions & 219 deletions

File tree

backends/nxp/backend/ir/converter/node_converters/ops_converters/softmax_converter.py

Lines changed: 13 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -59,63 +59,31 @@ def _is_supported_on_target(
5959
parameters_mapping: dict[str, Parameter],
6060
custom_delegation_options: CustomDelegationOptions,
6161
) -> bool:
62-
if neutron_target_spec.use_new_flow_neutron_c:
63-
"""New flow: Hardware constraints for the new flow:
64-
1. Input and Output must be INT8/UINT8
65-
2. Channels <= 2040
66-
3. Total spatial size <= 4096
67-
4. Total size (channels * spatial_size) <= 524288
68-
"""
69-
# Constraint 1: Input and Output must be INT8/UINT8.
70-
supported_types = [torch.int8, torch.uint8]
71-
if not NodeConverter.uses_quantization_type_for_io(
72-
node, supported_types, [0], [0]
73-
):
74-
return False
75-
76-
# Constraint 2: Channel size limit
77-
channels = SoftmaxConverter._get_channels(node)
78-
if channels > 2040:
79-
return False
80-
81-
# Constraint 3: Spatial size limit
82-
total_spatial_size = SoftmaxConverter._get_total_spatial_size(node)
83-
if total_spatial_size > 4096:
84-
return False
85-
86-
# Constraint 4: Total processing size limit
87-
if channels * total_spatial_size > 524288:
88-
return False
89-
90-
return True
91-
92-
"""Old flow. Hardware constraints for the old flow:
93-
1. Input rank must be >= 2 (Neutron does not support 1D)
94-
2. Channels < 4096 / num_pipes * 4
62+
"""New flow: Hardware constraints for the new flow:
63+
1. Input and Output must be INT8/UINT8
64+
2. Channels <= 2040
9565
3. Total spatial size (N*H*W) <= 4096
96-
4. (channels * spatial_size) / num_macs <= 65536
66+
4. Total size (channels * spatial_size) <= 524288
9767
"""
98-
input_shape = node.meta["val"].shape
99-
100-
# Constraint 1: Neutron does not support 1D SoftMax
101-
if len(input_shape) == 1:
68+
# Constraint 1: Input and Output must be INT8/UINT8.
69+
supported_types = [torch.int8, torch.uint8]
70+
if not NodeConverter.uses_quantization_type_for_io(
71+
node, supported_types, [0], [0]
72+
):
10273
return False
10374

104-
num_macs = neutron_target_spec.get_num_macs()
105-
num_pipes = neutron_target_spec.get_num_pipes()
106-
channels = SoftmaxConverter._get_channels(node)
107-
total_spatial_size = SoftmaxConverter._get_total_spatial_size(node)
108-
10975
# Constraint 2: Channel size limit
110-
if channels >= 4096 / num_pipes * 4:
76+
channels = SoftmaxConverter._get_channels(node)
77+
if channels > 2040:
11178
return False
11279

11380
# Constraint 3: Spatial size limit
81+
total_spatial_size = SoftmaxConverter._get_total_spatial_size(node)
11482
if total_spatial_size > 4096:
11583
return False
11684

11785
# Constraint 4: Total processing size limit
118-
if channels * total_spatial_size / num_macs > 65536:
86+
if channels * total_spatial_size > 524288:
11987
return False
12088

12189
return True

backends/nxp/tests/ir/converter/node_converter/test_softmax_converter.py

Lines changed: 4 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,8 @@
77
import pytest
88
import torch
99

10-
from executorch.backends.nxp.backend.edge_program_converter import (
11-
EdgeProgramToIRConverter,
12-
)
1310
from executorch.backends.nxp.tests.executorch_pipeline import to_quantized_edge_program
14-
from executorch.backends.nxp.tests.executors import (
15-
convert_run_compare,
16-
graph_contains_any_of_ops,
17-
ToChannelFirstPreprocess,
18-
ToChannelLastPreprocess,
19-
)
11+
from executorch.backends.nxp.tests.executors import graph_contains_any_of_ops
2012

2113
from executorch.backends.nxp.tests.graph_verifier import DetailedGraphVerifier
2214

@@ -55,164 +47,7 @@ def assert_softmax_not_delegated(graph):
5547
assert graph_contains_any_of_ops(graph, [Softmax])
5648

5749

58-
def random_input_data(input_shape):
59-
return (np.random.random(input_shape).astype(np.float32) * 256.0 - 128.0).astype(
60-
np.int8
61-
)
62-
63-
64-
@pytest.mark.parametrize(
65-
"input_shape, dim",
66-
[
67-
# Dim must always be the last dimension, which must be a multiple of 8 (num_macs).
68-
pytest.param((4096, 128), -1, id="2D_total_size_limit"),
69-
pytest.param((5, 8), -1, id="2D_dim_-1"),
70-
pytest.param((5, 8), 1, id="2D_dim_1"),
71-
pytest.param((4096, 8), -1, id="2D_WxH_limit"),
72-
pytest.param((2, 2048 - 8), -1, id="2D_channels_limit"),
73-
pytest.param((5, 4, 8), -1, id="3D_dim_-1"),
74-
pytest.param((4096, 1, 8), -1, id="3D_WxH_limit"),
75-
pytest.param((5, 4, 3, 8), -1, id="4D_dim_-1"),
76-
pytest.param((1, 64, 64, 8), -1, id="4D_WxH_limit"),
77-
pytest.param((64, 1, 64, 128), -1, id="4D_total_size_limit"),
78-
pytest.param((5, 4, 3, 2, 8), -1, id="5D_dim_-1"),
79-
],
80-
)
81-
def test_softmax_delegation(input_shape, dim: int, mocker):
82-
model = SoftmaxModule(dim)
83-
84-
converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program")
85-
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
86-
87-
assert_softmax_delegated(delegated_ep.graph)
88-
89-
# Verify correct behavior of the converted NeutronIR model.
90-
intermediate_ep = converter_spy.call_args.args[1]
91-
neutron_ir_model, _ = converter_spy.spy_return
92-
input_data = random_input_data(input_shape)
93-
94-
# Make sure the tested program contains the `softmax`, and its input has the expected rank.
95-
nodes = list(intermediate_ep.graph.nodes)
96-
assert nodes[2].target == Softmax
97-
assert len(nodes[2].args[0].meta["val"].shape) == len(input_shape)
98-
99-
convert_run_compare(
100-
intermediate_ep,
101-
tfl_model=neutron_ir_model,
102-
input_data=input_data,
103-
)
104-
105-
106-
@pytest.mark.parametrize(
107-
"input_shape,dim",
108-
[
109-
# `dim` must be the second dimension, which must be a multiple of 8 (num_macs).
110-
pytest.param((1, 8, 2, 3), 1, id="4D_dim_1"),
111-
pytest.param((1, 8, 64, 64), 1, id="4D_WxH_limit"),
112-
pytest.param((64, 128, 1, 64), -3, id="4D_dim_-3_total_size_limit"),
113-
],
114-
)
115-
def test_softmax_delegation__channel_first(input_shape, dim: int, mocker):
116-
model = ConvSoftmaxModule(dim, input_shape[1])
117-
118-
converter_spy = mocker.spy(EdgeProgramToIRConverter, "convert_program")
119-
delegated_ep = to_quantized_edge_program(
120-
model, input_shape, use_neutron_for_format_conversion=False
121-
).exported_program()
122-
123-
assert_softmax_delegated(delegated_ep.graph)
124-
125-
# Verify correct behavior of the converted NeutronIR model.
126-
intermediate_ep = converter_spy.call_args.args[1]
127-
neutron_ir_model, _ = converter_spy.spy_return
128-
input_data = random_input_data(input_shape)
129-
130-
# Make sure the tested program contains the `softmax`.
131-
assert graph_contains_any_of_ops(intermediate_ep.graph, [Softmax])
132-
133-
convert_run_compare(
134-
intermediate_ep,
135-
tfl_model=neutron_ir_model,
136-
input_data=input_data,
137-
tflite_input_preprocess=ToChannelLastPreprocess(),
138-
tflite_output_preprocess=ToChannelFirstPreprocess(),
139-
)
140-
141-
142-
@pytest.mark.parametrize(
143-
"input_shape,dim",
144-
[
145-
# `dim` is not the last dimension.
146-
pytest.param((10, 32), 0, id="2D_dim_0"),
147-
pytest.param((10, 32, 32), 1, id="3D_dim_1"),
148-
pytest.param((10, 32, 32, 8), 2, id="4D_dim_2"),
149-
pytest.param((10, 32, 32, 8, 8), 3, id="5D_dim_3"),
150-
pytest.param((10, 32, 32, 8, 8), 2, id="5D_dim_2"),
151-
],
152-
)
153-
def test_softmax_delegation__unsupported_dims(input_shape, dim: int):
154-
model = SoftmaxModule(dim)
155-
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
156-
assert_softmax_not_delegated(delegated_ep.graph)
157-
158-
159-
@pytest.mark.parametrize(
160-
"input_shape,dim",
161-
[
162-
# `dim` is not the second dimension.
163-
pytest.param((10, 32, 32, 8), 2, id="dim_2"),
164-
pytest.param((10, 32, 32, 8), -1, id="dim_-1"),
165-
pytest.param((10, 32, 32, 8), 3, id="dim_3"),
166-
],
167-
)
168-
def test_softmax_delegation__unsupported_dims__channels_first(input_shape, dim: int):
169-
model = SoftmaxModule(dim)
170-
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
171-
assert_softmax_not_delegated(delegated_ep.graph)
172-
173-
174-
@pytest.mark.parametrize(
175-
"input_shape,dim",
176-
[
177-
pytest.param((4096 + 1, 8), -1, id="2D_WxH_exceeded"),
178-
pytest.param((4096, 2, 8), -1, id="3D_WxH_exceeded"),
179-
pytest.param((2, 64, 64, 8), -1, id="4D_WxH_exceeded"),
180-
pytest.param((1, 2048), -1, id="2D_channels_exceeded"),
181-
pytest.param((4096, 128 + 8), -1, id="2D_total_size_exceeded"),
182-
pytest.param((64, 1, 64, 128 + 8), -1, id="4D_total_size_exceeded"),
183-
],
184-
)
185-
def test_softmax_delegation__unsupported_dimension_sizes(input_shape, dim: int):
186-
model = SoftmaxModule(dim)
187-
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
188-
assert_softmax_not_delegated(delegated_ep.graph)
189-
190-
191-
@pytest.mark.parametrize(
192-
"input_shape,dim",
193-
[
194-
pytest.param((2, 8, 64, 64), -1, id="4D_WxH_exceeded"),
195-
pytest.param((64, 128 + 8, 1, 64), -1, id="4D_total_size_exceeded"),
196-
],
197-
)
198-
def test_softmax_delegation__unsupported_dimension_sizes__channels_first(
199-
input_shape, dim: int
200-
):
201-
model = ConvSoftmaxModule(dim, input_shape[1])
202-
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
203-
assert_softmax_not_delegated(delegated_ep.graph)
204-
205-
206-
def test_softmax_delegation__1d():
207-
input_shape = (8,)
208-
dim = 0
209-
210-
model = SoftmaxModule(dim)
211-
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
212-
assert_softmax_not_delegated(delegated_ep.graph)
213-
214-
215-
class TestSoftmaxNewNeutronFlow:
50+
class TestSoftmax:
21651
@pytest.mark.parametrize(
21752
"input_shape, dim",
21853
[
@@ -238,7 +73,6 @@ def test__basic_nsys_inference(self, mocker, input_shape, dim):
23873
model,
23974
input_shape,
24075
graph_verifier,
241-
use_new_flow_neutron_c=True,
24276
output_comparator=output_comparator,
24377
)
24478

@@ -254,9 +88,7 @@ def test__basic_nsys_inference(self, mocker, input_shape, dim):
25488
)
25589
def test__limits(self, input_shape, dim, mocker):
25690
model = SoftmaxModule(dim)
257-
delegated_ep = to_quantized_edge_program(
258-
model, input_shape, use_new_flow_neutron_c=True
259-
).exported_program()
91+
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
26092

26193
# Make sure the `softmax` was delegated.
26294
assert_softmax_delegated(delegated_ep.graph)
@@ -273,9 +105,7 @@ def test__limits(self, input_shape, dim, mocker):
273105
)
274106
def test__limits_exceeded(self, input_shape, dim):
275107
model = SoftmaxModule(dim)
276-
delegated_ep = to_quantized_edge_program(
277-
model, input_shape, use_new_flow_neutron_c=True
278-
).exported_program()
108+
delegated_ep = to_quantized_edge_program(model, input_shape).exported_program()
279109

280110
# Make sure the `softmax` was NOT delegated.
281111

0 commit comments

Comments
 (0)