Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 1 | # Copyright © 2022 Arm Ltd and Contributors. All rights reserved. |
Jan Eilers | 2cd1847 | 2020-12-15 10:42:38 +0000 | [diff] [blame] | 2 | # SPDX-License-Identifier: MIT |
| 3 | |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 4 | import numpy as np |
Jan Eilers | 2cd1847 | 2020-12-15 10:42:38 +0000 | [diff] [blame] | 5 | import pytest |
| 6 | import tflite_runtime.interpreter as tflite |
| 7 | import os |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 8 | from utils import run_mock_model, run_inference, compare_outputs |
Jan Eilers | 2cd1847 | 2020-12-15 10:42:38 +0000 | [diff] [blame] | 9 | |
| 10 | def 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 | |
Jan Eilers | 2cd1847 | 2020-12-15 10:42:38 +0000 | [diff] [blame] | 17 | def 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 |
| 24 | def 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 | |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 60 | @pytest.mark.GpuAccTest |
| 61 | def 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. |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 69 | open(binary_file, "a").close() |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 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 |
| 102 | def 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. |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 105 | armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "GpuAcc", |
| 106 | "enable-fast-math": "1", |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 107 | "logging-severity": "info"}) |
| 108 | |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 109 | model_file_name = "conv2d.tflite" |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 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 |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 134 | def test_external_delegate_cpu_options(delegate_dir, test_data_folder): |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 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. |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 137 | armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuAcc", |
| 138 | "enable-fast-math": "1", |
| 139 | "number-of-threads": "4", |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 140 | "logging-severity": "info"}) |
| 141 | |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 142 | model_file_name = "conv2d.tflite" |
Matthew Sloyan | c2b99a87 | 2021-04-27 17:16:12 +0100 | [diff] [blame] | 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 | |
Jan Eilers | 2cd1847 | 2020-12-15 10:42:38 +0000 | [diff] [blame] | 166 | def 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"}) |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 171 | |
| 172 | def test_external_delegate_options_debug(capfd, delegate_dir, test_data_folder): |
| 173 | # create armnn delegate with debug option |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 174 | armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuRef", |
| 175 | "debug-data": "1"}) |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 176 | |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 177 | model_file_name = "fp32_model.tflite" |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 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() |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 193 | assert "layerGuid" in captured.out |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 194 | |
| 195 | |
| 196 | def test_external_delegate_options_fp32_to_fp16(capfd, delegate_dir, test_data_folder): |
| 197 | # create armnn delegate with reduce-fp32-to-fp16 option |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 198 | armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuRef", |
| 199 | "debug-data": "1", |
| 200 | "reduce-fp32-to-fp16": "1"}) |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 201 | |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 202 | model_file_name = "fp32_model.tflite" |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 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() |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 218 | assert "convert_fp32_to_fp16" in captured.out |
| 219 | assert "convert_fp16_to_fp32" in captured.out |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 220 | |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 221 | def test_external_delegate_options_memory_import(delegate_dir, test_data_folder): |
| 222 | # create armnn delegate with memory-import option |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 223 | armnn_delegate = tflite.load_delegate(delegate_dir, options = {"backends": "CpuAcc,CpuRef", |
| 224 | "memory-import": "1"}) |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 225 | |
Cathal Corbett | 46f2986 | 2022-07-25 13:24:49 +0100 | [diff] [blame] | 226 | model_file_name = "fallback_model.tflite" |
Narumol Prangnawarat | 74a3cf5 | 2021-01-29 15:38:54 +0000 | [diff] [blame] | 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]) |