# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. """NNAPI network tests.""" import numpy as np import pytest pytest.importorskip("onnx") import onnx import tvm from test_nnapi.conftest import remote from test_nnapi.infrastructure import build_and_run # , build_and_run_vm from tvm.contrib.download import download_testdata from tvm.relax.frontend.onnx import from_onnx from tvm.testing import env def _build_and_run_network(remote_obj, tracker, mod, input_data): """Helper function to build and run a network.""" def execute_on_host(mod, inputs): with tvm.transform.PassContext(opt_level=3): ex = tvm.compile(mod, target="llvm") dev = tvm.cpu(0) vm = tvm.relax.VirtualMachine(ex, device=dev) output = vm["main"](*inputs) return output.numpy() outputs = [] for nnapi in [True, False]: if nnapi: outputs.append( build_and_run( remote_obj, tracker, mod, input_data, enable_nnapi=nnapi, ) ) else: outputs.append(execute_on_host(mod, input_data)) return outputs def get_network(name, dtype, input_shape=(1, 3, 224, 224)): def download_model(model_url, name): model_path = download_testdata(model_url, name + ".onnx", module="onnx") onnx_model = onnx.load(model_path) shape_dict = {"x": input_shape} mod = from_onnx(onnx_model, shape_dict) return mod def create_model(name): if "vgg11" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/vgg11_Opset18_timm/vgg11_Opset18.onnx" elif "mobilenetv3" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/mobilenetv3_large_100_miil_Opset17_timm/mobilenetv3_large_100_miil_Opset17.onnx" elif "alexnet" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/alexnet_Opset17_torch_hub/alexnet_Opset17.onnx" elif "resnet50" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/resnet50_Opset18_timm/resnet50_Opset18.onnx" elif "resnet34" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/resnet34_Opset18_timm/resnet34_Opset18.onnx" elif "resnet18" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/resnet18_Opset18_timm/resnet18_Opset18.onnx" elif "squeezenet" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/squeezenet1_1_Opset18_torch_hub/squeezenet1_1_Opset18.onnx" elif "vgg16" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/vgg16_Opset18_timm/vgg16_Opset18.onnx" elif "vgg19" == name: model_url = "https://github.com/onnx/models/raw/bec48b6a70e5e9042c0badbaafefe4454e072d08/Computer_Vision/vgg19_Opset18_timm/vgg19_Opset18.onnx" else: assert False, f"Not supported model {name}" return download_model(model_url, name) mod = create_model(name) return mod, {"data": (input_shape, dtype)} @pytest.mark.parametrize( "name", [ "alexnet", "vgg11", "vgg16", "vgg19", "resnet18", "resnet34", "resnet50", "squeezenet", "mobilenetv3", ], ) @pytest.mark.parametrize( "dtype", [ "float32", ], ) @pytest.mark.skipif(not env.build_flag_enabled("USE_NNAPI_CODEGEN"), reason="need nnapi") def test_network(name, dtype): remote_obj, tracker = remote() print(f"Network evaluating {name} with dtype {dtype}") np.random.seed(0) mod, inputs = get_network(name, dtype) input_data = {} for _name, (shape, _dtype) in inputs.items(): input_data[_name] = np.random.uniform(-1.0, 1.0, shape).astype(_dtype) inputs_tvm: list[tvm.runtime.Tensor] = [tvm.runtime.tensor(v) for k, v in input_data.items()] outputs = _build_and_run_network(remote_obj, tracker, mod, inputs_tvm) nnapi_out = outputs[0] expected_out = outputs[1] tvm.testing.assert_allclose(nnapi_out, expected_out, rtol=1e-4, atol=1e-5) if __name__ == "__main__": tvm.testing.main()