1919
2020from executorch .examples .nxp .experimental .cifar_net .cifar_net import CifarNetModel
2121
22+ from executorch .examples .models .mlperf_tiny .resnet8 import ResNet8
23+ from executorch .examples .models .mlperf_tiny import DSCNNKWS
24+ from executorch .examples .models .mlperf_tiny import MobileNetV1025
25+ from executorch .examples .models .mlperf_tiny import DeepAutoEncoder
2226
2327@pytest .fixture (autouse = True )
2428def reseed_model_per_test_run ():
@@ -39,7 +43,7 @@ def extract_map_from_logs(caplog):
3943 return None
4044
4145
42- class ParallelPoolModel (torch .nn .Module ):
46+ class SimpleParallelPoolModel (torch .nn .Module ):
4347 def __init__ (self , channels : int ):
4448 super ().__init__ ()
4549 self .conv_in = torch .nn .Conv2d (channels , channels , kernel_size = 3 , padding = 1 )
@@ -53,6 +57,27 @@ def forward(self, x):
5357 x = self .conv_out (x )
5458 return x
5559
60+ class ParallelPoolModel (torch .nn .Module ):
61+ def __init__ (self , ch = 16 ):
62+ super ().__init__ ()
63+ self .conv1 = torch .nn .Conv2d (ch , ch , 3 , padding = 1 )
64+ self .bn1 = torch .nn .BatchNorm2d (ch )
65+ self .conv2 = torch .nn .Conv2d (ch , ch , 3 , padding = 1 )
66+ self .maxpool = torch .nn .MaxPool2d (2 )
67+ self .avgpool = torch .nn .AvgPool2d (2 )
68+ self .conv_out = torch .nn .Conv2d (2 * ch , ch , 1 )
69+
70+ def forward (self , x ):
71+ residual = x
72+ x = self .conv1 (x )
73+ x = self .bn1 (x )
74+ x = torch .relu (x )
75+ x = self .conv2 (x )
76+ x = x + residual # residual connection
77+ x = torch .cat ((self .maxpool (x ), self .avgpool (x )), dim = 1 ) # parallel merge
78+ x = self .conv_out (x )
79+ return torch .relu (x )
80+
5681
5782class TestProfiling :
5883 @pytest .mark .xfail (reason = "SoftMax support PR is not merged so far." , strict = True )
@@ -78,10 +103,10 @@ def test__softmax(self, caplog, request):
78103 3 : (), # Neutron Dump
79104 }
80105
81- def test__parallel_pool (self , caplog , request ):
106+ def test__simple_parallel_pool (self , caplog , request ):
82107 caplog .set_level (logging .INFO )
83108 input_shape = (1 , 3 , 32 , 32 )
84- model = ParallelPoolModel (input_shape [1 ])
109+ model = SimpleParallelPoolModel (input_shape [1 ])
85110 lower_run_compare (
86111 model ,
87112 input_shape ,
@@ -156,3 +181,177 @@ def test__avg_pool(self, caplog, request):
156181 2 : (2 ,), # Slice
157182 3 : (), # Neutron Dump
158183 }
184+
185+
186+ def test__parallel_pool (self , caplog , request ):
187+ caplog .set_level (logging .INFO )
188+ input_shape = (1 , 16 , 32 , 32 )
189+ model = ParallelPoolModel (input_shape [1 ])
190+ lower_run_compare (
191+ model ,
192+ input_shape ,
193+ dlg_model_verifier = BaseGraphVerifier (1 , []),
194+ request = request ,
195+ output_comparator = NumericalStatsOutputComparator (),
196+ use_neutron_for_format_conversion = False ,
197+ use_profiling = True ,
198+ )
199+ neutron_map = extract_map_from_logs (caplog )
200+ assert neutron_map == {
201+ 0 : (8 , 9 ), # Conv2DStandardV1 (Pad + Conv2d)
202+ 1 : (10 ,), # Conv2DStandardV1
203+ 2 : (11 ,), # Add
204+ 3 : (), # Conv2DDepthwiseV2 (AvgPool)
205+ 4 : (12 ,), # MaxPool
206+ 5 : (14 ,), # StridedSliceConcat
207+ 6 : (15 , 16 ), # Conv2DPointwise (Conv2D + Relu)
208+ 7 : () # Neutron Dump
209+ }
210+
211+
212+ def test__resnet8 (self , caplog , request ):
213+ # Three-stage residual network for the MLPerf Tiny image-classification.
214+ caplog .set_level (logging .INFO )
215+ model = ResNet8 ()
216+ input_shape = (1 , 3 , 32 , 32 )
217+
218+ lower_run_compare (model ,
219+ input_shape ,
220+ dlg_model_verifier = BaseGraphVerifier (1 , []),
221+ request = request ,
222+ output_comparator = NumericalStatsOutputComparator (),
223+ use_neutron_for_format_conversion = False ,
224+ use_profiling = True ,
225+ )
226+ neutron_map = extract_map_from_logs (caplog )
227+ assert neutron_map == {
228+ 0 : (14 , 15 ), # Conv2DStandardV2 (Pad + Conv)
229+ 1 : (17 , 18 ), # Conv2DStandardV1 (Pad + Conv)
230+ 2 : (20 ,), # Conv2DStandardV1
231+ 3 : (21 ,), # Add
232+ 4 : (22 ,), # GlobalBiasScale (Relu)
233+ 5 : (28 ,), # Conv2DStandardV1
234+ 6 : (24 , 25 ), #Conv2DStandardV1 (Pad + Conv)
235+ 7 : (27 ,), # Conv2DStandardV1
236+ 8 : (29 ,), # Add
237+ 9 : (30 ,), # GlobalBiasScale (Relu)
238+ 10 : (36 ,), # Conv2DStandardV1
239+ 11 : (32 , 33 ), # Conv2DStandardV1 (Pad + Conv)
240+ 12 : (35 ,), # Conv2DStandardV1
241+ 13 : (37 ,), # Add
242+ 14 : (38 ,), # GlobalBiasScale (Relu)
243+ 15 : (), # GlobalAvgPool (Mean)
244+ 16 : (41 ,), # FullyConnected
245+ 17 : () # Neutron Dump
246+ }
247+
248+
249+ def test__ds_cnn (self , caplog , request ):
250+ # Depthwise Separable CNN used for keyword spotting in MLCommons Tiny.
251+ caplog .set_level (logging .INFO )
252+ model = DSCNNKWS ()
253+ input_shape = (1 , 1 , 49 , 10 )
254+
255+ lower_run_compare (model ,
256+ input_shape ,
257+ dlg_model_verifier = BaseGraphVerifier (1 , []),
258+ request = request ,
259+ output_comparator = NumericalStatsOutputComparator (),
260+ use_neutron_for_format_conversion = False ,
261+ use_profiling = True ,
262+ )
263+ neutron_map = extract_map_from_logs (caplog )
264+ assert neutron_map == {
265+ 0 : (14 , 15 ), # Pad (Conv + Relu)
266+ 1 : (14 , 15 ), # Conv2DStandardV2 (Conv + Relu)
267+ 2 : (18 , 19 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
268+ 3 : (21 , 22 ), # Conv2DPointwise (Conv + Relu)
269+ 4 : (24 , 25 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
270+ 5 : (27 , 28 ), # Conv2DDepthwiseV1 (Conv + Relu)
271+ 6 : (30 , 31 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
272+ 7 : (33 , 34 ), # Conv2DPointwise (Conv + Relu)
273+ 8 : (36 , 37 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
274+ 9 : (39 , 40 ), # Conv2DPointwise (Conv + Relu)
275+ 10 : (42 ,), # Conv2DDepthwiseDense (AvgPool)
276+ 11 : (44 ,), # FullyConnected
277+ 12 : () # Neutron Dump
278+ }
279+
280+
281+ def test__mobilenet_v1_025 (self , caplog , request ):
282+ # MobileNetV1 with width multiplier 0.25 for the Visual Wake Words.
283+ caplog .set_level (logging .INFO )
284+ model = MobileNetV1025 ()
285+ input_shape = (1 , 3 , 96 , 96 )
286+
287+ lower_run_compare (model ,
288+ input_shape ,
289+ dlg_model_verifier = BaseGraphVerifier (1 , []),
290+ request = request ,
291+ output_comparator = NumericalStatsOutputComparator (),
292+ use_neutron_for_format_conversion = False ,
293+ use_profiling = True ,
294+ )
295+ neutron_map = extract_map_from_logs (caplog )
296+ assert neutron_map == {
297+ 0 : (32 , 33 ), # Conv2DStandardV2 (Conv + Relu)
298+ 1 : (35 , 36 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
299+ 2 : (38 , 39 ), # Conv2DPointwise (Conv + Relu)
300+ 3 : (41 , 42 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
301+ 4 : (44 , 45 ), # Conv2DPointwise (Conv + Relu)
302+ 5 : (47 , 48 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
303+ 6 : (50 , 51 ), # Conv2DPointwise (Conv + Relu)
304+ 7 : (53 , 54 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
305+ 8 : (56 , 57 ), # Conv2DPointwise (Conv + Relu)
306+ 9 : (59 , 60 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
307+ 10 : (62 , 63 ), # Conv2DPointwise (Conv + Relu)
308+ 11 : (65 , 66 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
309+ 12 : (68 , 69 ), # Conv2DPointwise (Conv + Relu)
310+ 13 : (71 , 72 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
311+ 14 : (74 , 75 ), # Conv2DPointwise (Conv + Relu)
312+ 15 : (77 , 78 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
313+ 16 : (80 , 81 ), # Conv2DPointwise (Conv + Relu)
314+ 17 : (83 , 84 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
315+ 18 : (86 , 87 ), # Conv2DPointwise (Conv + Relu)
316+ 19 : (89 , 90 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
317+ 20 : (92 , 93 ), # Conv2DPointwise (Conv + Relu)
318+ 21 : (95 , 96 ), # Conv2DDepthwiseV1 (DepthwiseConv + Relu)
319+ 22 : (98 , 99 ), # Conv2DPointwise (Conv + Relu)
320+ 23 : (101 , 102 ), # Conv2DDepthwiseDense (DepthwiseConv + Relu)
321+ 24 : (104 , 105 ), # Conv2DPointwise (Conv + Relu)
322+ 25 : (107 , 108 ), # Conv2DDepthwiseDense (DepthwiseConv + Relu)
323+ 26 : (110 , 111 ), # Conv2DPointwise (Conv + Relu)
324+ 27 : (), # Mean (GlobalAvgPool)
325+ 28 : (114 ,), # FullyConnected
326+ 29 : () # Neutron Dump
327+ }
328+
329+
330+ def test__deep_autoencoder (self , caplog , request ):
331+ # MLPerf Tiny anomaly detection deep autoencoder.
332+ caplog .set_level (logging .INFO )
333+ model = DeepAutoEncoder ()
334+ input_shape = (1 , 640 )
335+
336+ lower_run_compare (model ,
337+ input_shape ,
338+ dlg_model_verifier = BaseGraphVerifier (1 , []),
339+ request = request ,
340+ output_comparator = NumericalStatsOutputComparator (),
341+ use_neutron_for_format_conversion = False ,
342+ use_profiling = True ,
343+ )
344+ neutron_map = extract_map_from_logs (caplog )
345+ assert neutron_map == {
346+ 0 : (22 , 23 ), # FullyConnected (FullyConnected + Relu)
347+ 1 : (24 , 25 ), # FullyConnected (FullyConnected + Relu)
348+ 2 : (26 , 27 ), # FullyConnected (FullyConnected + Relu)
349+ 3 : (28 , 29 ), # FullyConnected (FullyConnected + Relu)
350+ 4 : (30 , 31 ), # FullyConnected (FullyConnected + Relu)
351+ 5 : (32 , 33 ), # FullyConnected (FullyConnected + Relu)
352+ 6 : (34 , 35 ), # FullyConnected (FullyConnected + Relu)
353+ 7 : (36 , 37 ), # FullyConnected (FullyConnected + Relu)
354+ 8 : (38 , 39 ), # FullyConnected (FullyConnected + Relu)
355+ 9 : (40 ,), # FullyConnected
356+ 10 : () # Neutron Dump
357+ }
0 commit comments