99from executorch .backends .nxp .backend .edge_program_converter import (
1010 EdgeProgramToIRConverter ,
1111)
12- from executorch .backends .nxp .tests .executors import (
13- convert_run_compare ,
14- graph_contains_any_of_ops ,
12+ from executorch .backends .nxp .tests .executors import graph_contains_any_of_ops
13+ from executorch .backends .nxp .tests .graph_verifier import DetailedGraphVerifier
14+ from executorch .backends .nxp .tests .model_output_comparator import (
15+ AllCloseOutputComparator ,
1516)
1617from executorch .backends .nxp .tests .models import (
18+ ConvPReLUModule ,
1719 LinearPReLUModule ,
1820 TwoPartitionPReLUModel ,
1921)
22+
23+ from executorch .backends .nxp .tests .nsys_testing import lower_run_compare
24+ from executorch .backends .nxp .tests .ops_aliases import (
25+ AddMm ,
26+ Convolution ,
27+ ExecutorchDelegateCall ,
28+ GtScalar ,
29+ MulTensor ,
30+ PermuteCopy ,
31+ Prelu ,
32+ ViewCopy ,
33+ WhereSelf ,
34+ )
2035from torch .export import ExportedProgram
2136from executorch .backends .nxp .tests .use_qat import * # noqa F403
2237from executorch .backends .nxp .tests .executorch_pipeline import to_quantized_edge_program
23- from executorch .exir .dialects ._ops import ops as exir_ops
2438
2539
2640@pytest .fixture (autouse = True )
@@ -29,123 +43,126 @@ def reseed_model_per_test_run():
2943 np .random .seed (23 )
3044
3145
32- # noinspection PyProtectedMember
33- ExecutorchDelegateCall = torch .ops .higher_order .executorch_call_delegate
34-
35-
36- @pytest .mark .parametrize (
37- "input_shape" ,
38- [
39- pytest .param ((1 , 8 , 24 , 32 ), id = "4D." ),
40- ],
41- )
42- def test_prelu_with_linear_quant_conversion (mocker , input_shape ):
43- converter_spy = mocker .spy (EdgeProgramToIRConverter , "convert_program" )
44-
45- # Run conversion
46- channels = input_shape [- 1 ]
47- edge_program = to_quantized_edge_program (
48- LinearPReLUModule (in_features = channels , out_features = channels ),
49- input_shape ,
50- ).exported_program ()
51-
52- # Capture generated entities
53- neutron_ir_model , _ = converter_spy .spy_return
54- exported_program : ExportedProgram = converter_spy .call_args .args [1 ]
55-
56- # Check `prelu` was not decomposed into simpler edge operators
57- assert not graph_contains_any_of_ops (
58- exported_program .graph ,
46+ class TestPreluConverter :
47+ @pytest .mark .parametrize (
48+ "input_shape" ,
5949 [
60- exir_ops .edge .aten .gt .Scalar ,
61- exir_ops .edge .aten .mul .Tensor ,
62- exir_ops .edge .aten .where .self ,
50+ pytest .param ((1 ,), id = "1D." ),
51+ pytest .param (
52+ (36 , 487 ),
53+ id = "2D incorrect." ,
54+ marks = pytest .mark .xfail (
55+ reason = "AIR-14737: incorrect results" , strict = True
56+ ),
57+ ),
58+ pytest .param (
59+ (87 , 842 ),
60+ id = "2D incorrect alt." ,
61+ marks = pytest .mark .xfail (
62+ reason = "AIR-14737: incorrect results" , strict = True
63+ ),
64+ ),
65+ pytest .param ((7 , 83 ), id = "2D." ),
66+ pytest .param (
67+ (1 , 43 , 183 ),
68+ id = "3D incorrect alt." ,
69+ marks = pytest .mark .xfail (
70+ reason = "AIR-14737: incorrect results" , strict = True
71+ ),
72+ ),
73+ pytest .param ((1 , 43 , 93 ), id = "3D." ),
74+ pytest .param ((1 , 4 , 7 , 8 ), id = "4D." ),
75+ pytest .param ((1 , 4 , 3 , 4 , 14 ), id = "5D." ),
6376 ],
6477 )
65-
66- assert graph_contains_any_of_ops (
67- exported_program .graph ,
68- [exir_ops .edge .aten .prelu .default ],
69- )
70-
71- # Check `prelu` was delegated
72- assert not graph_contains_any_of_ops (
73- edge_program .graph ,
74- [exir_ops .edge .aten .prelu .default ],
75- )
76-
77- input_data = (
78- (2 * np .random .random (input_shape ).astype (np .float32 ) - 1 ) * 50
79- ).astype (np .int8 )
80-
81- convert_run_compare (exported_program , input_data , tfl_model = neutron_ir_model )
82-
83-
84- @pytest .mark .parametrize (
85- "input_shape" ,
86- [
87- pytest .param ((1 , 8 , 24 , 32 ), id = "4D." ),
88- ],
89- )
90- def test_prelu_2_partitions (mocker , input_shape ):
91- # TODO (Martin) Add a channels last dim order variant of this test to verify correct partitioning.
92- # Run conversion
93- edge_program = to_quantized_edge_program (
94- TwoPartitionPReLUModel (), [input_shape , input_shape ]
95- ).exported_program ()
96-
97- # Check `prelu` was delegated
98- assert not graph_contains_any_of_ops (
99- edge_program .graph ,
100- [exir_ops .edge .aten .prelu .default ],
101- )
102-
103- # Check there are two partitions
104- edge_nodes = list (edge_program .graph .nodes )
105- assert sum (n .target == ExecutorchDelegateCall for n in edge_nodes ) == 2
106-
107-
108- @pytest .mark .parametrize (
109- "input_shape" ,
110- [
111- pytest .param ((1 ,), id = "1D not supported." ),
112- pytest .param ((1 , 8 ), id = "2D not supported." ),
113- pytest .param ((1 , 8 , 16 ), id = "3D not supported." ),
114- pytest .param ((1 , 8 , 16 , 32 , 64 ), id = "5D not supported." ),
115- pytest .param ((1 , 8 , 16 , 31 ), id = "channels must be divisible by NUM_MACS" ),
116- pytest .param ((1 , 8 , 1024 , 8 ), id = "width*height is too big (limit 4096)" ),
117- ],
118- )
119- def test_prelu__no_delegation__unsupported_conversion (mocker , input_shape ):
120- # Run conversion
121- channels = input_shape [- 1 ]
122- edge_program = to_quantized_edge_program (
123- LinearPReLUModule (in_features = channels , out_features = channels ),
124- input_shape ,
125- ).exported_program ()
126-
127- # Check `prelu` was not delegated (only `linear` was)
128- edge_nodes = list (edge_program .graph .nodes )
129- assert sum (n .target == ExecutorchDelegateCall for n in edge_nodes ) == 1
130-
131- # Check `prelu` was decomposed into simpler edge operators
132- assert graph_contains_any_of_ops (
133- edge_program .graph ,
134- [
135- exir_ops .edge .aten .gt .Scalar ,
136- ],
137- )
138-
139- assert graph_contains_any_of_ops (
140- edge_program .graph ,
141- [
142- exir_ops .edge .aten .mul .Tensor ,
143- ],
144- )
145-
146- assert graph_contains_any_of_ops (
147- edge_program .graph ,
78+ def test__basic_nsys_inference (self , mocker , request , input_shape ):
79+ channels = input_shape [- 1 ]
80+ rank = len (input_shape )
81+ model = LinearPReLUModule (in_features = channels , out_features = channels )
82+ graph_verifier = DetailedGraphVerifier (
83+ mocker ,
84+ expected_delegated_ops = {
85+ Prelu : 1 ,
86+ AddMm : 1 ,
87+ PermuteCopy : 1 ,
88+ ViewCopy : 0 if rank == 2 else 2 ,
89+ },
90+ expected_non_delegated_ops = {},
91+ )
92+ comparator = AllCloseOutputComparator (atol = 1 )
93+ converter_spy = mocker .spy (EdgeProgramToIRConverter , "convert_program" )
94+
95+ lower_run_compare (
96+ model ,
97+ input_shape ,
98+ graph_verifier ,
99+ request ,
100+ output_comparator = comparator ,
101+ remove_quant_io_ops = True ,
102+ )
103+
104+ # Capture generated entities
105+ neutron_ir_model , _ = converter_spy .spy_return
106+ exported_program : ExportedProgram = converter_spy .call_args .args [1 ]
107+
108+ # Check `prelu` was not decomposed into simpler edge operators
109+ assert not graph_contains_any_of_ops (
110+ exported_program .graph ,
111+ [
112+ GtScalar ,
113+ MulTensor ,
114+ WhereSelf ,
115+ ],
116+ )
117+
118+ def test_prelu_2_partitions (self ):
119+ input_shape = (1 , 8 , 24 , 32 )
120+ # Run conversion
121+ edge_program = to_quantized_edge_program (
122+ TwoPartitionPReLUModel (), [input_shape , input_shape ]
123+ ).exported_program ()
124+
125+ # Check `prelu` was delegated
126+ assert not graph_contains_any_of_ops (
127+ edge_program .graph ,
128+ [Prelu ],
129+ )
130+
131+ # Check there are two partitions
132+ edge_nodes = list (edge_program .graph .nodes )
133+ assert sum (n .target == ExecutorchDelegateCall for n in edge_nodes ) == 2
134+
135+ @pytest .mark .parametrize (
136+ "input_shape" ,
148137 [
149- exir_ops .edge .aten .where .self ,
138+ pytest .param ((1 , 8 , 42 , 24 ), id = "4D." ),
139+ pytest .param (
140+ (1 , 8 , 42 , 21 ),
141+ id = "4D." ,
142+ marks = pytest .mark .xfail (
143+ reason = "AIR-14737: incorrect results" , strict = True
144+ ),
145+ ),
150146 ],
151147 )
148+ def test__w_conv (self , mocker , request , input_shape ):
149+ channels = input_shape [1 ]
150+ model = ConvPReLUModule (in_channels = channels )
151+ graph_verifier = DetailedGraphVerifier (
152+ mocker ,
153+ expected_delegated_ops = {
154+ Prelu : 1 ,
155+ Convolution : 1 ,
156+ },
157+ expected_non_delegated_ops = {},
158+ )
159+ comparator = AllCloseOutputComparator (atol = 1 )
160+
161+ lower_run_compare (
162+ model ,
163+ input_shape ,
164+ graph_verifier ,
165+ request ,
166+ output_comparator = comparator ,
167+ remove_quant_io_ops = True ,
168+ )
0 commit comments