chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import tvm
|
||||
import tvm.testing
|
||||
from tvm import relax
|
||||
from tvm.support import ndk
|
||||
|
||||
# Test Infra
|
||||
|
||||
|
||||
class run_time_check:
|
||||
def __init__(self, device):
|
||||
self.device = device
|
||||
|
||||
def check(self):
|
||||
# Ensure adreno specific tests
|
||||
if self.device == "real":
|
||||
return "ADRENO_TARGET" in os.environ
|
||||
|
||||
# Adreno CI
|
||||
if "ADRENO_TARGET" in os.environ:
|
||||
return True
|
||||
|
||||
# Tests that can run on generic targets too
|
||||
elif self.device == "opencl":
|
||||
return tvm.opencl().exist
|
||||
elif self.device == "vulkan":
|
||||
return tvm.vulkan().exist
|
||||
elif self.device == "any":
|
||||
return tvm.opencl().exist or tvm.vulkan().exist
|
||||
else:
|
||||
return False
|
||||
|
||||
def __call__(self):
|
||||
return self.check
|
||||
|
||||
|
||||
# Eager skips for Adreno GPU tests, resolved at import time. Pair each with
|
||||
# ``@pytest.mark.gpu`` at the test site so CI's ``-m gpu`` filter selects it.
|
||||
|
||||
# OpenCL or Vulkan
|
||||
skip_unless_adreno_opencl_vulkan = pytest.mark.skipif(
|
||||
not run_time_check("any").check(),
|
||||
reason="need adreno opencl or vulkan",
|
||||
)
|
||||
|
||||
# CLML Codegen
|
||||
skip_unless_adreno_clml = pytest.mark.skipif(
|
||||
tvm.get_global_func("relax.is_openclml_runtime_enabled", allow_missing=True) is None,
|
||||
reason="need adreno openclml",
|
||||
)
|
||||
|
||||
|
||||
def is_target_available(target):
|
||||
if "clml" in target.attrs.get("keys", []) and "ADRENO_TARGET" not in os.environ:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class SessionManager:
|
||||
def __init__(self):
|
||||
self.is_remote = SessionManager.is_target_rpc()
|
||||
|
||||
def __enter__(self):
|
||||
if self.is_remote:
|
||||
self.RPC_TRACKER_HOST = os.getenv("TVM_TRACKER_HOST", "localhost")
|
||||
self.RPC_TRACKER_PORT = int(os.getenv("TVM_TRACKER_PORT", 7979))
|
||||
self.RPC_DEVICE_KEY = os.getenv("RPC_DEVICE_KEY", "android")
|
||||
|
||||
self.tracker = tvm.rpc.connect_tracker(self.RPC_TRACKER_HOST, self.RPC_TRACKER_PORT)
|
||||
self.rpc = self.tracker.request(self.RPC_DEVICE_KEY, priority=0, session_timeout=600)
|
||||
else:
|
||||
self.rpc = tvm.rpc.LocalSession()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.rpc.get_function("CloseRPCConnection")()
|
||||
|
||||
def load_module(self, ex: relax.VMExecutable):
|
||||
with tempfile.TemporaryDirectory() as tempdir:
|
||||
file_name = "vm_library.so"
|
||||
file_path = os.path.join(tempdir, file_name)
|
||||
if self.is_remote:
|
||||
ex.export_library(
|
||||
file_path, fcompile=ndk.create_shared, options=["-shared", "-fPIC", "-lm"]
|
||||
)
|
||||
else:
|
||||
ex.export_library(file_path)
|
||||
|
||||
self.rpc.upload(file_path)
|
||||
rexec = self.rpc.load_module(file_name)
|
||||
return rexec
|
||||
|
||||
def device(self, device: str):
|
||||
return self.rpc.device(device)
|
||||
|
||||
@staticmethod
|
||||
def is_target_rpc():
|
||||
"""
|
||||
Checks if the target is a remote device.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool: True if RPC_TARGET is set, False otherwise
|
||||
"""
|
||||
return os.environ.get("ADRENO_TARGET") == "adreno"
|
||||
|
||||
|
||||
def run_local(mod, inputs, target):
|
||||
"""
|
||||
Run the Relax module on the local CPU for verification.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mod : tvm.IRModule
|
||||
The Relax IRModule to execute.
|
||||
inputs : list of numpy.ndarray
|
||||
The input data for the module.
|
||||
save_lib : bool, optional
|
||||
Whether to save the compiled library. Default is False.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tvm.runtime.NDArray or tuple of tvm.runtime.NDArray
|
||||
The output from the module execution.
|
||||
"""
|
||||
ex = relax.build(mod, target)
|
||||
dev = tvm.cpu()
|
||||
vm = relax.VirtualMachine(ex, dev)
|
||||
inputs = [tvm.runtime.tensor(inp, dev) for inp in inputs]
|
||||
vm.set_input("main", *inputs)
|
||||
vm.invoke_stateful("main")
|
||||
tvm_output = vm.get_outputs("main")
|
||||
if isinstance(tvm_output, tuple):
|
||||
tvm_output = tuple(out.numpy() for out in tvm_output)
|
||||
else:
|
||||
tvm_output = (tvm_output.numpy(),)
|
||||
return tvm_output
|
||||
|
||||
|
||||
def build_and_run(mod, inputs, tgt):
|
||||
if SessionManager.is_target_rpc():
|
||||
tgt = tvm.target.Target(tgt, host={"kind": "llvm", "mtriple": "aarch64-linux-gnu"})
|
||||
else:
|
||||
tgt = tvm.target.Target(tgt, host={"kind": "llvm"})
|
||||
|
||||
relax_pipeline = relax.pipeline.get_default_pipeline(tgt)
|
||||
tir_pipeline = tvm.tirx.get_default_tir_pipeline(tgt)
|
||||
mod = relax_pipeline(mod)
|
||||
|
||||
ex = tvm.compile(mod, tgt, tir_pipeline=tir_pipeline)
|
||||
|
||||
def run_and_check():
|
||||
with SessionManager() as sess:
|
||||
rexec = sess.load_module(ex)
|
||||
dev = sess.device(tgt.kind.name)
|
||||
|
||||
if "vdevice" in mod.global_infos:
|
||||
device_arr = [dev for _ in range(len(mod.global_infos["vdevice"]))]
|
||||
else:
|
||||
device_arr = [dev]
|
||||
vm = relax.VirtualMachine(rexec, device_arr)
|
||||
device_inputs = [tvm.runtime.tensor(ip, dev) for ip in inputs]
|
||||
vm.set_input("main", *device_inputs)
|
||||
vm.invoke_stateful("main")
|
||||
tvm_output = vm.get_outputs("main")
|
||||
if isinstance(tvm_output, tuple):
|
||||
return tuple(out.numpy() for out in tvm_output)
|
||||
return (tvm_output.numpy(),)
|
||||
|
||||
if SessionManager.is_target_rpc():
|
||||
return run_and_check()
|
||||
return tvm.testing.run_with_gpu_lock(run_and_check)
|
||||
|
||||
|
||||
def verify_results(mod, target, ref_target):
|
||||
if not is_target_available(target):
|
||||
print("Skipping Eval Tests", flush=True)
|
||||
return
|
||||
|
||||
inputs = []
|
||||
for arg in mod["main"].params:
|
||||
shape = tuple(shape_val.value for shape_val in arg.ty.shape.values)
|
||||
inputs.append(np.random.uniform(0, 1, size=shape).astype(arg.ty.dtype))
|
||||
|
||||
mod_org, mod_ref = mod, mod.clone()
|
||||
|
||||
mod_ref = tvm.relax.transform.DecomposeOpsForInference()(mod_ref)
|
||||
if ref_target.kind.name == "llvm":
|
||||
rs_ref = run_local(mod_ref, inputs, ref_target)
|
||||
else:
|
||||
rs_ref = build_and_run(mod_ref, inputs, ref_target)
|
||||
|
||||
rs_org = build_and_run(mod_org, inputs, target)
|
||||
|
||||
for vl_org, vl_ref in zip(rs_org, rs_ref):
|
||||
tvm.testing.assert_allclose(vl_org, vl_ref, rtol=1e-3, atol=1e-3)
|
||||
Reference in New Issue
Block a user