1# Copyright © 2022 Arm Ltd and Contributors. All rights reserved. 2# SPDX-License-Identifier: MIT 3 4import numpy as np 5import pytest 6import tflite_runtime.interpreter as tflite 7import os 8from utils import run_mock_model, run_inference, compare_outputs 9 10def test_external_delegate_unknown_options(delegate_dir): 11 print(delegate_dir) 12 with pytest.raises(ValueError): 13 tflite.load_delegate( 14 delegate_dir, 15 options={"wrong": "wrong"}) 16 17def test_external_delegate_options_multiple_backends(delegate_dir): 18 tflite.load_delegate( 19 delegate_dir, 20 options={"backends": "GpuAcc,CpuAcc,CpuRef,Unknown"}) 21 22 23@pytest.mark.GpuAccTest 24def test_external_delegate_options_gpu_tuning(delegate_dir, test_data_folder, tmp_path): 25 26 tuning_file = os.path.join(str(tmp_path), "test_gpu.tuning") 27 # cleanup previous test run if necessary 28 if os.path.exists(tuning_file): 29 os.remove(tuning_file) 30 31 # with tuning level 2 a tuning file should be created 32 armnn_delegate = tflite.load_delegate( 33 delegate_dir, 34 options={ 35 "backends": "GpuAcc", 36 "gpu-tuning-level": "2", 37 "gpu-tuning-file": tuning_file, 38 "logging-severity": "info"}) 39 40 run_mock_model(armnn_delegate, test_data_folder) 41 42 # destroy delegate, otherwise tuning file won't be written to file 43 armnn_delegate.__del__() 44 assert (os.path.exists(tuning_file)) 45 46 # if no tuning level is provided it defaults to 0 which means it will use the tuning parameters from a tuning 47 # file if one is provided 48 armnn_delegate2 = tflite.load_delegate( 49 delegate_dir, 50 options={ 51 "backends": "GpuAcc", 52 "gpu-tuning-file": tuning_file, 53 "logging-severity": "info"}) 54 55 run_mock_model(armnn_delegate2, test_data_folder) 56 57 # cleanup 58 os.remove(tuning_file) 59 60@pytest.mark.GpuAccTest 61def test_external_delegate_options_gpu_cached_network(delegate_dir, test_data_folder, tmp_path): 62 63 binary_file = os.path.join(str(tmp_path), "test_binary.bin") 64 # cleanup previous test run if necessary 65 if os.path.exists(binary_file): 66 os.remove(binary_file) 67 68 # Create blank binary file to write to. 69 open(binary_file, "a").close() 70 assert (os.path.exists(binary_file)) 71 assert (os.stat(binary_file).st_size == 0) 72 73 # Run inference to save cached network. 74 armnn_delegate = tflite.load_delegate( 75 delegate_dir, 76 options={ 77 "backends": "GpuAcc", 78 "save-cached-network": "1", 79 "cached-network-filepath": binary_file, 80 "logging-severity": "info"}) 81 82 run_mock_model(armnn_delegate, test_data_folder) 83 84 # destroy delegate and check if file has been saved. 85 armnn_delegate.__del__() 86 assert (os.stat(binary_file).st_size != 0) 87 88 # Create second delegate to load in binary file created. 89 armnn_delegate2 = tflite.load_delegate( 90 delegate_dir, 91 options={ 92 "backends": "GpuAcc", 93 "cached-network-filepath": binary_file, 94 "logging-severity": "info"}) 95 96 run_mock_model(armnn_delegate2, test_data_folder) 97 98 # cleanup 99 os.remove(binary_file) 100 101@pytest.mark.GpuAccTest 102def test_external_delegate_gpu_fastmath(delegate_dir, test_data_folder): 103 # create armnn delegate with enable-fast-math 104 # fast-math is only enabled on Conv2d layer, so use conv2d model. 105 armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "GpuAcc", 106 "enable-fast-math": "1", 107 "logging-severity": "info"}) 108 109 model_file_name = "conv2d.tflite" 110 111 inputShape = [ 1, 5, 5, 1 ] 112 outputShape = [ 1, 3, 3, 1 ] 113 114 inputValues = [ 1, 5, 2, 3, 5, 115 8, 7, 3, 6, 3, 116 3, 3, 9, 1, 9, 117 4, 1, 8, 1, 3, 118 6, 8, 1, 9, 2 ] 119 120 expectedResult = [ 28, 38, 29, 121 96, 104, 53, 122 31, 55, 24 ] 123 124 input = np.array(inputValues, dtype=np.float32).reshape(inputShape) 125 expected_output = np.array(expectedResult, dtype=np.float32).reshape(outputShape) 126 127 # run the inference 128 armnn_outputs = run_inference(test_data_folder, model_file_name, [input], [armnn_delegate]) 129 130 # check results 131 compare_outputs(armnn_outputs, [expected_output]) 132 133@pytest.mark.CpuAccTest 134def test_external_delegate_cpu_options(delegate_dir, test_data_folder): 135 # create armnn delegate with enable-fast-math and number-of-threads options 136 # fast-math is only enabled on Conv2d layer, so use conv2d model. 137 armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuAcc", 138 "enable-fast-math": "1", 139 "number-of-threads": "4", 140 "logging-severity": "info"}) 141 142 model_file_name = "conv2d.tflite" 143 144 inputShape = [ 1, 5, 5, 1 ] 145 outputShape = [ 1, 3, 3, 1 ] 146 147 inputValues = [ 1, 5, 2, 3, 5, 148 8, 7, 3, 6, 3, 149 3, 3, 9, 1, 9, 150 4, 1, 8, 1, 3, 151 6, 8, 1, 9, 2 ] 152 153 expectedResult = [ 28, 38, 29, 154 96, 104, 53, 155 31, 55, 24 ] 156 157 input = np.array(inputValues, dtype=np.float32).reshape(inputShape) 158 expected_output = np.array(expectedResult, dtype=np.float32).reshape(outputShape) 159 160 # run the inference 161 armnn_outputs = run_inference(test_data_folder, model_file_name, [input], [armnn_delegate]) 162 163 # check results 164 compare_outputs(armnn_outputs, [expected_output]) 165 166def test_external_delegate_options_wrong_logging_level(delegate_dir): 167 with pytest.raises(ValueError): 168 tflite.load_delegate( 169 delegate_dir, 170 options={"logging-severity": "wrong"}) 171 172def test_external_delegate_options_debug(capfd, delegate_dir, test_data_folder): 173 # create armnn delegate with debug option 174 armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuRef", 175 "debug-data": "1"}) 176 177 model_file_name = "fp32_model.tflite" 178 179 tensor_shape = [1, 2, 2, 1] 180 181 input0 = np.array([1, 2, 3, 4], dtype=np.float32).reshape(tensor_shape) 182 input1 = np.array([2, 2, 3, 4], dtype=np.float32).reshape(tensor_shape) 183 inputs = [input0, input0, input1] 184 expected_output = np.array([1, 2, 2, 2], dtype=np.float32).reshape(tensor_shape) 185 186 # run the inference 187 armnn_outputs = run_inference(test_data_folder, model_file_name, inputs, [armnn_delegate]) 188 189 # check results 190 compare_outputs(armnn_outputs, [expected_output]) 191 192 captured = capfd.readouterr() 193 assert "layerGuid" in captured.out 194 195 196def test_external_delegate_options_fp32_to_fp16(capfd, delegate_dir, test_data_folder): 197 # create armnn delegate with reduce-fp32-to-fp16 option 198 armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuRef", 199 "debug-data": "1", 200 "reduce-fp32-to-fp16": "1"}) 201 202 model_file_name = "fp32_model.tflite" 203 204 tensor_shape = [1, 2, 2, 1] 205 206 input0 = np.array([1, 2, 3, 4], dtype=np.float32).reshape(tensor_shape) 207 input1 = np.array([2, 2, 3, 4], dtype=np.float32).reshape(tensor_shape) 208 inputs = [input0, input0, input1] 209 expected_output = np.array([1, 2, 2, 2], dtype=np.float32).reshape(tensor_shape) 210 211 # run the inference 212 armnn_outputs = run_inference(test_data_folder, model_file_name, inputs, [armnn_delegate]) 213 214 # check results 215 compare_outputs(armnn_outputs, [expected_output]) 216 217 captured = capfd.readouterr() 218 assert "convert_fp32_to_fp16" in captured.out 219 assert "convert_fp16_to_fp32" in captured.out 220 221def test_external_delegate_options_memory_import(delegate_dir, test_data_folder): 222 # create armnn delegate with memory-import option 223 armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuAcc,CpuRef", 224 "memory-import": "1"}) 225 226 model_file_name = "fallback_model.tflite" 227 228 tensor_shape = [1, 2, 2, 1] 229 230 input0 = np.array([1, 2, 3, 4], dtype=np.uint8).reshape(tensor_shape) 231 input1 = np.array([2, 2, 3, 4], dtype=np.uint8).reshape(tensor_shape) 232 inputs = [input0, input0, input1] 233 expected_output = np.array([1, 2, 2, 2], dtype=np.uint8).reshape(tensor_shape) 234 235 # run the inference 236 armnn_outputs = run_inference(test_data_folder, model_file_name, inputs, [armnn_delegate]) 237 238 # check results 239 compare_outputs(armnn_outputs, [expected_output])