blob: 27ad70be3b422bf6d7e22b671d6ebb88e9734066 [file] [log] [blame]
Teresa Charlin18147332021-11-17 14:34:30 +00001# Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
Richard Burtondc0c6ed2020-04-08 16:39:05 +01002# SPDX-License-Identifier: MIT
3import os
4import stat
Cathal Corbett9f184c42021-11-10 12:14:39 +00005import numpy as np
Richard Burtondc0c6ed2020-04-08 16:39:05 +01006
7import pytest
8import pyarmnn as ann
9
alexander73010782021-10-18 19:17:24 +010010
Jan Eilers841aca12020-08-12 14:59:06 +010011def test_optimizer_options_default_values():
12 opt = ann.OptimizerOptions()
13 assert opt.m_ReduceFp32ToFp16 == False
14 assert opt.m_Debug == False
15 assert opt.m_ReduceFp32ToBf16 == False
Narumol Prangnawaratea063df2020-08-21 10:03:49 +010016 assert opt.m_ImportEnabled == False
alexander73010782021-10-18 19:17:24 +010017 assert opt.m_shapeInferenceMethod == ann.ShapeInferenceMethod_ValidateOnly
18
Jan Eilers841aca12020-08-12 14:59:06 +010019
20def test_optimizer_options_set_values1():
21 opt = ann.OptimizerOptions(True, True)
22 assert opt.m_ReduceFp32ToFp16 == True
23 assert opt.m_Debug == True
24 assert opt.m_ReduceFp32ToBf16 == False
Narumol Prangnawaratea063df2020-08-21 10:03:49 +010025 assert opt.m_ImportEnabled == False
alexander73010782021-10-18 19:17:24 +010026 assert opt.m_shapeInferenceMethod == ann.ShapeInferenceMethod_ValidateOnly
27
Jan Eilers841aca12020-08-12 14:59:06 +010028
29def test_optimizer_options_set_values2():
30 opt = ann.OptimizerOptions(False, False, True)
31 assert opt.m_ReduceFp32ToFp16 == False
32 assert opt.m_Debug == False
33 assert opt.m_ReduceFp32ToBf16 == True
Narumol Prangnawaratea063df2020-08-21 10:03:49 +010034 assert opt.m_ImportEnabled == False
alexander73010782021-10-18 19:17:24 +010035 assert opt.m_shapeInferenceMethod == ann.ShapeInferenceMethod_ValidateOnly
36
Narumol Prangnawaratea063df2020-08-21 10:03:49 +010037
38def test_optimizer_options_set_values3():
alexander73010782021-10-18 19:17:24 +010039 opt = ann.OptimizerOptions(False, False, True, ann.ShapeInferenceMethod_InferAndValidate, True)
Narumol Prangnawaratea063df2020-08-21 10:03:49 +010040 assert opt.m_ReduceFp32ToFp16 == False
41 assert opt.m_Debug == False
42 assert opt.m_ReduceFp32ToBf16 == True
43 assert opt.m_ImportEnabled == True
alexander73010782021-10-18 19:17:24 +010044 assert opt.m_shapeInferenceMethod == ann.ShapeInferenceMethod_InferAndValidate
45
Richard Burtondc0c6ed2020-04-08 16:39:05 +010046
47@pytest.fixture(scope="function")
48def get_runtime(shared_data_folder, network_file):
49 parser= ann.ITfLiteParser()
50 preferred_backends = [ann.BackendId('CpuAcc'), ann.BackendId('CpuRef')]
51 network = parser.CreateNetworkFromBinaryFile(os.path.join(shared_data_folder, network_file))
52 options = ann.CreationOptions()
53 runtime = ann.IRuntime(options)
54
55 yield preferred_backends, network, runtime
56
57
58@pytest.mark.parametrize("network_file",
59 [
60 'mock_model.tflite',
61 ],
62 ids=['mock_model'])
63def test_optimize_executes_successfully(network_file, get_runtime):
64 preferred_backends = [ann.BackendId('CpuRef')]
65 network = get_runtime[1]
66 runtime = get_runtime[2]
67
68 opt_network, messages = ann.Optimize(network, preferred_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
69
70 assert len(messages) == 0, 'With only CpuRef, there should be no warnings irrelevant of architecture.'
71 assert opt_network
72
73
74@pytest.mark.parametrize("network_file",
75 [
76 'mock_model.tflite',
77 ],
78 ids=['mock_model'])
79def test_optimize_owned_by_python(network_file, get_runtime):
80 preferred_backends = get_runtime[0]
81 network = get_runtime[1]
82 runtime = get_runtime[2]
83
84 opt_network, _ = ann.Optimize(network, preferred_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
85 assert opt_network.thisown
86
87
88@pytest.mark.aarch64
89@pytest.mark.parametrize("network_file",
90 [
91 'mock_model.tflite'
92 ],
93 ids=['mock_model'])
94def test_optimize_executes_successfully_for_neon_backend_only(network_file, get_runtime):
95 preferred_backends = [ann.BackendId('CpuAcc')]
96 network = get_runtime[1]
97 runtime = get_runtime[2]
98
99 opt_network, messages = ann.Optimize(network, preferred_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
100 assert 0 == len(messages)
101 assert opt_network
102
103
104@pytest.mark.parametrize("network_file",
105 [
106 'mock_model.tflite'
107 ],
108 ids=['mock_model'])
109def test_optimize_fails_for_invalid_backends(network_file, get_runtime):
110 invalid_backends = [ann.BackendId('Unknown')]
111 network = get_runtime[1]
112 runtime = get_runtime[2]
113
114 with pytest.raises(RuntimeError) as err:
115 ann.Optimize(network, invalid_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
116
117 expected_error_message = "None of the preferred backends [Unknown ] are supported."
118 assert expected_error_message in str(err.value)
119
120
121@pytest.mark.parametrize("network_file",
122 [
123 'mock_model.tflite'
124 ],
125 ids=['mock_model'])
126def test_optimize_fails_for_no_backends_specified(network_file, get_runtime):
127 empty_backends = []
128 network = get_runtime[1]
129 runtime = get_runtime[2]
130
131 with pytest.raises(RuntimeError) as err:
132 ann.Optimize(network, empty_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
133
134 expected_error_message = "Invoked Optimize with no backends specified"
135 assert expected_error_message in str(err.value)
136
137
138@pytest.mark.parametrize("network_file",
139 [
140 'mock_model.tflite'
141 ],
142 ids=['mock_model'])
143def test_serialize_to_dot(network_file, get_runtime, tmpdir):
144 preferred_backends = get_runtime[0]
145 network = get_runtime[1]
146 runtime = get_runtime[2]
147 opt_network, _ = ann.Optimize(network, preferred_backends,
148 runtime.GetDeviceSpec(), ann.OptimizerOptions())
149 dot_file_path = os.path.join(tmpdir, 'mock_model.dot')
150 """Check that serialized file does not exist at the start, gets created after SerializeToDot and is not empty"""
151 assert not os.path.exists(dot_file_path)
152 opt_network.SerializeToDot(dot_file_path)
153
154 assert os.path.exists(dot_file_path)
155
156 with open(dot_file_path) as res_file:
157 expected_data = res_file.read()
158 assert len(expected_data) > 1
159 assert '[label=< [1,28,28,1] >]' in expected_data
160
161
162@pytest.mark.x86_64
163@pytest.mark.parametrize("network_file",
164 [
165 'mock_model.tflite'
166 ],
167 ids=['mock_model'])
168def test_serialize_to_dot_mode_readonly(network_file, get_runtime, tmpdir):
169 preferred_backends = get_runtime[0]
170 network = get_runtime[1]
171 runtime = get_runtime[2]
172 opt_network, _ = ann.Optimize(network, preferred_backends,
173 runtime.GetDeviceSpec(), ann.OptimizerOptions())
174 """Create file, write to it and change mode to read-only"""
175 dot_file_path = os.path.join(tmpdir, 'mock_model.dot')
176 f = open(dot_file_path, "w+")
177 f.write("test")
178 f.close()
179 os.chmod(dot_file_path, stat.S_IREAD)
180 assert os.path.exists(dot_file_path)
181
182 with pytest.raises(RuntimeError) as err:
183 opt_network.SerializeToDot(dot_file_path)
184
185 expected_error_message = "Failed to open dot file"
186 assert expected_error_message in str(err.value)
187
188
189@pytest.mark.parametrize("method", [
190 'AddActivationLayer',
191 'AddAdditionLayer',
192 'AddArgMinMaxLayer',
193 'AddBatchNormalizationLayer',
194 'AddBatchToSpaceNdLayer',
Teresa Charlin87dc8122021-11-22 15:34:26 +0000195 'AddCastLayer',
Teresa Charlinf7b50112021-11-18 15:24:50 +0000196 'AddChannelShuffleLayer',
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100197 'AddComparisonLayer',
198 'AddConcatLayer',
199 'AddConstantLayer',
200 'AddConvolution2dLayer',
Teresa Charlin18147332021-11-17 14:34:30 +0000201 'AddConvolution3dLayer',
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100202 'AddDepthToSpaceLayer',
203 'AddDepthwiseConvolution2dLayer',
204 'AddDequantizeLayer',
205 'AddDetectionPostProcessLayer',
206 'AddDivisionLayer',
207 'AddElementwiseUnaryLayer',
208 'AddFloorLayer',
Jan Eilers841aca12020-08-12 14:59:06 +0100209 'AddFillLayer',
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100210 'AddFullyConnectedLayer',
211 'AddGatherLayer',
212 'AddInputLayer',
213 'AddInstanceNormalizationLayer',
Cathal Corbettf0836e02021-11-18 18:17:38 +0000214 'AddLogicalBinaryLayer',
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100215 'AddLogSoftmaxLayer',
216 'AddL2NormalizationLayer',
217 'AddLstmLayer',
218 'AddMaximumLayer',
219 'AddMeanLayer',
220 'AddMergeLayer',
221 'AddMinimumLayer',
222 'AddMultiplicationLayer',
223 'AddNormalizationLayer',
224 'AddOutputLayer',
225 'AddPadLayer',
226 'AddPermuteLayer',
227 'AddPooling2dLayer',
228 'AddPreluLayer',
229 'AddQuantizeLayer',
230 'AddQuantizedLstmLayer',
Jan Eilers841aca12020-08-12 14:59:06 +0100231 'AddRankLayer',
Ryan OShea09a05222021-11-18 16:52:41 +0000232 'AddReduceLayer',
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100233 'AddReshapeLayer',
234 'AddResizeLayer',
Ryan OSheaaeee9ad2021-11-18 17:43:55 +0000235 'AddShapeLayer',
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100236 'AddSliceLayer',
237 'AddSoftmaxLayer',
238 'AddSpaceToBatchNdLayer',
239 'AddSpaceToDepthLayer',
240 'AddSplitterLayer',
241 'AddStackLayer',
242 'AddStandInLayer',
243 'AddStridedSliceLayer',
244 'AddSubtractionLayer',
245 'AddSwitchLayer',
Cathal Corbett2b4182f2021-11-18 10:28:47 +0000246 'AddTransposeConvolution2dLayer',
247 'AddTransposeLayer'
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100248])
249def test_network_method_exists(method):
250 assert getattr(ann.INetwork, method, None)
251
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100252def test_DepthwiseConvolution2d_layer_optional_none():
253 net = ann.INetwork()
254 layer = net.AddDepthwiseConvolution2dLayer(convolution2dDescriptor=ann.DepthwiseConvolution2dDescriptor(),
Cathal Corbett9f184c42021-11-10 12:14:39 +0000255 weights=ann.ConstTensor())
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100256
257 assert layer
258
259
260def test_DepthwiseConvolution2d_layer_optional_provided():
261 net = ann.INetwork()
262 layer = net.AddDepthwiseConvolution2dLayer(convolution2dDescriptor=ann.DepthwiseConvolution2dDescriptor(),
Cathal Corbett9f184c42021-11-10 12:14:39 +0000263 weights=ann.ConstTensor(),
264 biases=ann.ConstTensor())
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100265
266 assert layer
267
268
269def test_DepthwiseConvolution2d_layer_all_args():
270 net = ann.INetwork()
271 layer = net.AddDepthwiseConvolution2dLayer(convolution2dDescriptor=ann.DepthwiseConvolution2dDescriptor(),
Cathal Corbett9f184c42021-11-10 12:14:39 +0000272 weights=ann.ConstTensor(),
273 biases=ann.ConstTensor(),
274 name='NAME1')
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100275
276 assert layer
277 assert 'NAME1' == layer.GetName()
278
279
280def test_Convolution2d_layer_optional_none():
281 net = ann.INetwork()
282 layer = net.AddConvolution2dLayer(convolution2dDescriptor=ann.Convolution2dDescriptor(),
Cathal Corbett9f184c42021-11-10 12:14:39 +0000283 weights=ann.ConstTensor())
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100284
285 assert layer
286
287
288def test_Convolution2d_layer_optional_provided():
289 net = ann.INetwork()
290 layer = net.AddConvolution2dLayer(convolution2dDescriptor=ann.Convolution2dDescriptor(),
Cathal Corbett9f184c42021-11-10 12:14:39 +0000291 weights=ann.ConstTensor(),
292 biases=ann.ConstTensor())
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100293
294 assert layer
295
296
297def test_Convolution2d_layer_all_args():
298 net = ann.INetwork()
299 layer = net.AddConvolution2dLayer(convolution2dDescriptor=ann.Convolution2dDescriptor(),
Cathal Corbett9f184c42021-11-10 12:14:39 +0000300 weights=ann.ConstTensor(),
301 biases=ann.ConstTensor(),
302 name='NAME1')
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100303
304 assert layer
305 assert 'NAME1' == layer.GetName()
Cathal Corbett9f184c42021-11-10 12:14:39 +0000306
307
308def test_add_constant_layer_to_fully_connected():
309
310 inputWidth = 1
311 inputHeight = 1
312 inputChannels = 5
313 inputNum = 2
314
315 outputChannels = 3
316 outputNum = 2
317
318 inputShape = ( inputNum, inputChannels, inputHeight, inputWidth )
319 outputShape = ( outputNum, outputChannels )
320 weightsShape = ( inputChannels, outputChannels )
321 biasShape = ( outputChannels, )
322
323 input = np.array([
324 [1.0, 2.0, 3.0, 4.0, 5.0],
325 [5.0, 4.0, 3.0, 2.0, 1.0]
326 ], dtype=np.float32)
327
328 weights = np.array([
329 [.5, 2., .5],
330 [.5, 2., 1.],
331 [.5, 2., 2.],
332 [.5, 2., 3.],
333 [.5, 2., 4.]
334 ], dtype=np.float32)
335
336 biasValues = np.array([10, 20, 30], dtype=np.float32)
337
338 expectedOutput = np.array([
339 [0.5 + 1.0 + 1.5 + 2.0 + 2.5 + biasValues[0],
340 2.0 + 4.0 + 6.0 + 8.0 + 10. + biasValues[1],
341 0.5 + 2.0 + 6.0 + 12. + 20. + biasValues[2]],
342 [2.5 + 2.0 + 1.5 + 1.0 + 0.5 + biasValues[0],
343 10.0 + 8.0 + 6.0 + 4.0 + 2. + biasValues[1],
344 2.5 + 4.0 + 6.0 + 6. + 4. + biasValues[2]]
345 ], dtype=np.float32)
346
347 network = ann.INetwork()
348
349 input_info = ann.TensorInfo(ann.TensorShape(inputShape), ann.DataType_Float32, 0, 0, True)
350 input_tensor = ann.ConstTensor(input_info, input)
351 input_layer = network.AddInputLayer(0, "input")
352
353 w_info = ann.TensorInfo(ann.TensorShape(weightsShape), ann.DataType_Float32, 0, 0, True)
354 w_tensor = ann.ConstTensor(w_info, weights)
355 w_layer = network.AddConstantLayer(w_tensor, "weights")
356
357 b_info = ann.TensorInfo(ann.TensorShape(biasShape), ann.DataType_Float32, 0, 0, True)
358 b_tensor = ann.ConstTensor(b_info, biasValues)
359 b_layer = network.AddConstantLayer(b_tensor, "bias")
360
361 fc_descriptor = ann.FullyConnectedDescriptor()
362 fc_descriptor.m_BiasEnabled = True
363 fc_descriptor.m_ConstantWeights = True
364 fully_connected = network.AddFullyConnectedLayer(fc_descriptor, "fc")
365
366 output_info = ann.TensorInfo(ann.TensorShape(outputShape), ann.DataType_Float32)
367 output_tensor = ann.Tensor(output_info, np.zeros([1, 1], dtype=np.float32))
368 output = network.AddOutputLayer(0, "output")
369
370 input_layer.GetOutputSlot(0).Connect(fully_connected.GetInputSlot(0))
371 w_layer.GetOutputSlot(0).Connect(fully_connected.GetInputSlot(1))
372 b_layer.GetOutputSlot(0).Connect(fully_connected.GetInputSlot(2))
373 fully_connected.GetOutputSlot(0).Connect(output.GetInputSlot(0))
374
375 input_layer.GetOutputSlot(0).SetTensorInfo(input_info)
376 w_layer.GetOutputSlot(0).SetTensorInfo(w_info)
377 b_layer.GetOutputSlot(0).SetTensorInfo(b_info)
378 fully_connected.GetOutputSlot(0).SetTensorInfo(output_info)
379
380 preferred_backends = [ann.BackendId('CpuRef')]
381 options = ann.CreationOptions()
382 runtime = ann.IRuntime(options)
383 opt_network, messages = ann.Optimize(network, preferred_backends, runtime.GetDeviceSpec(), ann.OptimizerOptions())
384 net_id, messages = runtime.LoadNetwork(opt_network)
385
386 input_tensors = [(0, input_tensor)]
387 output_tensors = [(0, output_tensor)]
388 runtime.EnqueueWorkload(net_id, input_tensors, output_tensors)
389
390 output_vectors = ann.workload_tensors_to_ndarray(output_tensors)
391
392 assert (output_vectors==expectedOutput).all()