布局变换

布局变换#

参考:tvm/tests/python/contrib/test_onnx.py

import set_env
import numpy as np
import onnxruntime as rt

import onnx
import onnxruntime

import tvm
from tvm import relay
from tvm.contrib.target.onnx import to_onnx
from tvm.relay.testing import run_infer_type

def func_to_onnx(func, name):
    mod = tvm.IRModule()
    mod["main"] = func
    onnx_model = to_onnx(mod, {}, name, path=None)
    return onnx_model.SerializeToString()


def run_onnx(onnx_model, input_data):
    sess = rt.InferenceSession(onnx_model)
    input_names = {}
    for input, data in zip(sess.get_inputs(), input_data):
        input_names[input.name] = data
    output_names = [out.name for out in sess.get_outputs()]
    res = sess.run(output_names, input_names)
    return res


def run_relay(func, data_tuple, is_dyn=False):
    target = "llvm"
    dev = tvm.device("llvm", 0)
    kind = "graph" if not is_dyn else "vm"
    relay_res = relay.create_executor(kind, device=dev, target=target).evaluate(func)(*data_tuple)

    result = []
    relay_res = relay_res if isinstance(relay_res, list) else [relay_res]
    for res in relay_res:
        result.append(res.numpy())

    return result


def verify_results(relay_func, indata, test_name, rtol=1e-7, atol=0, is_dyn=False):
    relay_results = run_relay(relay_func, indata, is_dyn)
    onnx_results = run_onnx(func_to_onnx(relay_func, test_name), indata)

    for relay_res, onnx_res in zip(relay_results, onnx_results):
        np.testing.assert_allclose(relay_res, onnx_res, rtol=rtol, atol=atol)

def verify_layout_transform(dshape, src_layout, dst_layout, dtype="float32"):
    x = relay.var("x", relay.ty.TensorType(dshape, dtype))
    y = relay.layout_transform(x, src_layout, dst_layout)
    func = relay.Function([x], y)
    x_data = np.random.uniform(size=dshape).astype(dtype)
    verify_results(func, [x_data], "test_layout_transform", rtol=1e-5, atol=1e-5)
verify_layout_transform((1, 3, 8, 8), "NCHW", "NHWC")
verify_layout_transform((1, 8, 8, 3), "NHWC", "NCHW")