From 5140d90f27c4f47cf8032f0e677ac4dbb5e072de Mon Sep 17 00:00:00 2001 From: Matthew Brookhart Date: Tue, 3 Aug 2021 09:28:51 -0600 Subject: [PATCH] Parametrize ONNX Unit tests (#8621) --- tests/python/frontend/onnx/test_forward.py | 3743 ++++++++++---------- tests/scripts/task_python_frontend.sh | 5 +- 2 files changed, 1966 insertions(+), 1782 deletions(-) diff --git a/tests/python/frontend/onnx/test_forward.py b/tests/python/frontend/onnx/test_forward.py index 8b633c18977a..0100b439736d 100644 --- a/tests/python/frontend/onnx/test_forward.py +++ b/tests/python/frontend/onnx/test_forward.py @@ -16,6 +16,7 @@ # under the License. import os import re +import glob import numpy as np import pytest @@ -47,7 +48,7 @@ def get_input_data_shape_dict(graph_def, input_data): def get_tvm_output_with_vm( - graph_def, input_data, target, device, opset=None, freeze_params=False, convert_to_static=False + graph_def, input_data, target, dev, opset=None, freeze_params=False, convert_to_static=False ): """Generic function to execute and get tvm output with vm executor""" if not isinstance(input_data, list): @@ -61,7 +62,7 @@ def get_tvm_output_with_vm( if convert_to_static: mod = relay.transform.DynamicToStatic()(mod) - ex = relay.create_executor("vm", mod=mod, device=device, target=target) + ex = relay.create_executor("vm", mod=mod, device=dev, target=target) result = ex.evaluate()(*input_data, **params) if isinstance(result, tvm.runtime.NDArray): return result.numpy() @@ -72,7 +73,7 @@ def get_tvm_output( graph_def, input_data, target, - device, + dev, output_shape=None, output_dtype="float32", opset=None, @@ -80,9 +81,6 @@ def get_tvm_output( ): """Generic function to execute and get tvm output""" # TODO: Resolve the issues and remove the following lines - target = "llvm" - device = tvm.cpu(0) - input_names, shape_dict = get_input_data_shape_dict(graph_def, input_data) mod, params = relay.frontend.from_onnx(graph_def, shape_dict, opset=opset) @@ -90,7 +88,7 @@ def get_tvm_output( with tvm.transform.PassContext(opt_level=opt_level): graph, lib, params = relay.build(mod, target, params=params) - m = graph_executor.create(graph, lib, device) + m = graph_executor.create(graph, lib, dev) # set inputs if isinstance(input_data, list): for i, e in enumerate(input_names): @@ -137,7 +135,8 @@ def verify_with_ort_with_inputs( model, inputs, out_shape=None, - targets=None, + target=None, + dev=None, use_vm=False, opset=None, freeze_params=False, @@ -153,42 +152,38 @@ def verify_with_ort_with_inputs( ort_out = get_onnxruntime_output(model, inputs) - if targets is None: - targets = [tgt for (tgt, _) in tvm.testing.enabled_targets()] - - for target in targets: - dev = tvm.device(target, 0) - if use_vm: - tvm_out = get_tvm_output_with_vm( - model, - inputs, - target, - dev, - opset=opset, - freeze_params=freeze_params, - convert_to_static=convert_to_static, - ) - else: - tvm_out = get_tvm_output( - model, inputs, target, dev, out_shape, dtype, opset=opset, opt_level=opt_level - ) - if not isinstance(tvm_out, list): - tvm_out = [tvm_out] - if not isinstance(ort_out, list): - ort_out = [ort_out] - for tvm_val, ort_val in zip(tvm_out, ort_out): - if apply_softmax: - ort_val = scipy.special.softmax(ort_val) - tvm_val = scipy.special.softmax(tvm_val) - tvm.testing.assert_allclose(ort_val, tvm_val, rtol=rtol, atol=atol) - assert ort_val.dtype == tvm_val.dtype + if use_vm: + tvm_out = get_tvm_output_with_vm( + model, + inputs, + target, + dev, + opset=opset, + freeze_params=freeze_params, + convert_to_static=convert_to_static, + ) + else: + tvm_out = get_tvm_output( + model, inputs, target, dev, out_shape, dtype, opset=opset, opt_level=opt_level + ) + if not isinstance(tvm_out, list): + tvm_out = [tvm_out] + if not isinstance(ort_out, list): + ort_out = [ort_out] + for tvm_val, ort_val in zip(tvm_out, ort_out): + if apply_softmax: + ort_val = scipy.special.softmax(ort_val) + tvm_val = scipy.special.softmax(tvm_val) + tvm.testing.assert_allclose(ort_val, tvm_val, rtol=rtol, atol=atol) + assert ort_val.dtype == tvm_val.dtype def verify_with_ort( model, input_shapes, out_shape=None, - targets=None, + target=None, + dev=None, use_vm=False, opset=None, freeze_params=False, @@ -202,7 +197,8 @@ def verify_with_ort( model, inputs, out_shape=out_shape, - targets=targets, + target=target, + dev=dev, use_vm=use_vm, opset=opset, freeze_params=freeze_params, @@ -228,8 +224,8 @@ def is_version_greater_than(ver): ) -@tvm.testing.uses_gpu -def test_reshape(): +@tvm.testing.parametrize_targets +def test_reshape(target, dev): in_shape = (4, 3, 3, 4) ref_shape = (6, 2, 4, 3) @@ -256,14 +252,13 @@ def test_reshape(): model = helper.make_model(graph, producer_name="reshape_test") - for target, dev in tvm.testing.enabled_targets(): - x = np.random.uniform(size=in_shape).astype("int32") - tvm_out = get_tvm_output(model, x, target, dev, ref_shape, "float32") - tvm.testing.assert_allclose(ref_shape, tvm_out.shape) + x = np.random.uniform(size=in_shape).astype("int32") + tvm_out = get_tvm_output(model, x, target, dev, ref_shape, "float32") + tvm.testing.assert_allclose(ref_shape, tvm_out.shape) -@tvm.testing.uses_gpu -def test_double_reshape(): +@tvm.testing.parametrize_targets +def test_double_reshape(target, dev): in_shape = (4, 3, 3, 4) ref_shape = (6, 2, 4, 3) @@ -292,14 +287,13 @@ def test_double_reshape(): model = helper.make_model(graph, producer_name="reshape_test") - for target, dev in tvm.testing.enabled_targets(): - x = np.random.uniform(size=in_shape).astype("int32") - tvm_out = get_tvm_output(model, x, target, dev, ref_shape, "float32") - tvm.testing.assert_allclose(ref_shape, tvm_out.shape) + x = np.random.uniform(size=in_shape).astype("int32") + tvm_out = get_tvm_output(model, x, target, dev, ref_shape, "float32") + tvm.testing.assert_allclose(ref_shape, tvm_out.shape) -@tvm.testing.uses_gpu -def test_expand(): +@tvm.testing.parametrize_targets +def test_expand(target, dev): def _test_expand(name, data, shape, ref_data, dtype="int32"): shape_array = np.array(shape) if dtype == "int32": @@ -339,9 +333,8 @@ def _test_expand(name, data, shape, ref_data, dtype="int32"): model = helper.make_model(graph, producer_name=name) - for target, dev in tvm.testing.enabled_targets(): - tvm_out = get_tvm_output_with_vm(model, data, target, dev, freeze_params=True) - tvm.testing.assert_allclose(ref_data, tvm_out) + tvm_out = get_tvm_output_with_vm(model, data, target, dev, freeze_params=True) + tvm.testing.assert_allclose(ref_data, tvm_out) in_shape = (3, 1) shape = (3, 4) @@ -358,51 +351,53 @@ def _test_expand(name, data, shape, ref_data, dtype="int32"): _test_expand("expand_with_dim_changed_test", data, shape, ref_data, "int64") -def verify_depth_to_space(inshape, outshape, mode, blockSize): - node = onnx.helper.make_node("DepthToSpace", inputs=["x"], outputs=["y"], blocksize=blockSize) - - graph = helper.make_graph( - [node], - "depth_to_space_test", - inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(inshape))], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(outshape))], - ) +@tvm.testing.parametrize_targets +def test_depth_to_space(target, dev): + def verify_depth_to_space(inshape, outshape, mode, blockSize): + node = onnx.helper.make_node( + "DepthToSpace", inputs=["x"], outputs=["y"], blocksize=blockSize + ) - model = helper.make_model(graph, producer_name="depth_to_space_test") + graph = helper.make_graph( + [node], + "depth_to_space_test", + inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(inshape))], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(outshape))], + ) - verify_with_ort(model, [inshape], [outshape]) + model = helper.make_model(graph, producer_name="depth_to_space_test") + verify_with_ort(model, [inshape], [outshape], target, dev) -@tvm.testing.uses_gpu -def test_depth_to_space(): # current onnx.checker use OpSet-1 version of DepthToSpace, which doesn't have a mode argument. # TO-DO, we can add mode argument to test CRD mode and DCR mode # in the future when we update to a newer onnx version. verify_depth_to_space((1, 8, 2, 3), (1, 2, 4, 6), mode="CRD", blockSize=2) -def verify_space_to_depth(inshape, outshape, blockSize): - node = onnx.helper.make_node("SpaceToDepth", inputs=["x"], outputs=["y"], blocksize=blockSize) - - graph = helper.make_graph( - [node], - "space_to_depth_test", - inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(inshape))], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(outshape))], - ) +@tvm.testing.parametrize_targets +def test_space_to_depth(target, dev): + def verify_space_to_depth(inshape, outshape, blockSize): + node = onnx.helper.make_node( + "SpaceToDepth", inputs=["x"], outputs=["y"], blocksize=blockSize + ) - model = helper.make_model(graph, producer_name="space_to_depth_test") + graph = helper.make_graph( + [node], + "space_to_depth_test", + inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(inshape))], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(outshape))], + ) - verify_with_ort(model, [inshape], [outshape]) + model = helper.make_model(graph, producer_name="space_to_depth_test") + verify_with_ort(model, [inshape], [outshape], target, dev) -@tvm.testing.uses_gpu -def test_space_to_depth(): verify_space_to_depth((1, 1, 4, 6), (1, 4, 2, 3), 2) -@tvm.testing.uses_gpu -def test_shape(): +@tvm.testing.parametrize_targets +def test_shape(target, dev): in_shape = (4, 3, 3, 4) ref_shape = (6, 2, 4, 3) @@ -431,76 +426,72 @@ def test_shape(): model = helper.make_model(graph, producer_name="shape_test") - for target, dev in tvm.testing.enabled_targets(): - x = np.random.uniform(size=in_shape).astype("int32") - tvm_out = get_tvm_output(model, x, target, dev, ref_shape, "int32") - tvm.testing.assert_allclose(ref_shape, tvm_out) + x = np.random.uniform(size=in_shape).astype("int32") + tvm_out = get_tvm_output(model, x, target, dev, ref_shape, "int32") + tvm.testing.assert_allclose(ref_shape, tvm_out) -def _test_power_iteration(x_shape, y_shape): - if isinstance(y_shape, int): - y_shape = [y_shape] +@tvm.testing.parametrize_targets +def test_power(target, dev): + def _test_power_iteration(x_shape, y_shape): + if isinstance(y_shape, int): + y_shape = [y_shape] - x = np.random.uniform(size=x_shape).astype(np.float32) - y = np.random.uniform(size=y_shape).astype(np.float32) + x = np.random.uniform(size=x_shape).astype(np.float32) + y = np.random.uniform(size=y_shape).astype(np.float32) - np_res = np.power(x, y).astype(np.float32) + np_res = np.power(x, y).astype(np.float32) - res = helper.make_node("Pow", ["x", "y"], ["out"]) + res = helper.make_node("Pow", ["x", "y"], ["out"]) - graph = helper.make_graph( - [res], - "power_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), - helper.make_tensor_value_info("y", TensorProto.FLOAT, list(y_shape)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(np_res.shape))], - ) + graph = helper.make_graph( + [res], + "power_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), + helper.make_tensor_value_info("y", TensorProto.FLOAT, list(y_shape)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(np_res.shape))], + ) - model = helper.make_model(graph, producer_name="power_test") + model = helper.make_model(graph, producer_name="power_test") - for target, dev in tvm.testing.enabled_targets(): tvm_out = get_tvm_output(model, [x, y], target, dev, np_res.shape) tvm.testing.assert_allclose(np_res, tvm_out, rtol=1e-5, atol=1e-5) - -@tvm.testing.uses_gpu -def test_power(): _test_power_iteration((1, 3), (1)) _test_power_iteration((2, 3), (2, 3)) _test_power_iteration((2, 3), (1, 3)) -def verify_range(start, limit, delta, dtype): - dtype_map = { - "float32": TensorProto.FLOAT, - "int32": TensorProto.INT32, - "int64": TensorProto.INT64, - } - dtype_onnx = dtype_map[dtype] - y = helper.make_node("Range", ["start", "limit", "delta"], ["output"]) - graph = helper.make_graph( - [y], - "range_test", - inputs=[ - helper.make_tensor_value_info("start", dtype_onnx, []), - helper.make_tensor_value_info("limit", dtype_onnx, []), - helper.make_tensor_value_info("delta", dtype_onnx, []), - ], - outputs=[ - helper.make_tensor_value_info( - "output", dtype_onnx, np.arange(start, limit, delta).shape - ) - ], - ) - model = helper.make_model(graph, producer_name="range_test") - inputs = [np.array(x).astype(dtype) for x in [start, limit, delta]] - verify_with_ort_with_inputs(model, inputs, use_vm=True) - +@tvm.testing.parametrize_targets +def test_range(target, dev): + def verify_range(start, limit, delta, dtype): + dtype_map = { + "float32": TensorProto.FLOAT, + "int32": TensorProto.INT32, + "int64": TensorProto.INT64, + } + dtype_onnx = dtype_map[dtype] + y = helper.make_node("Range", ["start", "limit", "delta"], ["output"]) + graph = helper.make_graph( + [y], + "range_test", + inputs=[ + helper.make_tensor_value_info("start", dtype_onnx, []), + helper.make_tensor_value_info("limit", dtype_onnx, []), + helper.make_tensor_value_info("delta", dtype_onnx, []), + ], + outputs=[ + helper.make_tensor_value_info( + "output", dtype_onnx, np.arange(start, limit, delta).shape + ) + ], + ) + model = helper.make_model(graph, producer_name="range_test") + inputs = [np.array(x).astype(dtype) for x in [start, limit, delta]] + verify_with_ort_with_inputs(model, inputs, target=target, dev=dev, use_vm=True) -@tvm.testing.uses_gpu -def test_range(): for t in ["float32", "int32", "int64"]: verify_range(0, 10, 1, t) verify_range(2, 8, 2, t) @@ -508,8 +499,8 @@ def test_range(): verify_range(-2, -7, -1, t) -@tvm.testing.uses_gpu -def test_squeeze(): +@tvm.testing.parametrize_targets +def test_squeeze(target, dev): in_shape = (1, 3, 1, 3, 1, 1) out_shape = (3, 3) y = helper.make_node("Squeeze", ["in"], ["out"], axes=[0, 2, 4, 5]) @@ -523,11 +514,11 @@ def test_squeeze(): model = helper.make_model(graph, producer_name="squeeze_test") x = np.random.uniform(size=in_shape).astype("float32") - verify_with_ort_with_inputs(model, [x], [out_shape], opset=11) + verify_with_ort_with_inputs(model, [x], [out_shape], target=target, dev=dev, opset=11) -@tvm.testing.uses_gpu -def test_flatten(): +@tvm.testing.parametrize_targets +def test_flatten(target, dev): in_shape = (1, 3, 4, 4) axis = 1 @@ -543,11 +534,11 @@ def test_flatten(): ) model = helper.make_model(graph, producer_name="flatten_test") - verify_with_ort(model, [in_shape]) + verify_with_ort(model, [in_shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_unsqueeze(): +@tvm.testing.parametrize_targets +def test_unsqueeze(target, dev): in_shape = (3, 3) axis = (0, 3, 4) out_shape = (1, 3, 3, 1, 1) @@ -561,37 +552,36 @@ def test_unsqueeze(): ) model = helper.make_model(graph, producer_name="squeeze_test") - verify_with_ort(model, [in_shape], opset=11) - + verify_with_ort(model, [in_shape], target=target, dev=dev, opset=11) -def verify_gather(in_shape, indices, axis, dtype): - x = np.random.uniform(size=in_shape).astype(dtype) - indices = np.array(indices, dtype="int64") - out_np = np.take(x, indices, axis=axis) - y = helper.make_node("Gather", ["in", "indices"], ["out"], axis=axis) +@tvm.testing.parametrize_targets +def test_gather(target, dev): + def verify_gather(in_shape, indices, axis, dtype): + x = np.random.uniform(size=in_shape).astype(dtype) + indices = np.array(indices, dtype="int64") + out_np = np.take(x, indices, axis=axis) - graph = helper.make_graph( - [y], - "gather_test", - inputs=[ - helper.make_tensor_value_info( - "in", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(in_shape) - ), - helper.make_tensor_value_info("indices", TensorProto.INT64, list(indices.shape)), - ], - outputs=[ - helper.make_tensor_value_info( - "out", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(out_np.shape) - ) - ], - ) - model = helper.make_model(graph, producer_name="gather_test") - verify_with_ort_with_inputs(model, [x, indices], dtype=dtype) + y = helper.make_node("Gather", ["in", "indices"], ["out"], axis=axis) + graph = helper.make_graph( + [y], + "gather_test", + inputs=[ + helper.make_tensor_value_info( + "in", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(in_shape) + ), + helper.make_tensor_value_info("indices", TensorProto.INT64, list(indices.shape)), + ], + outputs=[ + helper.make_tensor_value_info( + "out", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(out_np.shape) + ) + ], + ) + model = helper.make_model(graph, producer_name="gather_test") + verify_with_ort_with_inputs(model, [x, indices], target=target, dev=dev, dtype=dtype) -@tvm.testing.uses_gpu -def test_gather(): verify_gather((4,), [1], 0, "int32") verify_gather((1, 4), [0], 0, "int32") verify_gather((4,), [[[1, 0], [0, 1]]], 0, "float32") @@ -600,8 +590,8 @@ def test_gather(): verify_gather((4, 3, 5, 6), [[2, 1, 0, 0]], 0, "float32") -@tvm.testing.uses_gpu -def test_dynamic_gather(): +@tvm.testing.parametrize_targets +def test_dynamic_gather(target, dev): dtype = "float32" in_shape = [2, 2] indices = 1 @@ -641,33 +631,31 @@ def test_dynamic_gather(): mod, params = relay.frontend.from_onnx(model) - for target, device in tvm.testing.enabled_targets(): - ex = relay.create_executor("vm", mod=mod, device=device, target=target) - result = ex.evaluate()(x, **params) - tvm.testing.assert_allclose(out_np, result.numpy(), rtol=1e-5, atol=1e-5) - + ex = relay.create_executor("vm", mod=mod, device=dev, target=target) + result = ex.evaluate()(x, **params) + tvm.testing.assert_allclose(out_np, result.numpy(), rtol=1e-5, atol=1e-5) -def verify_gatherelements(in_shape, indices, axis): - x = np.random.uniform(size=in_shape).astype("float32") - indices = np.array(indices, dtype="int32") - y = helper.make_node("GatherElements", ["data", "indices"], ["output"], axis=axis) - graph = helper.make_graph( - [y], - "gather_elements_test", - inputs=[ - helper.make_tensor_value_info("data", TensorProto.FLOAT, list(in_shape)), - helper.make_tensor_value_info("indices", TensorProto.INT32, list(indices.shape)), - ], - outputs=[helper.make_tensor_value_info("output", TensorProto.FLOAT, list(in_shape))], - ) - model = helper.make_model(graph, producer_name="gather_elements_test") +@tvm.testing.parametrize_targets +def test_gatherelements(target, dev): + def verify_gatherelements(in_shape, indices, axis): + x = np.random.uniform(size=in_shape).astype("float32") + indices = np.array(indices, dtype="int32") - verify_with_ort_with_inputs(model, [x, indices]) + y = helper.make_node("GatherElements", ["data", "indices"], ["output"], axis=axis) + graph = helper.make_graph( + [y], + "gather_elements_test", + inputs=[ + helper.make_tensor_value_info("data", TensorProto.FLOAT, list(in_shape)), + helper.make_tensor_value_info("indices", TensorProto.INT32, list(indices.shape)), + ], + outputs=[helper.make_tensor_value_info("output", TensorProto.FLOAT, list(in_shape))], + ) + model = helper.make_model(graph, producer_name="gather_elements_test") + verify_with_ort_with_inputs(model, [x, indices], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_gatherelements(): verify_gatherelements((4,), [3, 0, 2, 1], 0) verify_gatherelements((2, 2), [[1, 0], [0, 1]], 0) verify_gatherelements((2, 2), [[0, 0], [1, 0]], 1) @@ -682,29 +670,30 @@ def test_gatherelements(): verify_gatherelements((3, 3, 3), indices, 2) -def verify_scatter(in_shape, indices, axis): - x = np.random.uniform(size=in_shape).astype("float32") - indices = np.array(indices, dtype="int32") - updates = np.random.uniform(size=indices.shape).astype("float32") - - y = helper.make_node("ScatterElements", ["data", "indices", "updates"], ["output"], axis=axis) +@tvm.testing.parametrize_targets +def test_scatter(target, dev): + def verify_scatter(in_shape, indices, axis): + x = np.random.uniform(size=in_shape).astype("float32") + indices = np.array(indices, dtype="int32") + updates = np.random.uniform(size=indices.shape).astype("float32") - graph = helper.make_graph( - [y], - "scatter_test", - inputs=[ - helper.make_tensor_value_info("data", TensorProto.FLOAT, list(in_shape)), - helper.make_tensor_value_info("indices", TensorProto.INT32, list(indices.shape)), - helper.make_tensor_value_info("updates", TensorProto.FLOAT, list(indices.shape)), - ], - outputs=[helper.make_tensor_value_info("output", TensorProto.FLOAT, list(in_shape))], - ) - model = helper.make_model(graph, producer_name="scatter_test") - verify_with_ort_with_inputs(model, [x, indices, updates]) + y = helper.make_node( + "ScatterElements", ["data", "indices", "updates"], ["output"], axis=axis + ) + graph = helper.make_graph( + [y], + "scatter_test", + inputs=[ + helper.make_tensor_value_info("data", TensorProto.FLOAT, list(in_shape)), + helper.make_tensor_value_info("indices", TensorProto.INT32, list(indices.shape)), + helper.make_tensor_value_info("updates", TensorProto.FLOAT, list(indices.shape)), + ], + outputs=[helper.make_tensor_value_info("output", TensorProto.FLOAT, list(in_shape))], + ) + model = helper.make_model(graph, producer_name="scatter_test") + verify_with_ort_with_inputs(model, [x, indices, updates], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_scatter(): verify_scatter((4,), [1], 0) verify_scatter((1, 4), [[0]], 0) verify_scatter((4,), [2, 3], 0) @@ -713,120 +702,130 @@ def test_scatter(): verify_scatter((4, 3, 5, 6), [[[[2, 1, 0, 0]]]], 0) -def _test_slice_iteration_v1(indata, outdata, starts, ends, axes=None): - if axes: - y = helper.make_node("Slice", ["in"], ["out"], axes=axes, starts=starts, ends=ends) - else: - y = helper.make_node("Slice", ["in"], ["out"], starts=starts, ends=ends) +@tvm.testing.parametrize_targets +def test_slice(target, dev): + def _test_slice_iteration_v1(indata, outdata, starts, ends, axes=None): + if axes: + y = helper.make_node("Slice", ["in"], ["out"], axes=axes, starts=starts, ends=ends) + else: + y = helper.make_node("Slice", ["in"], ["out"], starts=starts, ends=ends) - graph = helper.make_graph( - [y], - "slice_test", - inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(indata.shape))], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], - ) + graph = helper.make_graph( + [y], + "slice_test", + inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(indata.shape))], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], + ) - model = helper.make_model(graph, producer_name="slice_test") - verify_with_ort_with_inputs(model, [indata], [outdata.shape], opset=1) - - -def _test_slice_iteration_v10(indata, outdata, **attrs): - starts = attrs["starts"] - ends = attrs["ends"] - axes = None if "axes" not in attrs else attrs["axes"] - steps = None if "steps" not in attrs else attrs["steps"] - starts = np.asarray(starts) - ends = np.asarray(ends) - inputs = [ - helper.make_tensor_value_info("data", TensorProto.FLOAT, list(indata.shape)), - helper.make_tensor_value_info("starts", TensorProto.INT64, list(starts.shape)), - helper.make_tensor_value_info("ends", TensorProto.INT64, list(ends.shape)), - ] - initializer = [ - helper.make_tensor("starts", TensorProto.INT64, list(starts.shape), starts), - helper.make_tensor("ends", TensorProto.INT64, list(ends.shape), ends), - ] - nodes = [] + model = helper.make_model(graph, producer_name="slice_test") + verify_with_ort_with_inputs( + model, [indata], [outdata.shape], opset=1, target=target, dev=dev + ) + + def _test_slice_iteration_v10(indata, outdata, **attrs): + starts = attrs["starts"] + ends = attrs["ends"] + axes = None if "axes" not in attrs else attrs["axes"] + steps = None if "steps" not in attrs else attrs["steps"] + starts = np.asarray(starts) + ends = np.asarray(ends) + inputs = [ + helper.make_tensor_value_info("data", TensorProto.FLOAT, list(indata.shape)), + helper.make_tensor_value_info("starts", TensorProto.INT64, list(starts.shape)), + helper.make_tensor_value_info("ends", TensorProto.INT64, list(ends.shape)), + ] + initializer = [ + helper.make_tensor("starts", TensorProto.INT64, list(starts.shape), starts), + helper.make_tensor("ends", TensorProto.INT64, list(ends.shape), ends), + ] + nodes = [] + + if "add_noop_to_input_attrs" in attrs: + + def add_noop_to_input_attr(attr_name, attr): + output_name = attr_name + "_output" + + ref_shape = list(np.array(attr).shape) + ref_shape.insert(0, 1) + ref_shape = tuple(ref_shape) + ref_array = np.array(ref_shape) + ref_node = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=["ref_in_" + attr_name], + value=onnx.helper.make_tensor( + name="const_tensor__1_" + attr_name, + data_type=onnx.TensorProto.INT64, + dims=ref_array.shape, + vals=ref_array.flatten().astype(int), + ), + ) + in_shape = np.array(attr).shape + in_array = np.array(in_shape) + ref_node2 = onnx.helper.make_node( + "Constant", + inputs=[], + outputs=["input_shape_" + attr_name], + value=onnx.helper.make_tensor( + name="const_tensor__2_" + attr_name, + data_type=onnx.TensorProto.INT64, + dims=in_array.shape, + vals=in_array.flatten().astype(int), + ), + ) - if "add_noop_to_input_attrs" in attrs: + reshape1_node = helper.make_node( + "Reshape", [attr_name, "ref_in_" + attr_name], ["reshape_" + attr_name] + ) + reshape2_node = helper.make_node( + "Reshape", ["reshape_" + attr_name, "input_shape_" + attr_name], [output_name] + ) + return [ref_node, ref_node2, reshape1_node, reshape2_node] - def add_noop_to_input_attr(attr_name, attr): - output_name = attr_name + "_output" + slice_inputs = [] + for attr_name in ["starts", "ends", "axes", "steps"]: + if attr_name not in attrs: + continue + if "add_noop_to_input_attrs" in attrs and attr_name in attrs["add_noop_to_input_attrs"]: + nodes.extend(add_noop_to_input_attr(attr_name, attrs[attr_name])) + slice_inputs.append(attr_name + "_output") + else: + slice_inputs.append(attr_name) - ref_shape = list(np.array(attr).shape) - ref_shape.insert(0, 1) - ref_shape = tuple(ref_shape) - ref_array = np.array(ref_shape) - ref_node = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=["ref_in_" + attr_name], - value=onnx.helper.make_tensor( - name="const_tensor__1_" + attr_name, - data_type=onnx.TensorProto.INT64, - dims=ref_array.shape, - vals=ref_array.flatten().astype(int), - ), + if axes: + axes = np.asarray(axes) + inputs.append( + helper.make_tensor_value_info("axes", TensorProto.INT64, list(axes.shape)) ) - in_shape = np.array(attr).shape - in_array = np.array(in_shape) - ref_node2 = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=["input_shape_" + attr_name], - value=onnx.helper.make_tensor( - name="const_tensor__2_" + attr_name, - data_type=onnx.TensorProto.INT64, - dims=in_array.shape, - vals=in_array.flatten().astype(int), - ), + initializer.append( + helper.make_tensor("axes", TensorProto.INT64, list(axes.shape), axes) ) - reshape1_node = helper.make_node( - "Reshape", [attr_name, "ref_in_" + attr_name], ["reshape_" + attr_name] + if steps: + assert axes is not None and len(axes) == len(steps) + steps = np.asarray(steps) + inputs.append( + helper.make_tensor_value_info("steps", TensorProto.INT64, list(axes.shape)) ) - reshape2_node = helper.make_node( - "Reshape", ["reshape_" + attr_name, "input_shape_" + attr_name], [output_name] + initializer.append( + helper.make_tensor("steps", TensorProto.INT64, list(steps.shape), steps) ) - return [ref_node, ref_node2, reshape1_node, reshape2_node] - - slice_inputs = [] - for attr_name in ["starts", "ends", "axes", "steps"]: - if attr_name not in attrs: - continue - if "add_noop_to_input_attrs" in attrs and attr_name in attrs["add_noop_to_input_attrs"]: - nodes.extend(add_noop_to_input_attr(attr_name, attrs[attr_name])) - slice_inputs.append(attr_name + "_output") - else: - slice_inputs.append(attr_name) - - if axes: - axes = np.asarray(axes) - inputs.append(helper.make_tensor_value_info("axes", TensorProto.INT64, list(axes.shape))) - initializer.append(helper.make_tensor("axes", TensorProto.INT64, list(axes.shape), axes)) - if steps: - assert axes is not None and len(axes) == len(steps) - steps = np.asarray(steps) - inputs.append(helper.make_tensor_value_info("steps", TensorProto.INT64, list(axes.shape))) - initializer.append(helper.make_tensor("steps", TensorProto.INT64, list(steps.shape), steps)) - - y = helper.make_node("Slice", ["data", *slice_inputs], ["out"]) - - nodes.append(y) - graph = helper.make_graph( - nodes, - "slice_test", - inputs=inputs, - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], - initializer=initializer, - ) - model = helper.make_model(graph, producer_name="slice_test") - verify_with_ort_with_inputs(model, [indata], opset=10, freeze_params=True, use_vm=True) + y = helper.make_node("Slice", ["data", *slice_inputs], ["out"]) + nodes.append(y) + graph = helper.make_graph( + nodes, + "slice_test", + inputs=inputs, + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], + initializer=initializer, + ) + model = helper.make_model(graph, producer_name="slice_test") + verify_with_ort_with_inputs( + model, [indata], opset=10, freeze_params=True, use_vm=True, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_slice(): x = np.random.randn(20, 10, 5).astype(np.float32) _test_slice_iteration_v1(x, x[0:3, 0:10], starts=(0, 0), ends=(3, 10), axes=(0, 1)) _test_slice_iteration_v1(x, x[:, :, 3:4], starts=(0, 0, 3), ends=(20, 10, 4)) @@ -900,7 +899,9 @@ def test_slice(): ) -def _test_onnx_op_elementwise(inshape, outfunc, npargs, dtype, opname, kwargs, opset=None): +def _test_onnx_op_elementwise( + target, dev, inshape, outfunc, npargs, dtype, opname, kwargs, opset=None +): indata = np.random.uniform(-1, 1, size=inshape).astype(dtype) outdata = outfunc(indata, **npargs) @@ -914,22 +915,26 @@ def _test_onnx_op_elementwise(inshape, outfunc, npargs, dtype, opname, kwargs, o ) model = helper.make_model(graph, producer_name=opname + "_test") - verify_with_ort_with_inputs(model, [indata], [outdata.shape], opset=opset, dtype=dtype) + verify_with_ort_with_inputs( + model, [indata], [outdata.shape], opset=opset, dtype=dtype, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_floor(): - _test_onnx_op_elementwise((2, 4, 5, 6), np.floor, {}, "float32", "Floor", {}) +@tvm.testing.parametrize_targets +def test_floor(target, dev): + _test_onnx_op_elementwise(target, dev, (2, 4, 5, 6), np.floor, {}, "float32", "Floor", {}) -@tvm.testing.uses_gpu -def test_ceil(): - _test_onnx_op_elementwise((2, 4, 5, 6), np.ceil, {}, "float32", "Ceil", {}) +@tvm.testing.parametrize_targets +def test_ceil(target, dev): + _test_onnx_op_elementwise(target, dev, (2, 4, 5, 6), np.ceil, {}, "float32", "Ceil", {}) -@tvm.testing.uses_gpu -def test_clip(): +@tvm.testing.parametrize_targets +def test_clip(target, dev): _test_onnx_op_elementwise( + target, + dev, (2, 4, 5, 6), np.clip, {"a_min": -1.0, "a_max": 1.0}, @@ -940,6 +945,8 @@ def test_clip(): ) _test_onnx_op_elementwise( + target, + dev, (2, 4, 5, 6), np.clip, {"a_min": -np.inf, "a_max": 1.0}, @@ -950,6 +957,8 @@ def test_clip(): ) _test_onnx_op_elementwise( + target, + dev, (2, 4, 5, 6), np.clip, {"a_min": -1.0, "a_max": np.inf}, @@ -960,8 +969,8 @@ def test_clip(): ) -@tvm.testing.uses_gpu -def test_clip_min_max_as_inputs(): +@tvm.testing.parametrize_targets +def test_clip_min_max_as_inputs(target, dev): input_shape = (2, 4, 5, 6) nodes = [ make_constant_node("min", onnx.TensorProto.FLOAT, (), [0.0]), @@ -977,15 +986,15 @@ def test_clip_min_max_as_inputs(): ) model = helper.make_model(graph, producer_name="clip_test") - verify_with_ort(model, [input_shape], out_shape=[input_shape]) + verify_with_ort(model, [input_shape], out_shape=[input_shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_round(): - _test_onnx_op_elementwise((2, 4, 5, 6), np.round, {}, "float32", "Round", {}) +@tvm.testing.parametrize_targets +def test_round(target, dev): + _test_onnx_op_elementwise(target, dev, (2, 4, 5, 6), np.round, {}, "float32", "Round", {}) -def _test_finite_ops(inshape, outfunc, npargs, dtype, opname, kwargs): +def _test_finite_ops(target, dev, inshape, outfunc, npargs, dtype, opname, kwargs): indata = np.random.choice(a=[np.nan, np.inf, -np.inf, 0.5, 1.0, 0], size=inshape).astype(dtype) outdata = outfunc(indata, **npargs) @@ -999,50 +1008,53 @@ def _test_finite_ops(inshape, outfunc, npargs, dtype, opname, kwargs): ) model = helper.make_model(graph, producer_name=opname + "_test") - verify_with_ort_with_inputs(model, [indata], [outdata.shape], dtype=dtype) - + verify_with_ort_with_inputs( + model, [indata], [outdata.shape], dtype=dtype, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_isinf(): - _test_finite_ops((2, 4, 5, 6), np.isinf, {}, "float32", "IsInf", {}) +@tvm.testing.parametrize_targets +def test_isinf(target, dev): + _test_finite_ops(target, dev, (2, 4, 5, 6), np.isinf, {}, "float32", "IsInf", {}) -@tvm.testing.uses_gpu -def test_isnan(): - _test_finite_ops((2, 4, 5, 6), np.isnan, {}, "float32", "IsNaN", {}) +@tvm.testing.parametrize_targets +def test_isnan(target, dev): + _test_finite_ops(target, dev, (2, 4, 5, 6), np.isnan, {}, "float32", "IsNaN", {}) -def verify_gather_nd(in_shape, indices, out_shape, dtype="float32", batch_dims=0, opset=11): - x = np.random.uniform(size=in_shape).astype(dtype) - indices = np.array(indices, dtype="int64") - y = helper.make_node("GatherND", ["in", "indices"], ["out"]) +@tvm.testing.parametrize_targets +def test_gather_nd(target, dev): + def verify_gather_nd(in_shape, indices, out_shape, dtype="float32", batch_dims=0, opset=11): + x = np.random.uniform(size=in_shape).astype(dtype) + indices = np.array(indices, dtype="int64") - if opset >= 12: - batch_dims_attr = helper.make_attribute("batch_dims", batch_dims) - y.attribute.append(batch_dims_attr) + y = helper.make_node("GatherND", ["in", "indices"], ["out"]) - graph = helper.make_graph( - [y], - "gather_test", - inputs=[ - helper.make_tensor_value_info( - "in", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(in_shape) - ), - helper.make_tensor_value_info("indices", TensorProto.INT64, list(indices.shape)), - ], - outputs=[ - helper.make_tensor_value_info( - "out", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(out_shape) - ) - ], - ) - model = helper.make_model(graph, producer_name="gather_test") - verify_with_ort_with_inputs(model, [x, indices], [out_shape], opset=opset) + if opset >= 12: + batch_dims_attr = helper.make_attribute("batch_dims", batch_dims) + y.attribute.append(batch_dims_attr) + graph = helper.make_graph( + [y], + "gather_test", + inputs=[ + helper.make_tensor_value_info( + "in", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(in_shape) + ), + helper.make_tensor_value_info("indices", TensorProto.INT64, list(indices.shape)), + ], + outputs=[ + helper.make_tensor_value_info( + "out", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], list(out_shape) + ) + ], + ) + model = helper.make_model(graph, producer_name="gather_test") + verify_with_ort_with_inputs( + model, [x, indices], [out_shape], opset=opset, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_gather_nd(): verify_gather_nd([2, 2], [[0, 0], [1, 1]], [2], "int32") verify_gather_nd([2, 2], [[1], [0]], [2, 2]) verify_gather_nd([2, 2, 2], [[0, 1], [1, 0]], [2, 2]) @@ -1059,8 +1071,8 @@ def test_gather_nd(): ) -@tvm.testing.uses_gpu -def test_onehot(): +@tvm.testing.parametrize_targets +def test_onehot(target, dev): indices_shape = [10] indices_array = np.random.randint(low=0, high=9, size=indices_shape, dtype="int32") depth = 10 @@ -1083,60 +1095,65 @@ def test_onehot(): model = helper.make_model(graph, producer_name="onehot_test") # TODO(jwfromm): Replace test against np with test against onnxrt once we update versions. - for target, dev in tvm.testing.enabled_targets(): - tvm_out = get_tvm_output_with_vm( - model, [indices_array, np.array([depth]).astype("int32"), values], target, dev - ) - tvm.testing.assert_allclose(out_np, tvm_out, rtol=1e-5, atol=1e-5) - + tvm_out = get_tvm_output_with_vm( + model, [indices_array, np.array([depth]).astype("int32"), values], target, dev + ) + tvm.testing.assert_allclose(out_np, tvm_out, rtol=1e-5, atol=1e-5) -def verify_gemm(a_shape, b_shape, c_shape=None, freeze_params=False, dtype="float32"): - out_shape = [a_shape[0], b_shape[1]] - a_array = np.random.uniform(size=a_shape).astype(dtype) - b_array = np.random.uniform(size=b_shape).astype(dtype) - input_names = ["a", "b"] - ONNX_DTYPE = mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)] - input_nodes = [ - helper.make_tensor_value_info("a", ONNX_DTYPE, list(a_shape)), - helper.make_tensor_value_info("b", ONNX_DTYPE, list(b_shape)), - ] - input_values = [a_array, b_array] - if c_shape is not None: - c_array = np.random.uniform(size=c_shape).astype(dtype) - input_names.append("c") - input_nodes.append(helper.make_tensor_value_info("c", ONNX_DTYPE, list(c_shape))) - input_values.append(c_array) - gemm_node = helper.make_node("Gemm", input_names, ["out"]) +@tvm.testing.parametrize_targets +def test_gemm(target, dev): + def verify_gemm(a_shape, b_shape, c_shape=None, freeze_params=False, dtype="float32"): + out_shape = [a_shape[0], b_shape[1]] + a_array = np.random.uniform(size=a_shape).astype(dtype) + b_array = np.random.uniform(size=b_shape).astype(dtype) + input_names = ["a", "b"] + ONNX_DTYPE = mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)] + input_nodes = [ + helper.make_tensor_value_info("a", ONNX_DTYPE, list(a_shape)), + helper.make_tensor_value_info("b", ONNX_DTYPE, list(b_shape)), + ] + input_values = [a_array, b_array] + if c_shape is not None: + c_array = np.random.uniform(size=c_shape).astype(dtype) + input_names.append("c") + input_nodes.append(helper.make_tensor_value_info("c", ONNX_DTYPE, list(c_shape))) + input_values.append(c_array) - graph = helper.make_graph( - [gemm_node], - "gemm_test", - inputs=input_nodes, - outputs=[helper.make_tensor_value_info("out", ONNX_DTYPE, list(out_shape))], - ) + gemm_node = helper.make_node("Gemm", input_names, ["out"]) - model = helper.make_model(graph, producer_name="gemm_test") - atol = 1e-5 - rtol = 1e-5 - if dtype == "float16": - atol = 1e-3 - rtol = 1e-3 - verify_with_ort_with_inputs( - model, input_values, freeze_params=freeze_params, dtype=dtype, atol=atol, rtol=rtol - ) + graph = helper.make_graph( + [gemm_node], + "gemm_test", + inputs=input_nodes, + outputs=[helper.make_tensor_value_info("out", ONNX_DTYPE, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="gemm_test") + atol = 1e-5 + rtol = 1e-5 + if dtype == "float16": + atol = 1e-3 + rtol = 1e-3 + verify_with_ort_with_inputs( + model, + input_values, + freeze_params=freeze_params, + dtype=dtype, + atol=atol, + rtol=rtol, + target=target, + dev=dev, + ) -@tvm.testing.uses_gpu -def test_gemm(): verify_gemm(a_shape=(4, 3), b_shape=(3, 4)) verify_gemm(a_shape=(4, 3), b_shape=(3, 4), c_shape=(4,)) verify_gemm(a_shape=(4, 3), b_shape=(3, 4), c_shape=(4,), freeze_params=True) verify_gemm(a_shape=(4, 3), b_shape=(3, 4), c_shape=(4,), freeze_params=True, dtype="float16") -@tvm.testing.uses_gpu -def test_matmul(): +@tvm.testing.parametrize_targets +def test_matmul(target, dev): a_shape = (4, 3) b_shape = (3, 4) out_shape = [a_shape[0], b_shape[1]] @@ -1157,40 +1174,39 @@ def test_matmul(): ) model = helper.make_model(graph, producer_name="matmul_test") - verify_with_ort_with_inputs(model, [a_array, b_array]) + verify_with_ort_with_inputs(model, [a_array, b_array], target=target, dev=dev) -def verify_batch_matmul(a_shape, b_shape, out_shape, target, dev): - a_array = np.random.uniform(size=a_shape).astype("float32") - b_array = np.random.uniform(size=b_shape).astype("float32") - - mul_node = helper.make_node("MatMul", ["a", "b"], ["out"]) +@tvm.testing.parametrize_targets +def test_batch_matmul(target, dev): + def verify_batch_matmul(a_shape, b_shape, out_shape): + a_array = np.random.uniform(size=a_shape).astype("float32") + b_array = np.random.uniform(size=b_shape).astype("float32") - graph = helper.make_graph( - [mul_node], - "matmul_test", - inputs=[ - helper.make_tensor_value_info("a", TensorProto.FLOAT, list(a_shape)), - helper.make_tensor_value_info("b", TensorProto.FLOAT, list(b_shape)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, out_shape)], - ) + mul_node = helper.make_node("MatMul", ["a", "b"], ["out"]) - model = helper.make_model(graph, producer_name="matmul_test") - verify_with_ort_with_inputs(model, [a_array, b_array], use_vm=True, targets=[target]) + graph = helper.make_graph( + [mul_node], + "matmul_test", + inputs=[ + helper.make_tensor_value_info("a", TensorProto.FLOAT, list(a_shape)), + helper.make_tensor_value_info("b", TensorProto.FLOAT, list(b_shape)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, out_shape)], + ) + model = helper.make_model(graph, producer_name="matmul_test") + verify_with_ort_with_inputs(model, [a_array, b_array], use_vm=True, target=target, dev=dev) -@tvm.testing.uses_gpu -def test_batch_matmul(target, dev): - verify_batch_matmul((2, 3, 4, 3), (2, 3, 3, 4), (2, 3, 4, 4), target, dev) - verify_batch_matmul((2, 4, 3), (3, 4), (2, 4, 4), target, dev) - verify_batch_matmul((2, 3, 4, 3), (3, 4), (2, 3, 4, 4), target, dev) + verify_batch_matmul((2, 3, 4, 3), (2, 3, 3, 4), (2, 3, 4, 4)) + verify_batch_matmul((2, 4, 3), (3, 4), (2, 4, 4)) + verify_batch_matmul((2, 3, 4, 3), (3, 4), (2, 3, 4, 4)) # Test implicit broadcasting. - verify_batch_matmul((4, 3), (2, 3, 4), (2, 4, 4), target, dev) - verify_batch_matmul((2, 4, 3), (1, 3, 4), (2, 4, 4), target, dev) - verify_batch_matmul((1, 4, 3), (2, 3, 4), (2, 4, 4), target, dev) - verify_batch_matmul((4, 32, 16), (16, 32), (4, 32, 32), target, dev) - verify_batch_matmul((4, 32, 16, 32), (32, 16), (4, 32, 16, 16), target, dev) + verify_batch_matmul((4, 3), (2, 3, 4), (2, 4, 4)) + verify_batch_matmul((2, 4, 3), (1, 3, 4), (2, 4, 4)) + verify_batch_matmul((1, 4, 3), (2, 3, 4), (2, 4, 4)) + verify_batch_matmul((4, 32, 16), (16, 32), (4, 32, 32)) + verify_batch_matmul((4, 32, 16, 32), (32, 16), (4, 32, 16, 16)) def verify_simple_dynamic_model(a_shape, b_shape, target, dev): @@ -1243,70 +1259,71 @@ def test_batch_matmul_dynamic_model(target, dev): verify_simple_dynamic_model((2, 3, 4, 3), (3, 4), target, dev) -def verify_lrn(shape, nsize, dtype, alpha=None, beta=None, bias=None): - in_array = np.random.uniform(size=shape).astype(dtype) - - if alpha == None and beta == None and bias == None: - alpha = 0.0001 - beta = 0.75 - bias = 1.0 - node = onnx.helper.make_node("LRN", inputs=["in"], outputs=["out"], size=nsize) - else: - node = onnx.helper.make_node( - "LRN", inputs=["in"], outputs=["out"], alpha=alpha, beta=beta, bias=bias, size=nsize - ) +@tvm.testing.parametrize_targets +def test_lrn(target, dev): + def verify_lrn(shape, nsize, dtype, alpha=None, beta=None, bias=None): + in_array = np.random.uniform(size=shape).astype(dtype) - graph = helper.make_graph( - [node], - "lrn_test", - inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(shape))], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(shape))], - ) - model = helper.make_model(graph, producer_name="lrn_test") - verify_with_ort_with_inputs(model, [in_array]) + if alpha == None and beta == None and bias == None: + alpha = 0.0001 + beta = 0.75 + bias = 1.0 + node = onnx.helper.make_node("LRN", inputs=["in"], outputs=["out"], size=nsize) + else: + node = onnx.helper.make_node( + "LRN", inputs=["in"], outputs=["out"], alpha=alpha, beta=beta, bias=bias, size=nsize + ) + graph = helper.make_graph( + [node], + "lrn_test", + inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(shape))], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(shape))], + ) + model = helper.make_model(graph, producer_name="lrn_test") + verify_with_ort_with_inputs(model, [in_array], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_lrn(): verify_lrn((5, 5, 5, 5), 3, "float32") verify_lrn((5, 5, 5, 5), 3, "float32", alpha=0.0002, beta=0.5, bias=2.0) -def verify_instance_norm(shape, axis=1): - x = np.random.randn(*shape).astype(np.float32) - gamma = np.random.randn(shape[1]).astype(np.float32) - beta = np.random.randn(shape[1]).astype(np.float32) - epsilon = 1e-5 - - node = onnx.helper.make_node( - "InstanceNormalization", - inputs=["x", "gamma", "beta"], - outputs=["y"], - epsilon=epsilon, - ) - graph = helper.make_graph( - [node], - "instance_norm_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(shape)), - helper.make_tensor_value_info("gamma", TensorProto.FLOAT, (shape[1],)), - helper.make_tensor_value_info("beta", TensorProto.FLOAT, (shape[1],)), - ], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(shape))], - ) - model = helper.make_model(graph, producer_name="instance_norm_test") - verify_with_ort_with_inputs(model, [x, gamma, beta], out_shape=[shape]) +@tvm.testing.parametrize_targets +def test_instance_norm(target, dev): + def verify_instance_norm(shape, axis=1): + x = np.random.randn(*shape).astype(np.float32) + gamma = np.random.randn(shape[1]).astype(np.float32) + beta = np.random.randn(shape[1]).astype(np.float32) + epsilon = 1e-5 - -@tvm.testing.uses_gpu -def test_instance_norm(): - verify_instance_norm((2, 3, 4, 5)) + node = onnx.helper.make_node( + "InstanceNormalization", + inputs=["x", "gamma", "beta"], + outputs=["y"], + epsilon=epsilon, + ) + graph = helper.make_graph( + [node], + "instance_norm_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(shape)), + helper.make_tensor_value_info("gamma", TensorProto.FLOAT, (shape[1],)), + helper.make_tensor_value_info("beta", TensorProto.FLOAT, (shape[1],)), + ], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(shape))], + ) + model = helper.make_model(graph, producer_name="instance_norm_test") + verify_with_ort_with_inputs( + model, [x, gamma, beta], out_shape=[shape], target=target, dev=dev + ) + + verify_instance_norm((2, 3, 4, 5)) verify_instance_norm((32, 64, 80, 64)) verify_instance_norm((8, 6, 5)) verify_instance_norm((8, 7, 6, 5, 4)) -def verify_upsample_nearest(): +@tvm.testing.parametrize_targets +def test_upsample_nearest(target, dev): scale = 2 in_shape = (1, 1, 3, 3) out_shape = (1, 1, 3 * scale, 3 * scale) @@ -1322,10 +1339,11 @@ def verify_upsample_nearest(): ) model = helper.make_model(graph, producer_name="upsample_nearest_test") - verify_with_ort_with_inputs(model, [in_array], [out_shape], opset=7) + verify_with_ort_with_inputs(model, [in_array], [out_shape], opset=7, target=target, dev=dev) -def verify_upsample3d_nearest(): +@tvm.testing.parametrize_targets +def test_upsample3d_nearest(target, dev): scale = 2 in_shape = (1, 1, 3, 3, 3) out_shape = (1, 1, 3 * scale, 3 * scale, 3 * scale) @@ -1344,10 +1362,11 @@ def verify_upsample3d_nearest(): model = helper.make_model(graph, producer_name="upsample_nearest_test") # Upsample is deprecated after opset 9 - verify_with_ort_with_inputs(model, [in_array], [out_shape], opset=7) + verify_with_ort_with_inputs(model, [in_array], [out_shape], opset=7, target=target, dev=dev) -def verify_upsample_bilinear(): +@tvm.testing.parametrize_targets +def test_upsample_bilinear(target, dev): scale = 2 in_shape = (1, 1, 3, 3) out_shape = (1, 1, 3 * scale, 3 * scale) @@ -1363,10 +1382,11 @@ def verify_upsample_bilinear(): ) model = helper.make_model(graph, producer_name="upsample_bilinear_test") - verify_with_ort_with_inputs(model, [in_array], [out_shape], opset=7) + verify_with_ort_with_inputs(model, [in_array], [out_shape], opset=7, target=target, dev=dev) -def verify_upsample3d_trilinear(): +@tvm.testing.parametrize_targets +def test_upsample3d_trilinear(target, dev): scale = 2 in_shape = (1, 1, 3, 3, 3) out_shape = (1, 1, 3 * scale, 3 * scale, 3 * scale) @@ -1404,191 +1424,181 @@ def verify_upsample3d_trilinear(): model = helper.make_model(graph, producer_name="upsample_trilinear_test") # TODO(jwfromm): Trilinear upsampling not supported in 1.0.0 onnxruntime. # Replace topi comparison with verify_with_ort once we update. - for target, dev in tvm.testing.enabled_targets(): - tvm_out = get_tvm_output(model, in_array, target, dev, out_shape, "float32") - tvm.testing.assert_allclose(out_array, tvm_out, rtol=1e-5, atol=1e-5) - - -@tvm.testing.uses_gpu -def test_upsample(): - verify_upsample_nearest() - verify_upsample_bilinear() - verify_upsample3d_nearest() - verify_upsample3d_trilinear() + tvm_out = get_tvm_output(model, in_array, target, dev, out_shape, "float32") + tvm.testing.assert_allclose(out_array, tvm_out, rtol=1e-5, atol=1e-5) -def verify_softmax(inshape, axis): - opname = "Softmax" - indata = np.random.uniform(size=inshape).astype(np.float32) - outshape = inshape - y = helper.make_node(opname, ["in"], ["out"]) - if axis is not None: - axis_attr = helper.make_attribute("axis", axis) - y.attribute.append(axis_attr) +@tvm.testing.parametrize_targets +def test_softmax(target, dev): + def verify_softmax(inshape, axis): + opname = "Softmax" + indata = np.random.uniform(size=inshape).astype(np.float32) + outshape = inshape + y = helper.make_node(opname, ["in"], ["out"]) + if axis is not None: + axis_attr = helper.make_attribute("axis", axis) + y.attribute.append(axis_attr) - graph = helper.make_graph( - [y], - opname + "_test", - inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(indata.shape))], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outshape))], - ) - - model = helper.make_model(graph, producer_name=opname + "_test") - verify_with_ort_with_inputs(model, [indata]) + graph = helper.make_graph( + [y], + opname + "_test", + inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(indata.shape))], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outshape))], + ) + model = helper.make_model(graph, producer_name=opname + "_test") + verify_with_ort_with_inputs(model, [indata], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_softmax(): verify_softmax((1, 10), None) verify_softmax((1, 10), 1) -def verify_min(input_dim): - dtype = "float32" - - a_np1 = np.random.uniform(size=input_dim).astype(dtype) - a_np2 = np.random.uniform(size=input_dim).astype(dtype) - a_np3 = np.random.uniform(size=input_dim).astype(dtype) +@tvm.testing.parametrize_targets +def test_forward_min(target, dev): + def verify_min(input_dim): + dtype = "float32" - min_node = helper.make_node("Min", ["a_np1", "a_np2", "a_np3"], ["out"]) + a_np1 = np.random.uniform(size=input_dim).astype(dtype) + a_np2 = np.random.uniform(size=input_dim).astype(dtype) + a_np3 = np.random.uniform(size=input_dim).astype(dtype) - graph = helper.make_graph( - [min_node], - "Min_test", - inputs=[ - helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim)), - helper.make_tensor_value_info("a_np2", TensorProto.FLOAT, list(input_dim)), - helper.make_tensor_value_info("a_np3", TensorProto.FLOAT, list(input_dim)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], - ) + min_node = helper.make_node("Min", ["a_np1", "a_np2", "a_np3"], ["out"]) - model = helper.make_model(graph, producer_name="Min_test") - verify_with_ort_with_inputs(model, [a_np1, a_np2, a_np3]) + graph = helper.make_graph( + [min_node], + "Min_test", + inputs=[ + helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim)), + helper.make_tensor_value_info("a_np2", TensorProto.FLOAT, list(input_dim)), + helper.make_tensor_value_info("a_np3", TensorProto.FLOAT, list(input_dim)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], + ) + model = helper.make_model(graph, producer_name="Min_test") + verify_with_ort_with_inputs(model, [a_np1, a_np2, a_np3], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_forward_min(): verify_min((1, 3, 20, 20)) verify_min((20, 20)) -def verify_max(input_dim): - dtype = "float32" - - a_np1 = np.random.uniform(size=input_dim).astype(dtype) - a_np2 = np.random.uniform(size=input_dim).astype(dtype) - a_np3 = np.random.uniform(size=input_dim).astype(dtype) +@tvm.testing.parametrize_targets +def test_forward_max(target, dev): + def verify_max(input_dim): + dtype = "float32" - max_node = helper.make_node("Max", ["a_np1", "a_np2", "a_np3"], ["out"]) + a_np1 = np.random.uniform(size=input_dim).astype(dtype) + a_np2 = np.random.uniform(size=input_dim).astype(dtype) + a_np3 = np.random.uniform(size=input_dim).astype(dtype) - graph = helper.make_graph( - [max_node], - "Max_test", - inputs=[ - helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim)), - helper.make_tensor_value_info("a_np2", TensorProto.FLOAT, list(input_dim)), - helper.make_tensor_value_info("a_np3", TensorProto.FLOAT, list(input_dim)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], - ) + max_node = helper.make_node("Max", ["a_np1", "a_np2", "a_np3"], ["out"]) - model = helper.make_model(graph, producer_name="Max_test") - verify_with_ort_with_inputs(model, [a_np1, a_np2, a_np3]) + graph = helper.make_graph( + [max_node], + "Max_test", + inputs=[ + helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim)), + helper.make_tensor_value_info("a_np2", TensorProto.FLOAT, list(input_dim)), + helper.make_tensor_value_info("a_np3", TensorProto.FLOAT, list(input_dim)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], + ) + model = helper.make_model(graph, producer_name="Max_test") + verify_with_ort_with_inputs(model, [a_np1, a_np2, a_np3], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_forward_max(): verify_max((1, 3, 20, 20)) verify_max((20, 20)) -def verify_mean(input_dim): - dtype = "float32" +@tvm.testing.parametrize_targets +def test_forward_mean(target, dev): + def verify_mean(input_dim): + dtype = "float32" - a_np1 = np.random.uniform(size=input_dim).astype(dtype) - a_np2 = np.random.uniform(size=input_dim).astype(dtype) - a_np3 = np.random.uniform(size=input_dim).astype(dtype) + a_np1 = np.random.uniform(size=input_dim).astype(dtype) + a_np2 = np.random.uniform(size=input_dim).astype(dtype) + a_np3 = np.random.uniform(size=input_dim).astype(dtype) - mean_node = helper.make_node("Mean", ["a_np1", "a_np2", "a_np3"], ["out"]) + mean_node = helper.make_node("Mean", ["a_np1", "a_np2", "a_np3"], ["out"]) - graph = helper.make_graph( - [mean_node], - "Mean_test", - inputs=[ - helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim)), - helper.make_tensor_value_info("a_np2", TensorProto.FLOAT, list(input_dim)), - helper.make_tensor_value_info("a_np3", TensorProto.FLOAT, list(input_dim)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], - ) - - model = helper.make_model(graph, producer_name="Mean_test") - verify_with_ort_with_inputs(model, [a_np1, a_np2, a_np3]) + graph = helper.make_graph( + [mean_node], + "Mean_test", + inputs=[ + helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim)), + helper.make_tensor_value_info("a_np2", TensorProto.FLOAT, list(input_dim)), + helper.make_tensor_value_info("a_np3", TensorProto.FLOAT, list(input_dim)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], + ) + model = helper.make_model(graph, producer_name="Mean_test") + verify_with_ort_with_inputs(model, [a_np1, a_np2, a_np3], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_forward_mean(): verify_mean((1, 3, 20, 20)) verify_mean((20, 20)) -def verify_hardsigmoid(input_dim, alpha, beta): - dtype = "float32" - - a_np1 = np.random.uniform(size=input_dim).astype(dtype) +@tvm.testing.parametrize_targets +def test_forward_hardsigmoid(target, dev): + def verify_hardsigmoid(input_dim, alpha, beta): + dtype = "float32" - hardsigmoid_node = helper.make_node("HardSigmoid", ["a_np1"], ["out"], alpha=alpha, beta=beta) + a_np1 = np.random.uniform(size=input_dim).astype(dtype) - graph = helper.make_graph( - [hardsigmoid_node], - "HardSigmoid_test", - inputs=[helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim))], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], - ) + hardsigmoid_node = helper.make_node( + "HardSigmoid", ["a_np1"], ["out"], alpha=alpha, beta=beta + ) - model = helper.make_model(graph, producer_name="HardSigmoid_test") - verify_with_ort_with_inputs(model, [a_np1]) + graph = helper.make_graph( + [hardsigmoid_node], + "HardSigmoid_test", + inputs=[helper.make_tensor_value_info("a_np1", TensorProto.FLOAT, list(input_dim))], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(input_dim))], + ) + model = helper.make_model(graph, producer_name="HardSigmoid_test") + verify_with_ort_with_inputs(model, [a_np1], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_forward_hardsigmoid(): verify_hardsigmoid((1, 3, 20, 20), 0.5, 0.6) verify_hardsigmoid((20, 20), 0.3, 0.4) -def verify_argreduce(input_dim, op_name, axis=None, keepdims=None): - a_np1 = np.random.uniform(-10, 10, input_dim).astype(np.int32) - out_shape = list(a_np1.shape) - def_axis = axis if axis is not None else 0 - if keepdims == 1 or keepdims == None: - out_shape[def_axis] = 1 - else: - out_shape.pop(def_axis) - - node = onnx.helper.make_node(op_name, inputs=["a_np1"], outputs=["out"]) +# TODO (mbrookhart, electriclilies) Fix argmin on GPU and enable this test +@tvm.testing.parametrize_targets +def test_forward_arg_min_max(target, dev): + if "cuda" in target: + pytest.skip("Fails on CUDA") + + def verify_argreduce(input_dim, op_name, axis=None, keepdims=None): + a_np1 = np.random.uniform(-10, 10, input_dim).astype(np.int32) + out_shape = list(a_np1.shape) + def_axis = axis if axis is not None else 0 + if keepdims == 1 or keepdims == None: + out_shape[def_axis] = 1 + else: + out_shape.pop(def_axis) - if keepdims is not None: - keepdims_attr = helper.make_attribute("keepdims", keepdims) - node.attribute.append(keepdims_attr) - if axis is not None: - axis_attr = helper.make_attribute("axis", axis) - node.attribute.append(axis_attr) + node = onnx.helper.make_node(op_name, inputs=["a_np1"], outputs=["out"]) - graph = helper.make_graph( - [node], - "argreduce_test", - inputs=[helper.make_tensor_value_info("a_np1", TensorProto.INT32, list(a_np1.shape))], - outputs=[helper.make_tensor_value_info("out", TensorProto.INT64, list(out_shape))], - ) + if keepdims is not None: + keepdims_attr = helper.make_attribute("keepdims", keepdims) + node.attribute.append(keepdims_attr) + if axis is not None: + axis_attr = helper.make_attribute("axis", axis) + node.attribute.append(axis_attr) - model = helper.make_model(graph, producer_name="argreduce_test") - verify_with_ort_with_inputs(model, [a_np1]) + graph = helper.make_graph( + [node], + "argreduce_test", + inputs=[helper.make_tensor_value_info("a_np1", TensorProto.INT32, list(a_np1.shape))], + outputs=[helper.make_tensor_value_info("out", TensorProto.INT64, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="argreduce_test") + verify_with_ort_with_inputs(model, [a_np1], target=target, dev=dev) -# TODO (mbrookhart, electriclilies) Fix argmin on GPU and enable this test -# @tvm.testing.uses_gpu -def test_forward_arg_min_max(): """Verify argmin and argmax""" verify_argreduce([3, 4, 4], "ArgMin") verify_argreduce([3, 4, 4], "ArgMax") @@ -1602,122 +1612,126 @@ def test_forward_arg_min_max(): verify_argreduce([3, 4, 4], "ArgMax", axis, keepdims) -def verify_constantofshape(input_dim, value, dtype): - fill_node = helper.make_node( - "ConstantOfShape", - ["input"], - ["output"], - value=helper.make_tensor( - "value", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], (1,), (value,) - ), - ) - - inputs = [helper.make_tensor_value_info("input", TensorProto.INT64, [len(input_dim)])] +@tvm.testing.parametrize_targets +def test_constantofshape(target, dev): + def verify_constantofshape(input_dim, value, dtype): + fill_node = helper.make_node( + "ConstantOfShape", + ["input"], + ["output"], + value=helper.make_tensor( + "value", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], (1,), (value,) + ), + ) - graph = helper.make_graph( - [fill_node], - "fill_test", - inputs, - outputs=[ - helper.make_tensor_value_info( - "output", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], input_dim - ) - ], - ) + inputs = [helper.make_tensor_value_info("input", TensorProto.INT64, [len(input_dim)])] - model = helper.make_model(graph, producer_name="fill_test") - input_np = np.array(input_dim).astype("int64") - verify_with_ort_with_inputs(model, [input_np], use_vm=True) + graph = helper.make_graph( + [fill_node], + "fill_test", + inputs, + outputs=[ + helper.make_tensor_value_info( + "output", mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)], input_dim + ) + ], + ) + model = helper.make_model(graph, producer_name="fill_test") + input_np = np.array(input_dim).astype("int64") + verify_with_ort_with_inputs(model, [input_np], use_vm=True, target=target, dev=dev) -@tvm.testing.uses_gpu -def test_constantofshape(): verify_constantofshape((2, 3, 4, 5), 10, "float32") verify_constantofshape((3, 3), 0, "int32") verify_constantofshape((1, 2, 3), -1, "float32") -def verify_pad(indata, pads, mode="constant", value=0.0): - indata = np.array(indata).astype(np.float32) - # numpy expect result - len_dim = len(pads) // 2 - np_pads = [(pads[i], pads[i + len_dim]) for i in range(len_dim)] - # onnx graph - if mode in ["edge", "reflect"]: - outdata = np.pad(indata, pad_width=np_pads, mode=mode) - node = helper.make_node( - "Pad", - inputs=["input"], - outputs=["output"], - mode=mode, - pads=pads, - ) - else: - outdata = np.pad(indata, pad_width=np_pads, mode="constant", constant_values=value) - node = helper.make_node( - "Pad", inputs=["input"], outputs=["output"], mode="constant", pads=pads, value=value - ) - graph = helper.make_graph( - [node], - "pad_test", - inputs=[helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape))], - outputs=[helper.make_tensor_value_info("output", TensorProto.FLOAT, list(outdata.shape))], - ) - model = helper.make_model(graph, producer_name="pad_test") - verify_with_ort_with_inputs(model, [indata], [outdata.shape], dtype="float32", opset=2) - - -def verify_pad_v11(indata, pads, mode="constant", value=0.0): - indata = np.array(indata).astype(np.float32) - # numpy expect result - len_dim = len(pads) // 2 - np_pads = [(pads[i], pads[i + len_dim]) for i in range(len_dim)] - pads = np.array(pads) - # onnx graph - if mode in ["edge", "reflect"]: - inputs = [indata] - outdata = np.pad(indata, pad_width=np_pads, mode=mode) - node = helper.make_node("Pad", inputs=["input", "pads"], outputs=["output"], mode=mode) +@tvm.testing.parametrize_targets +def test_pad(target, dev): + def verify_pad(indata, pads, mode="constant", value=0.0): + indata = np.array(indata).astype(np.float32) + # numpy expect result + len_dim = len(pads) // 2 + np_pads = [(pads[i], pads[i + len_dim]) for i in range(len_dim)] + # onnx graph + if mode in ["edge", "reflect"]: + outdata = np.pad(indata, pad_width=np_pads, mode=mode) + node = helper.make_node( + "Pad", + inputs=["input"], + outputs=["output"], + mode=mode, + pads=pads, + ) + else: + outdata = np.pad(indata, pad_width=np_pads, mode="constant", constant_values=value) + node = helper.make_node( + "Pad", inputs=["input"], outputs=["output"], mode="constant", pads=pads, value=value + ) graph = helper.make_graph( [node], "pad_test", - inputs=[ - helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape)), - helper.make_tensor_value_info("pads", TensorProto.INT64, (len(pads),)), - ], - initializer=[helper.make_tensor("pads", TensorProto.INT64, (len(pads),), pads)], + inputs=[helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape))], outputs=[ helper.make_tensor_value_info("output", TensorProto.FLOAT, list(outdata.shape)) ], ) - else: - inputs = [indata] - outdata = np.pad(indata, pad_width=np_pads, mode="constant", constant_values=value) - node = helper.make_node( - "Pad", inputs=["input", "pads", "constant_value"], outputs=["output"], mode="constant" - ) - graph = helper.make_graph( - [node], - "pad_test", - inputs=[ - helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape)), - helper.make_tensor_value_info("pads", TensorProto.INT64, (len(pads),)), - helper.make_tensor_value_info("constant_value", TensorProto.FLOAT, (1,)), - ], - initializer=[ - helper.make_tensor("pads", TensorProto.INT64, (len(pads),), pads), - helper.make_tensor("constant_value", TensorProto.FLOAT, (1,), [value]), - ], - outputs=[ - helper.make_tensor_value_info("output", TensorProto.FLOAT, list(outdata.shape)) - ], + model = helper.make_model(graph, producer_name="pad_test") + verify_with_ort_with_inputs( + model, [indata], [outdata.shape], dtype="float32", opset=2, target=target, dev=dev ) - model = helper.make_model(graph, producer_name="pad_test") - verify_with_ort_with_inputs(model, inputs, opset=11, use_vm=True) + def verify_pad_v11(indata, pads, mode="constant", value=0.0): + indata = np.array(indata).astype(np.float32) + # numpy expect result + len_dim = len(pads) // 2 + np_pads = [(pads[i], pads[i + len_dim]) for i in range(len_dim)] + pads = np.array(pads) + # onnx graph + if mode in ["edge", "reflect"]: + inputs = [indata] + outdata = np.pad(indata, pad_width=np_pads, mode=mode) + node = helper.make_node("Pad", inputs=["input", "pads"], outputs=["output"], mode=mode) + graph = helper.make_graph( + [node], + "pad_test", + inputs=[ + helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape)), + helper.make_tensor_value_info("pads", TensorProto.INT64, (len(pads),)), + ], + initializer=[helper.make_tensor("pads", TensorProto.INT64, (len(pads),), pads)], + outputs=[ + helper.make_tensor_value_info("output", TensorProto.FLOAT, list(outdata.shape)) + ], + ) + else: + inputs = [indata] + outdata = np.pad(indata, pad_width=np_pads, mode="constant", constant_values=value) + node = helper.make_node( + "Pad", + inputs=["input", "pads", "constant_value"], + outputs=["output"], + mode="constant", + ) + graph = helper.make_graph( + [node], + "pad_test", + inputs=[ + helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape)), + helper.make_tensor_value_info("pads", TensorProto.INT64, (len(pads),)), + helper.make_tensor_value_info("constant_value", TensorProto.FLOAT, (1,)), + ], + initializer=[ + helper.make_tensor("pads", TensorProto.INT64, (len(pads),), pads), + helper.make_tensor("constant_value", TensorProto.FLOAT, (1,), [value]), + ], + outputs=[ + helper.make_tensor_value_info("output", TensorProto.FLOAT, list(outdata.shape)) + ], + ) + model = helper.make_model(graph, producer_name="pad_test") + verify_with_ort_with_inputs(model, inputs, opset=11, use_vm=True, target=target, dev=dev) -@tvm.testing.uses_gpu -def test_pad(): verify_pad(np.random.randn(2, 2).astype(np.float32), [0, 1, 0, 0], "constant", 0.0) verify_pad(np.random.randn(2, 3).astype(np.float32), [1, 0, 0, 1], "constant", 0.0) verify_pad(np.random.randn(3, 2).astype(np.float32), [0, 0, 1, 0], "constant", 5.0) @@ -1733,31 +1747,30 @@ def test_pad(): ) -def verify_reduce_func(func, data, axis, keepdims): - inshape = data.shape - outshape = np.sum(data, axis=axis, keepdims=keepdims == 1).shape +@tvm.testing.parametrize_targets +def test_all_reduce_funcs(target, dev): + def verify_reduce_func(func, data, axis, keepdims): + inshape = data.shape + outshape = np.sum(data, axis=axis, keepdims=keepdims == 1).shape - if axis: - node = onnx.helper.make_node( - func, inputs=["x"], outputs=["y"], axes=axis, keepdims=keepdims - ) - else: - node = onnx.helper.make_node(func, inputs=["x"], outputs=["y"], keepdims=keepdims) - - graph = helper.make_graph( - [node], - "reduce_test", - inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(inshape))], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(outshape))], - ) + if axis: + node = onnx.helper.make_node( + func, inputs=["x"], outputs=["y"], axes=axis, keepdims=keepdims + ) + else: + node = onnx.helper.make_node(func, inputs=["x"], outputs=["y"], keepdims=keepdims) - model = helper.make_model(graph, producer_name="reduce_test") + graph = helper.make_graph( + [node], + "reduce_test", + inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(inshape))], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(outshape))], + ) - verify_with_ort_with_inputs(model, [data], [outshape], opset=11) + model = helper.make_model(graph, producer_name="reduce_test") + verify_with_ort_with_inputs(model, [data], [outshape], opset=11, target=target, dev=dev) -@tvm.testing.uses_gpu -def test_all_reduce_funcs(): funcs = [ "ReduceMax", "ReduceMean", @@ -1798,58 +1811,64 @@ def test_all_reduce_funcs(): ) -def verify_split(indata, outdatas, split, axis=0, pass_split=True, opset=11): - indata = np.array(indata).astype(np.float32) - outdatas = [np.array(o).astype(np.float32) for o in outdatas] - inputs = [helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape))] - input_names = ["input"] - initializer = [] - - if split: - split_index = range(len(split)) - else: - split_index = range(len(outdatas)) - - if pass_split: - if opset >= 13: - input_names.append("split") - np_split = np.array(split).astype(np.int64) - inputs.append( - helper.make_tensor_value_info("split", TensorProto.INT64, list(np_split.shape)) - ) - indata = [indata, np_split] - initializer.append( - helper.make_tensor("split", TensorProto.INT64, list(np_split.shape), np_split) - ) - node = helper.make_node( - "Split", - inputs=input_names, - outputs=["output_{}".format(i) for i in range(len(split_index))], - axis=axis, - ) +@tvm.testing.parametrize_targets +def test_split(target, dev): + def verify_split(indata, outdatas, split, axis=0, pass_split=True, opset=11): + indata = np.array(indata).astype(np.float32) + outdatas = [np.array(o).astype(np.float32) for o in outdatas] + inputs = [helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape))] + input_names = ["input"] + initializer = [] - if pass_split and opset < 13: - split_attr = helper.make_attribute("split", split) - node.attribute.append(split_attr) + if split: + split_index = range(len(split)) + else: + split_index = range(len(outdatas)) + + if pass_split: + if opset >= 13: + input_names.append("split") + np_split = np.array(split).astype(np.int64) + inputs.append( + helper.make_tensor_value_info("split", TensorProto.INT64, list(np_split.shape)) + ) + indata = [indata, np_split] + initializer.append( + helper.make_tensor("split", TensorProto.INT64, list(np_split.shape), np_split) + ) + node = helper.make_node( + "Split", + inputs=input_names, + outputs=["output_{}".format(i) for i in range(len(split_index))], + axis=axis, + ) - graph = helper.make_graph( - [node], - "split_test", - inputs=inputs, - initializer=initializer, - outputs=[ - helper.make_tensor_value_info( - "output_{}".format(i), TensorProto.FLOAT, list(outdatas[i].shape) - ) - for i in range(len(split_index)) - ], - ) - model = helper.make_model(graph, producer_name="split_test") - verify_with_ort_with_inputs(model, indata, out_shape=list(range(len(split_index))), opset=opset) + if pass_split and opset < 13: + split_attr = helper.make_attribute("split", split) + node.attribute.append(split_attr) + graph = helper.make_graph( + [node], + "split_test", + inputs=inputs, + initializer=initializer, + outputs=[ + helper.make_tensor_value_info( + "output_{}".format(i), TensorProto.FLOAT, list(outdatas[i].shape) + ) + for i in range(len(split_index)) + ], + ) + model = helper.make_model(graph, producer_name="split_test") + verify_with_ort_with_inputs( + model, + indata, + out_shape=list(range(len(split_index))), + opset=opset, + target=target, + dev=dev, + ) -@tvm.testing.uses_gpu -def test_split(): # 1D verify_split([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], [2, 2, 2], 0) verify_split( @@ -1869,8 +1888,8 @@ def test_split(): verify_split([1], [[1]], [1], pass_split=True) -@tvm.testing.uses_gpu -def test_binary_ops(): +@tvm.testing.parametrize_targets +def test_binary_ops(target, dev): in_shape = (1, 2, 3, 3) dtype = "float32" out_shape = in_shape @@ -1891,7 +1910,7 @@ def verify_binary_ops(op, x, y, out_type="float32"): ], ) model = helper.make_model(graph, producer_name="_test") - verify_with_ort_with_inputs(model, [x, y]) + verify_with_ort_with_inputs(model, [x, y], target=target, dev=dev) x = np.random.uniform(size=in_shape).astype(dtype) y = np.random.uniform(size=in_shape).astype(dtype) @@ -1914,8 +1933,8 @@ def verify_binary_ops(op, x, y, out_type="float32"): verify_binary_ops("Equal", x, z, "bool") -@tvm.testing.uses_gpu -def test_unary_ops(): +@tvm.testing.parametrize_targets +def test_unary_ops(target, dev): in_shape = (1, 2, 3, 3) dtype = "float32" out_shape = in_shape @@ -1933,7 +1952,7 @@ def verify_unary_ops(op, x, rtol=1e-5, atol=1e-5, dtype="float32"): outputs=[helper.make_tensor_value_info("out", ONNX_DTYPE, list(out_shape))], ) model = helper.make_model(graph, producer_name="_test") - verify_with_ort_with_inputs(model, [x], rtol=rtol, atol=atol) + verify_with_ort_with_inputs(model, [x], rtol=rtol, atol=atol, target=target, dev=dev) x = np.random.uniform(size=in_shape) verify_unary_ops("Neg", x) @@ -1961,32 +1980,41 @@ def verify_unary_ops(op, x, rtol=1e-5, atol=1e-5, dtype="float32"): verify_unary_ops("Softsign", x) -@tvm.testing.uses_gpu -def test_leaky_relu(): +@tvm.testing.parametrize_targets +def test_leaky_relu(target, dev): def leaky_relu_x(x, alpha): return np.where(x >= 0, x, x * alpha) _test_onnx_op_elementwise( - (2, 4, 5, 6), leaky_relu_x, {"alpha": 0.25}, "float32", "LeakyRelu", {"alpha": 0.25} + target, + dev, + (2, 4, 5, 6), + leaky_relu_x, + {"alpha": 0.25}, + "float32", + "LeakyRelu", + {"alpha": 0.25}, ) -@tvm.testing.uses_gpu -def test_elu(): +@tvm.testing.parametrize_targets +def test_elu(target, dev): def elu_x(x, alpha): return np.where(x > 0, x, alpha * (np.exp(x) - 1.0)) _test_onnx_op_elementwise( - (2, 4, 5, 6), elu_x, {"alpha": 0.25}, "float32", "Elu", {"alpha": 0.25} + target, dev, (2, 4, 5, 6), elu_x, {"alpha": 0.25}, "float32", "Elu", {"alpha": 0.25} ) -@tvm.testing.uses_gpu -def test_selu(): +@tvm.testing.parametrize_targets +def test_selu(target, dev): def selu_x(x, alpha, gamma): return gamma * np.where(x > 0, x, alpha * (np.exp(x) - 1.0)) _test_onnx_op_elementwise( + target, + dev, (2, 4, 5, 6), selu_x, {"alpha": 0.25, "gamma": 0.3}, @@ -1996,8 +2024,8 @@ def selu_x(x, alpha, gamma): ) -@tvm.testing.uses_gpu -def test_prelu(): +@tvm.testing.parametrize_targets +def test_prelu(target, dev): def verify_prelu(x_shape, a_shape): node = helper.make_node("PRelu", inputs=["X", "slope"], outputs=["Y"]) @@ -2019,6 +2047,8 @@ def verify_prelu(x_shape, a_shape): out_shape=[list(x_shape)], use_vm=True, convert_to_static=True, + target=target, + dev=dev, ) verify_prelu([3, 4, 5, 6], [1, 4, 1, 1]) @@ -2028,14 +2058,16 @@ def verify_prelu(x_shape, a_shape): verify_prelu([3, 1], [3, 1]) # Test non NCHW workload. -@tvm.testing.uses_gpu -def test_ThresholdedRelu(): +@tvm.testing.parametrize_targets +def test_ThresholdedRelu(target, dev): def ThresholdedRelu_x(x, alpha): out_np = np.clip(x, alpha, np.inf) out_np[out_np == alpha] = 0 return out_np _test_onnx_op_elementwise( + target, + dev, (2, 4, 5, 6), ThresholdedRelu_x, {"alpha": 0.25}, @@ -2045,26 +2077,35 @@ def ThresholdedRelu_x(x, alpha): ) -@tvm.testing.uses_gpu -def test_LogSoftmax(): +@tvm.testing.parametrize_targets +def test_LogSoftmax(target, dev): _test_onnx_op_elementwise( - (1, 4), tvm.topi.testing.log_softmax_python, {}, "float32", "LogSoftmax", {"axis": 1} + target, + dev, + (1, 4), + tvm.topi.testing.log_softmax_python, + {}, + "float32", + "LogSoftmax", + {"axis": 1}, ) -def check_torch_conversion(model, input_size): +def check_torch_conversion(model, input_size, target, dev): dummy_input = torch.randn(*input_size) file_name = "{}.onnx".format(model.__name__) # Set verbose=True for more output torch.onnx.export(model(), dummy_input, file_name, export_params=True, verbose=False) onnx_model = onnx.load(file_name) input_data = np.random.uniform(size=input_size).astype("float32") - verify_with_ort_with_inputs(onnx_model, [input_data], apply_softmax=True) + verify_with_ort_with_inputs( + onnx_model, [input_data], apply_softmax=True, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_resnet(): - check_torch_conversion(torchvision.models.resnet18, (1, 3, 224, 224)) +@tvm.testing.parametrize_targets +def test_resnet(target, dev): + check_torch_conversion(torchvision.models.resnet18, (1, 3, 224, 224), target, dev) # check_torch_conversion(torchvision.models.resnet101, (1,3,224,224)) @@ -2082,14 +2123,14 @@ def test_resnet(): # check_torch_conversion(torchvision.models.squeezenet1_0, (1,3,224,224)) -@tvm.testing.uses_gpu -def test_densenet(): - check_torch_conversion(torchvision.models.densenet161, (1, 3, 224, 224)) +@tvm.testing.parametrize_targets +def test_densenet(target, dev): + check_torch_conversion(torchvision.models.densenet161, (1, 3, 224, 224), target, dev) -@tvm.testing.uses_gpu -def test_inception(): - check_torch_conversion(torchvision.models.inception_v3, (1, 3, 224, 224)) +@tvm.testing.parametrize_targets +def test_inception(target, dev): + check_torch_conversion(torchvision.models.inception_v3, (1, 3, 224, 224), target, dev) # TODO(@jroesch): Update Torch + ONNX to support this import. @@ -2101,36 +2142,35 @@ def test_inception(): # check_torch_conversion(torchvision.models.shufflenetv2, (1,3,224,224)) -@tvm.testing.uses_gpu -def test_sign(): +@tvm.testing.parametrize_targets +def test_sign(target, dev): def Sign_x(x): return np.sign(x) - _test_onnx_op_elementwise((3, 4, 5, 6), Sign_x, {}, "float32", "Sign", {}) + _test_onnx_op_elementwise(target, dev, (3, 4, 5, 6), Sign_x, {}, "float32", "Sign", {}) -def verify_not(indata, dtype): - x = indata.astype(dtype) +@tvm.testing.parametrize_targets +def test_not(target, dev): + def verify_not(indata, dtype): + x = indata.astype(dtype) - node = helper.make_node( - "Not", - inputs=["in"], - outputs=["out"], - ) - - graph = helper.make_graph( - [node], - "not_test", - inputs=[helper.make_tensor_value_info("in", TensorProto.BOOL, list(x.shape))], - outputs=[helper.make_tensor_value_info("out", TensorProto.BOOL, list(x.shape))], - ) + node = helper.make_node( + "Not", + inputs=["in"], + outputs=["out"], + ) - model = helper.make_model(graph, producer_name="not_test") - verify_with_ort_with_inputs(model, [x]) + graph = helper.make_graph( + [node], + "not_test", + inputs=[helper.make_tensor_value_info("in", TensorProto.BOOL, list(x.shape))], + outputs=[helper.make_tensor_value_info("out", TensorProto.BOOL, list(x.shape))], + ) + model = helper.make_model(graph, producer_name="not_test") + verify_with_ort_with_inputs(model, [x], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_not(): # 2d verify_not(indata=(np.random.randn(3, 4) > 0), dtype=bool) # 3d @@ -2139,33 +2179,32 @@ def test_not(): verify_not(indata=(np.random.randn(3, 4, 5, 6) > 0), dtype=bool) -def verify_and(indata, dtype): - x = indata[0].astype(dtype) - y = indata[1].astype(dtype) - outdata = np.logical_and(x, y) - - node = helper.make_node( - "And", - inputs=["in1", "in2"], - outputs=["out"], - ) +@tvm.testing.parametrize_targets +def test_and(target, dev): + def verify_and(indata, dtype): + x = indata[0].astype(dtype) + y = indata[1].astype(dtype) + outdata = np.logical_and(x, y) - graph = helper.make_graph( - [node], - "and_test", - inputs=[ - helper.make_tensor_value_info("in1", TensorProto.BOOL, list(x.shape)), - helper.make_tensor_value_info("in2", TensorProto.BOOL, list(y.shape)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.BOOL, list(outdata.shape))], - ) + node = helper.make_node( + "And", + inputs=["in1", "in2"], + outputs=["out"], + ) - model = helper.make_model(graph, producer_name="and_test") - verify_with_ort_with_inputs(model, [x, y], [outdata.shape]) + graph = helper.make_graph( + [node], + "and_test", + inputs=[ + helper.make_tensor_value_info("in1", TensorProto.BOOL, list(x.shape)), + helper.make_tensor_value_info("in2", TensorProto.BOOL, list(y.shape)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.BOOL, list(outdata.shape))], + ) + model = helper.make_model(graph, producer_name="and_test") + verify_with_ort_with_inputs(model, [x, y], [outdata.shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_and(): # 2d x = np.random.randn(3, 4) > 0 y = np.random.randn(3, 4) > 0 @@ -2192,75 +2231,76 @@ def test_and(): verify_and(indata=[x, y], dtype=bool) -def verify_tile_v6(indata, repeats, outdata): - node = helper.make_node("Tile", inputs=["input", "repeats"], outputs=["out"]) - graph = helper.make_graph( - [node], - "tile_test", - inputs=[ - helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape)), - helper.make_tensor_value_info("repeats", TensorProto.INT64, list(repeats.shape)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], - ) - - model = helper.make_model(graph, producer_name="tile_test") - verify_with_ort_with_inputs(model, [indata, repeats], use_vm=True, opset=6) +@tvm.testing.parametrize_targets +def test_tile(target, dev): + def verify_tile_v6(indata, repeats, outdata): + node = helper.make_node("Tile", inputs=["input", "repeats"], outputs=["out"]) + graph = helper.make_graph( + [node], + "tile_test", + inputs=[ + helper.make_tensor_value_info("input", TensorProto.FLOAT, list(indata.shape)), + helper.make_tensor_value_info("repeats", TensorProto.INT64, list(repeats.shape)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], + ) + model = helper.make_model(graph, producer_name="tile_test") + verify_with_ort_with_inputs( + model, [indata, repeats], use_vm=True, opset=6, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_tile(): x = np.random.rand(2, 3, 4, 5).astype(np.float32) repeats = np.random.randint(low=1, high=10, size=(np.ndim(x),)).astype(np.int64) z = np.tile(x, repeats) verify_tile_v6(x, repeats, z) -def verify_erf(indata, outdata): - node = helper.make_node("Erf", inputs=["in"], outputs=["out"]) - graph = helper.make_graph( - [node], - "erf_test", - inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(indata.shape))], - outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], - ) - model = helper.make_model(graph, producer_name="erf_test") - verify_with_ort_with_inputs(model, [indata], [outdata.shape]) - +@tvm.testing.parametrize_targets +def test_erf(target, dev): + def verify_erf(indata, outdata): + node = helper.make_node("Erf", inputs=["in"], outputs=["out"]) + graph = helper.make_graph( + [node], + "erf_test", + inputs=[helper.make_tensor_value_info("in", TensorProto.FLOAT, list(indata.shape))], + outputs=[helper.make_tensor_value_info("out", TensorProto.FLOAT, list(outdata.shape))], + ) + model = helper.make_model(graph, producer_name="erf_test") + verify_with_ort_with_inputs(model, [indata], [outdata.shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_erf(): x = np.random.rand(2, 3, 4, 6).astype(np.float32) z = scipy.special.erf(x) verify_erf(x, z) -def verify_where(condition, x, y, dtype, outdata, dynamic=False): - node_list = [] - where_inputs = ["condition", "x", "y"] - if dynamic: - shape_node = helper.make_node("Shape", ["x"], ["shape"]) - reshape_node = helper.make_node("Reshape", ["x", "shape"], ["X"]) - where_inputs[1] = "X" - node_list += [shape_node, reshape_node] - node = helper.make_node("Where", inputs=where_inputs, outputs=["out"]) - node_list.append(node) - graph = helper.make_graph( - node_list, - "where_test", - inputs=[ - helper.make_tensor_value_info("condition", TensorProto.BOOL, list(condition.shape)), - helper.make_tensor_value_info("x", dtype, list(x.shape)), - helper.make_tensor_value_info("y", dtype, list(y.shape)), - ], - outputs=[helper.make_tensor_value_info("out", dtype, list(outdata.shape))], - ) - model = helper.make_model(graph, producer_name="where_test") - verify_with_ort_with_inputs(model, [condition, x, y], [outdata.shape], use_vm=True) - +@tvm.testing.parametrize_targets +def test_where(target, dev): + def verify_where(condition, x, y, dtype, outdata, dynamic=False): + node_list = [] + where_inputs = ["condition", "x", "y"] + if dynamic: + shape_node = helper.make_node("Shape", ["x"], ["shape"]) + reshape_node = helper.make_node("Reshape", ["x", "shape"], ["X"]) + where_inputs[1] = "X" + node_list += [shape_node, reshape_node] + node = helper.make_node("Where", inputs=where_inputs, outputs=["out"]) + node_list.append(node) + graph = helper.make_graph( + node_list, + "where_test", + inputs=[ + helper.make_tensor_value_info("condition", TensorProto.BOOL, list(condition.shape)), + helper.make_tensor_value_info("x", dtype, list(x.shape)), + helper.make_tensor_value_info("y", dtype, list(y.shape)), + ], + outputs=[helper.make_tensor_value_info("out", dtype, list(outdata.shape))], + ) + model = helper.make_model(graph, producer_name="where_test") + verify_with_ort_with_inputs( + model, [condition, x, y], [outdata.shape], use_vm=True, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_where(): condition = np.array([[1, 0], [1, 1]], dtype=bool) x = np.array([[1, 2], [3, 4]], dtype=np.int64) y = np.array([[9, 8], [7, 6]], dtype=np.int64) @@ -2295,33 +2335,32 @@ def test_where(): verify_where(condition, x, y, TensorProto.FLOAT, outdata, dynamic=True) -def verify_or(indata, dtype): - x = indata[0].astype(dtype) - y = indata[1].astype(dtype) - outdata = np.logical_or(x, y) - - node = helper.make_node( - "Or", - inputs=["in1", "in2"], - outputs=["out"], - ) +@tvm.testing.parametrize_targets +def test_or(target, dev): + def verify_or(indata, dtype): + x = indata[0].astype(dtype) + y = indata[1].astype(dtype) + outdata = np.logical_or(x, y) - graph = helper.make_graph( - [node], - "or_test", - inputs=[ - helper.make_tensor_value_info("in1", TensorProto.BOOL, list(x.shape)), - helper.make_tensor_value_info("in2", TensorProto.BOOL, list(y.shape)), - ], - outputs=[helper.make_tensor_value_info("out", TensorProto.BOOL, list(outdata.shape))], - ) + node = helper.make_node( + "Or", + inputs=["in1", "in2"], + outputs=["out"], + ) - model = helper.make_model(graph, producer_name="or_test") - verify_with_ort_with_inputs(model, [x, y], [outdata.shape]) + graph = helper.make_graph( + [node], + "or_test", + inputs=[ + helper.make_tensor_value_info("in1", TensorProto.BOOL, list(x.shape)), + helper.make_tensor_value_info("in2", TensorProto.BOOL, list(y.shape)), + ], + outputs=[helper.make_tensor_value_info("out", TensorProto.BOOL, list(outdata.shape))], + ) + model = helper.make_model(graph, producer_name="or_test") + verify_with_ort_with_inputs(model, [x, y], [outdata.shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_or(): # 2d x = np.random.randn(3, 4) > 0 y = np.random.randn(3, 4) > 0 @@ -2348,8 +2387,8 @@ def test_or(): verify_or(indata=[x, y], dtype=bool) -@tvm.testing.uses_gpu -def test_batch_norm(): +@tvm.testing.parametrize_targets +def test_batch_norm(target, dev): def verify_batch_norm(in_shape): batchnorm = onnx.helper.make_node( "BatchNormalization", inputs=["x", "scale", "B", "mean", "var"], outputs=["Y"] @@ -2371,7 +2410,7 @@ def verify_batch_norm(in_shape): model = helper.make_model(graph, producer_name="batchnorm_test") # X, scale, b, mean, var inshapes = [in_shape, in_shape[1], in_shape[1], in_shape[1], in_shape[1]] - verify_with_ort(model, inshapes, out_shape=[in_shape]) + verify_with_ort(model, inshapes, out_shape=[in_shape], target=target, dev=dev) verify_batch_norm([1, 3, 224, 224]) verify_batch_norm([1, 3, 24, 24]) @@ -2380,8 +2419,8 @@ def verify_batch_norm(in_shape): verify_batch_norm([16, 16, 10, 10]) -@tvm.testing.uses_gpu -def test_batch_norm_dynamic_subgraph(): +@tvm.testing.parametrize_targets +def test_batch_norm_dynamic_subgraph(target, dev): def verify_batch_norm_dynamic_subgraph(in_shape, o_shape): batchnorm = onnx.helper.make_node( @@ -2408,81 +2447,88 @@ def verify_batch_norm_dynamic_subgraph(in_shape, o_shape): # X, inp, scale, b, mean, var inshapes = [in_shape, o_shape, in_shape[1], in_shape[1], in_shape[1], in_shape[1]] - verify_with_ort(model, inshapes, out_shape=[in_shape], use_vm=True) + verify_with_ort(model, inshapes, out_shape=[in_shape], use_vm=True, target=target, dev=dev) verify_batch_norm_dynamic_subgraph([16, 16, 10, 10], [160, 160]) -def verify_conv( - x_shape, - w_shape, - y_shape, - padding, - kernel_shape, - strides, - dilations, - group=1, - auto_pad="NOTSET", - unset_pad=False, -): - if unset_pad: - node = helper.make_node( - "Conv", - inputs=["x", "W"], - outputs=["y"], - kernel_shape=kernel_shape, - # Default values for other attributes: - strides=strides, - dilations=dilations, - group=group, - ) - elif padding is None: - ## autopadding with unset default attributes - kwargs = {} - if not all([s == 1 for s in strides]): - kwargs["strides"] = strides - if not all([d == 1 for d in dilations]): - kwargs["dilations"] = dilations +@tvm.testing.parametrize_targets +def test_conv(target, dev): + def verify_conv( + x_shape, + w_shape, + y_shape, + padding, + kernel_shape, + strides, + dilations, + group=1, + auto_pad="NOTSET", + unset_pad=False, + ): + if unset_pad: + node = helper.make_node( + "Conv", + inputs=["x", "W"], + outputs=["y"], + kernel_shape=kernel_shape, + # Default values for other attributes: + strides=strides, + dilations=dilations, + group=group, + ) + elif padding is None: + ## autopadding with unset default attributes + kwargs = {} + if not all([s == 1 for s in strides]): + kwargs["strides"] = strides + if not all([d == 1 for d in dilations]): + kwargs["dilations"] = dilations + + node = helper.make_node( + "Conv", + inputs=["x", "W"], + outputs=["y"], + # Default values for other attributes: + auto_pad=auto_pad, + group=group, + **kwargs, + ) + else: + node = helper.make_node( + "Conv", + inputs=["x", "W"], + outputs=["y"], + kernel_shape=kernel_shape, + # Default values for other attributes: + strides=strides, + dilations=dilations, + group=group, + pads=padding, + ) - node = helper.make_node( - "Conv", - inputs=["x", "W"], - outputs=["y"], - # Default values for other attributes: - auto_pad=auto_pad, - group=group, - **kwargs, - ) - else: - node = helper.make_node( - "Conv", - inputs=["x", "W"], - outputs=["y"], - kernel_shape=kernel_shape, - # Default values for other attributes: - strides=strides, - dilations=dilations, - group=group, - pads=padding, + graph = helper.make_graph( + [node], + "conv_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), + helper.make_tensor_value_info("W", TensorProto.FLOAT, list(w_shape)), + ], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(y_shape))], ) - graph = helper.make_graph( - [node], - "conv_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), - helper.make_tensor_value_info("W", TensorProto.FLOAT, list(w_shape)), - ], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(y_shape))], - ) - - model = helper.make_model(graph, producer_name="conv_test") - - verify_with_ort(model, [x_shape, w_shape], [y_shape], use_vm=True, convert_to_static=True) + model = helper.make_model(graph, producer_name="conv_test") + verify_with_ort( + model, + [x_shape, w_shape], + [y_shape], + use_vm=True, + convert_to_static=True, + target=target, + dev=dev, + ) -@tvm.testing.uses_gpu -def test_conv(): def repeat(N, D): return tuple([N for _ in range(D)]) @@ -2587,82 +2633,82 @@ def repeat(N, D): ) -def verify_convtranspose_with_padding( - x_shape, - w_shape, - padding, - kernel_shape, - strides, - dilations, - auto_pad="NOTSET", - unset_pad=False, - group=1, -): - node = helper.make_node( - "ConvTranspose", - inputs=["x", "W"], - outputs=["y"], - kernel_shape=kernel_shape, - # Default values for other attributes: - strides=strides, - dilations=dilations, - ) - if not unset_pad: - if padding is None: - pad_attr = helper.make_attribute("auto_pad", auto_pad) - else: - pad_attr = helper.make_attribute("pads", padding) - node.attribute.append(pad_attr) - - if group is not None: - group_attr = helper.make_attribute("group", group) - node.attribute.append(group_attr) - - graph = helper.make_graph( - [node], - "convtranspose_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), - helper.make_tensor_value_info("W", TensorProto.FLOAT, list(w_shape)), - ], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, ["?"] * len(x_shape))], - ) +@tvm.testing.parametrize_targets +def test_convtranspose(target, dev): + def verify_convtranspose_with_padding( + x_shape, + w_shape, + padding, + kernel_shape, + strides, + dilations, + auto_pad="NOTSET", + unset_pad=False, + group=1, + ): + node = helper.make_node( + "ConvTranspose", + inputs=["x", "W"], + outputs=["y"], + kernel_shape=kernel_shape, + # Default values for other attributes: + strides=strides, + dilations=dilations, + ) + if not unset_pad: + if padding is None: + pad_attr = helper.make_attribute("auto_pad", auto_pad) + else: + pad_attr = helper.make_attribute("pads", padding) + node.attribute.append(pad_attr) - model = helper.make_model(graph, producer_name="convtranspose_pad_test") + if group is not None: + group_attr = helper.make_attribute("group", group) + node.attribute.append(group_attr) - verify_with_ort(model, [x_shape, w_shape], use_vm=True, convert_to_static=True) + graph = helper.make_graph( + [node], + "convtranspose_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), + helper.make_tensor_value_info("W", TensorProto.FLOAT, list(w_shape)), + ], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, ["?"] * len(x_shape))], + ) + model = helper.make_model(graph, producer_name="convtranspose_pad_test") -def verify_convtranspose(x_shape, w_shape, y_shape, p, group=1): - node = onnx.helper.make_node( - "ConvTranspose", - inputs=["x", "W"], - outputs=["y"], - strides=[3, 2], - kernel_shape=[3, 3], - pads=p, - ) + verify_with_ort( + model, [x_shape, w_shape], use_vm=True, convert_to_static=True, target=target, dev=dev + ) - if group is not None: - group_attr = helper.make_attribute("group", group) - node.attribute.append(group_attr) + def verify_convtranspose(x_shape, w_shape, y_shape, p, group=1): + node = onnx.helper.make_node( + "ConvTranspose", + inputs=["x", "W"], + outputs=["y"], + strides=[3, 2], + kernel_shape=[3, 3], + pads=p, + ) - graph = helper.make_graph( - [node], - "verify_convtranspose_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), - helper.make_tensor_value_info("W", TensorProto.FLOAT, list(w_shape)), - ], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(y_shape))], - ) + if group is not None: + group_attr = helper.make_attribute("group", group) + node.attribute.append(group_attr) - model = helper.make_model(graph, producer_name="convtranspose_test") - verify_with_ort(model, [x_shape, w_shape], y_shape, opset=11) + graph = helper.make_graph( + [node], + "verify_convtranspose_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), + helper.make_tensor_value_info("W", TensorProto.FLOAT, list(w_shape)), + ], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(y_shape))], + ) + model = helper.make_model(graph, producer_name="convtranspose_test") + verify_with_ort(model, [x_shape, w_shape], y_shape, opset=11, target=target, dev=dev) -@tvm.testing.uses_gpu -def test_convtranspose(): # Convolution Transpose with padding # (1, 1, 3, 3) input tensor # (1, 2, 3, 3) tensor for convolution weights @@ -2747,8 +2793,8 @@ def repeat(N, D): # ) -@tvm.testing.uses_gpu -def test_unsqueeze_constant(): +@tvm.testing.parametrize_targets +def test_unsqueeze_constant(target, dev): from torch.nn import Linear, Module, Sequential class Flatten(Module): @@ -2768,43 +2814,50 @@ def forward(self, input): relay.frontend.from_onnx(onnx_model, {"0": input_size}) -def verify_pooling(x_shape, kernel_shape, strides, pads, out_shape, mode, auto_pad="NOTSET"): - x_np = np.random.uniform(size=x_shape).astype("float32") +@tvm.testing.parametrize_targets +def test_pooling(target, dev): + def verify_pooling(x_shape, kernel_shape, strides, pads, out_shape, mode, auto_pad="NOTSET"): + x_np = np.random.uniform(size=x_shape).astype("float32") - if mode == "max": - node_type = "MaxPool" - elif mode == "average": - node_type = "AveragePool" - else: - raise ValueError("Pool method {} is not supported.".format(mode)) - - pool_node = helper.make_node( - node_type, inputs=["x"], outputs=["y"], kernel_shape=kernel_shape, strides=strides - ) + if mode == "max": + node_type = "MaxPool" + elif mode == "average": + node_type = "AveragePool" + else: + raise ValueError("Pool method {} is not supported.".format(mode)) - if pads is None: - pad_attr = helper.make_attribute("auto_pad", auto_pad) - else: - pad_attr = helper.make_attribute("pads", pads) - pool_node.attribute.append(pad_attr) + pool_node = helper.make_node( + node_type, inputs=["x"], outputs=["y"], kernel_shape=kernel_shape, strides=strides + ) - if mode == "max": - storage_attr = helper.make_attribute("storage_order", 0) - pool_node.attribute.append(storage_attr) + if pads is None: + pad_attr = helper.make_attribute("auto_pad", auto_pad) + else: + pad_attr = helper.make_attribute("pads", pads) + pool_node.attribute.append(pad_attr) - graph = helper.make_graph( - [pool_node], - "pooling_test", - inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape))], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], - ) + if mode == "max": + storage_attr = helper.make_attribute("storage_order", 0) + pool_node.attribute.append(storage_attr) - model = helper.make_model(graph, producer_name="pooling_test") - verify_with_ort(model, [x_shape], [out_shape], use_vm=False, convert_to_static=True) + graph = helper.make_graph( + [pool_node], + "pooling_test", + inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape))], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="pooling_test") + verify_with_ort( + model, + [x_shape], + [out_shape], + use_vm=False, + convert_to_static=True, + target=target, + dev=dev, + ) -@tvm.testing.uses_gpu -def test_pooling(): for mode in ["max", "average"]: # Pool1D verify_pooling( @@ -2887,31 +2940,38 @@ def test_pooling(): ) -def verify_global_pooling(x_shape, mode): - out_shape = x_shape[:2] + [1] * (len(x_shape) - 2) - - if mode == "max": - node_type = "GlobalMaxPool" - elif mode == "average": - node_type = "GlobalAveragePool" - else: - raise ValueError("Pool method {} is not supported.".format(mode)) +@tvm.testing.parametrize_targets +def test_global_pooling(target, dev): + def verify_global_pooling(x_shape, mode): + out_shape = x_shape[:2] + [1] * (len(x_shape) - 2) - pool_node = helper.make_node(node_type, inputs=["x"], outputs=["y"]) + if mode == "max": + node_type = "GlobalMaxPool" + elif mode == "average": + node_type = "GlobalAveragePool" + else: + raise ValueError("Pool method {} is not supported.".format(mode)) - graph = helper.make_graph( - [pool_node], - "global_pooling_test", - inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape))], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], - ) + pool_node = helper.make_node(node_type, inputs=["x"], outputs=["y"]) - model = helper.make_model(graph, producer_name="global_pooling_test") - verify_with_ort(model, [x_shape], [out_shape], use_vm=False, convert_to_static=True) + graph = helper.make_graph( + [pool_node], + "global_pooling_test", + inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape))], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="global_pooling_test") + verify_with_ort( + model, + [x_shape], + [out_shape], + use_vm=False, + convert_to_static=True, + target=target, + dev=dev, + ) -@tvm.testing.uses_gpu -def test_global_pooling(): # Test each pooling mode across all N-D inputs. for mode in ["average", "max"]: # 1D Pooling (NCW) @@ -2925,29 +2985,28 @@ def test_global_pooling(): verify_global_pooling([4, 1, 2, 6, 4], mode) -def verify_mod(x_shape, y_shape, fmod, out_shape, dtype="float32"): - x_np = np.random.uniform(-100.0, 100.0, x_shape).astype(dtype) - y_np = np.random.uniform(-100.0, 100.0, y_shape).astype(dtype) - y_np = np.where(y_np == 0, 1, y_np) # remove 0's to avoid division by zero error +@tvm.testing.parametrize_targets +def test_mod(target, dev): + def verify_mod(x_shape, y_shape, fmod, out_shape, dtype="float32"): + x_np = np.random.uniform(-100.0, 100.0, x_shape).astype(dtype) + y_np = np.random.uniform(-100.0, 100.0, y_shape).astype(dtype) + y_np = np.where(y_np == 0, 1, y_np) # remove 0's to avoid division by zero error - mod_node = helper.make_node("Mod", inputs=["x", "y"], outputs=["z"], fmod=fmod) - - onnx_dtype = TensorProto.FLOAT if dtype == "float32" else TensorProto.INT32 - graph = helper.make_graph( - [mod_node], - "mod_test", - inputs=[ - helper.make_tensor_value_info("x", onnx_dtype, list(x_shape)), - helper.make_tensor_value_info("y", onnx_dtype, list(y_shape)), - ], - outputs=[helper.make_tensor_value_info("z", onnx_dtype, list(out_shape))], - ) - model = helper.make_model(graph, producer_name="mod_test") - verify_with_ort_with_inputs(model, [x_np, y_np], [out_shape]) + mod_node = helper.make_node("Mod", inputs=["x", "y"], outputs=["z"], fmod=fmod) + onnx_dtype = TensorProto.FLOAT if dtype == "float32" else TensorProto.INT32 + graph = helper.make_graph( + [mod_node], + "mod_test", + inputs=[ + helper.make_tensor_value_info("x", onnx_dtype, list(x_shape)), + helper.make_tensor_value_info("y", onnx_dtype, list(y_shape)), + ], + outputs=[helper.make_tensor_value_info("z", onnx_dtype, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="mod_test") + verify_with_ort_with_inputs(model, [x_np, y_np], [out_shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_mod(): # Mod verify_mod( x_shape=[1, 32, 32], y_shape=[1, 1, 32], fmod=0, out_shape=(1, 32, 32), dtype="int32" @@ -2976,31 +3035,30 @@ def test_mod(): verify_mod(x_shape=[1, 32, 32, 32], y_shape=[1, 32, 32, 32], fmod=1, out_shape=(1, 32, 32, 32)) -def verify_xor(x_shape, y_shape): - x_np = np.random.choice(a=[False, True], size=x_shape).astype("bool") - y_np = np.random.choice(a=[False, True], size=y_shape).astype("bool") - - np_out = np.logical_xor(x_np, y_np) - out_shape = np_out.shape +@tvm.testing.parametrize_targets +def test_xor(target, dev): + def verify_xor(x_shape, y_shape): + x_np = np.random.choice(a=[False, True], size=x_shape).astype("bool") + y_np = np.random.choice(a=[False, True], size=y_shape).astype("bool") - xor_node = helper.make_node("Xor", inputs=["x", "y"], outputs=["z"]) + np_out = np.logical_xor(x_np, y_np) + out_shape = np_out.shape - onnx_dtype = TensorProto.BOOL - graph = helper.make_graph( - [xor_node], - "xor_test", - inputs=[ - helper.make_tensor_value_info("x", onnx_dtype, list(x_shape)), - helper.make_tensor_value_info("y", onnx_dtype, list(y_shape)), - ], - outputs=[helper.make_tensor_value_info("z", onnx_dtype, list(out_shape))], - ) - model = helper.make_model(graph, producer_name="xor_test") - verify_with_ort_with_inputs(model, [x_np, y_np], [out_shape]) + xor_node = helper.make_node("Xor", inputs=["x", "y"], outputs=["z"]) + onnx_dtype = TensorProto.BOOL + graph = helper.make_graph( + [xor_node], + "xor_test", + inputs=[ + helper.make_tensor_value_info("x", onnx_dtype, list(x_shape)), + helper.make_tensor_value_info("y", onnx_dtype, list(y_shape)), + ], + outputs=[helper.make_tensor_value_info("z", onnx_dtype, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="xor_test") + verify_with_ort_with_inputs(model, [x_np, y_np], [out_shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_xor(): # XOR verify_xor(x_shape=[1, 32, 32], y_shape=[1, 32, 32]) @@ -3008,36 +3066,35 @@ def test_xor(): verify_xor(x_shape=[1, 32, 32], y_shape=[1, 1, 32]) -def verify_max_roi_pool(x_shape, rois_shape, pooled_shape, spatial_scale, out_shape): - if spatial_scale is None: - pool_node = helper.make_node( - "MaxRoiPool", inputs=["x", "rois"], outputs=["y"], pooled_shape=pooled_shape - ) - else: - pool_node = helper.make_node( - "MaxRoiPool", - inputs=["x", "rois"], - outputs=["y"], - pooled_shape=pooled_shape, - spatial_scale=spatial_scale, - ) - - graph = helper.make_graph( - [pool_node], - "pool_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), - helper.make_tensor_value_info("rois", TensorProto.FLOAT, list(rois_shape)), - ], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], - ) +@tvm.testing.parametrize_targets +def test_max_roi_pool(target, dev): + def verify_max_roi_pool(x_shape, rois_shape, pooled_shape, spatial_scale, out_shape): + if spatial_scale is None: + pool_node = helper.make_node( + "MaxRoiPool", inputs=["x", "rois"], outputs=["y"], pooled_shape=pooled_shape + ) + else: + pool_node = helper.make_node( + "MaxRoiPool", + inputs=["x", "rois"], + outputs=["y"], + pooled_shape=pooled_shape, + spatial_scale=spatial_scale, + ) - model = helper.make_model(graph, producer_name="pool_test") - verify_with_ort(model, [x_shape, rois_shape], [out_shape]) + graph = helper.make_graph( + [pool_node], + "pool_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape)), + helper.make_tensor_value_info("rois", TensorProto.FLOAT, list(rois_shape)), + ], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="pool_test") + verify_with_ort(model, [x_shape, rois_shape], [out_shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_max_roi_pool(): verify_max_roi_pool( x_shape=[1, 3, 6, 6], rois_shape=[3, 5], @@ -3055,41 +3112,48 @@ def test_max_roi_pool(): ) -def verify_lppool(x_shape, kernel_shape, p, strides, pads, out_shape, auto_pad="NOTSET"): - if pads is None: - pool_node = helper.make_node( - "LpPool", - inputs=["x"], - outputs=["y"], - kernel_shape=kernel_shape, - p=p, - auto_pad=auto_pad, - strides=strides, - ) - else: - pool_node = helper.make_node( - "LpPool", - inputs=["x"], - outputs=["y"], - kernel_shape=kernel_shape, - p=p, - pads=pads, - strides=strides, - ) - - graph = helper.make_graph( - [pool_node], - "lppool_test", - inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape))], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], - ) +@tvm.testing.parametrize_targets +def test_lppool(target, dev): + def verify_lppool(x_shape, kernel_shape, p, strides, pads, out_shape, auto_pad="NOTSET"): + if pads is None: + pool_node = helper.make_node( + "LpPool", + inputs=["x"], + outputs=["y"], + kernel_shape=kernel_shape, + p=p, + auto_pad=auto_pad, + strides=strides, + ) + else: + pool_node = helper.make_node( + "LpPool", + inputs=["x"], + outputs=["y"], + kernel_shape=kernel_shape, + p=p, + pads=pads, + strides=strides, + ) - model = helper.make_model(graph, producer_name="lppool_test") - verify_with_ort(model, [x_shape], [out_shape], use_vm=True, convert_to_static=True) + graph = helper.make_graph( + [pool_node], + "lppool_test", + inputs=[helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x_shape))], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(out_shape))], + ) + model = helper.make_model(graph, producer_name="lppool_test") + verify_with_ort( + model, + [x_shape], + [out_shape], + use_vm=True, + convert_to_static=True, + target=target, + dev=dev, + ) -@tvm.testing.uses_gpu -def test_lppool(): # Pool1D verify_lppool( x_shape=[1, 1, 32], kernel_shape=[3], p=2, strides=[1], pads=[1, 1], out_shape=[1, 1, 32] @@ -3178,6 +3242,8 @@ def verify_rnn( use_peep=False, linear_before_reset=False, directions=1, + target=None, + dev=None, ): if rnn_type == "LSTM": multiplier = 4 @@ -3297,11 +3363,13 @@ def register(name, shape, proto_type): model = helper.make_model(graph, producer_name="rnn_test") - verify_with_ort_with_inputs(model, input_values, output_shapes, atol=1e-2, rtol=1e-2) + verify_with_ort_with_inputs( + model, input_values, output_shapes, atol=1e-2, rtol=1e-2, target=target, dev=dev + ) -@tvm.testing.uses_gpu -def test_lstm(): +@tvm.testing.parametrize_targets +def test_lstm(target, dev): for directions in [1, 2]: # No bias. verify_rnn( @@ -3312,6 +3380,8 @@ def test_lstm(): use_bias=False, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # large batch. verify_rnn( @@ -3322,6 +3392,8 @@ def test_lstm(): use_bias=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # Non power of two. verify_rnn( @@ -3332,6 +3404,8 @@ def test_lstm(): use_bias=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # Long sequence. verify_rnn( @@ -3342,6 +3416,8 @@ def test_lstm(): use_bias=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # Large hidden. verify_rnn( @@ -3352,6 +3428,8 @@ def test_lstm(): use_bias=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # Large input. verify_rnn( @@ -3362,6 +3440,8 @@ def test_lstm(): use_bias=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # Different activation testing. @@ -3375,8 +3455,10 @@ def test_lstm(): activations=["HardSigmoid", "Tanh", "Tanh"] * directions, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) - # Multiple parameterized activations. + # Multiple parametrized activations. verify_rnn( seq_length=2, batch_size=1, @@ -3388,8 +3470,10 @@ def test_lstm(): betas=[0.3, 0.0, 0.0] * directions, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) - # All parameterized with new Affine activation. + # All parametrized with new Affine activation. verify_rnn( seq_length=2, batch_size=1, @@ -3401,6 +3485,8 @@ def test_lstm(): betas=[0.3, 0.1, 0.0] * directions, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) # Testing with initial state and peepholes @@ -3413,6 +3499,8 @@ def test_lstm(): use_initial_state=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) verify_rnn( @@ -3425,11 +3513,13 @@ def test_lstm(): use_peep=True, rnn_type="LSTM", directions=directions, + target=target, + dev=dev, ) -@tvm.testing.uses_gpu -def test_gru(): +@tvm.testing.parametrize_targets +def test_gru(target, dev): for directions in [1, 2]: # No bias. verify_rnn( @@ -3440,6 +3530,8 @@ def test_gru(): use_bias=False, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) # large batch. verify_rnn( @@ -3451,6 +3543,8 @@ def test_gru(): rnn_type="GRU", linear_before_reset=True, directions=directions, + target=target, + dev=dev, ) # Non power of two. verify_rnn( @@ -3461,6 +3555,8 @@ def test_gru(): use_bias=True, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) # Long sequence. verify_rnn( @@ -3471,6 +3567,8 @@ def test_gru(): use_bias=True, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) # Large hidden. verify_rnn( @@ -3481,6 +3579,8 @@ def test_gru(): use_bias=True, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) # Large input. verify_rnn( @@ -3491,6 +3591,8 @@ def test_gru(): use_bias=True, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) # Different activation testing. @@ -3504,8 +3606,10 @@ def test_gru(): activations=["HardSigmoid", "Softsign"] * directions, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) - # Multiple parameterized activations. + # Multiple parametrized activations. verify_rnn( seq_length=2, batch_size=1, @@ -3517,8 +3621,10 @@ def test_gru(): betas=[0.3, 0.0] * directions, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) - # All parameterized with new Affine activation. + # All parametrized with new Affine activation. verify_rnn( seq_length=2, batch_size=1, @@ -3530,6 +3636,8 @@ def test_gru(): betas=[0.3, 0.1] * directions, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) # Testing with initial state @@ -3542,11 +3650,13 @@ def test_gru(): use_initial_state=True, rnn_type="GRU", directions=directions, + target=target, + dev=dev, ) -@tvm.testing.uses_gpu -def test_resize(): +@tvm.testing.parametrize_targets +def test_resize(target, dev): def verify(ishape, oshape, scales, mode, coord_trans="asymmetric", alpha=0.5, exclude=False): nodes = [ make_constant_node("roi", onnx.TensorProto.FLOAT, (0,), []), @@ -3581,7 +3691,16 @@ def verify(ishape, oshape, scales, mode, coord_trans="asymmetric", alpha=0.5, ex model = helper.make_model(graph, producer_name="resize_test") - verify_with_ort(model, [ishape], [oshape], use_vm=True, opset=11, freeze_params=True) + verify_with_ort( + model, + [ishape], + [oshape], + use_vm=True, + opset=11, + freeze_params=True, + target=target, + dev=dev, + ) for ndim in [1, 2, 3]: method = "nearest" @@ -3667,14 +3786,23 @@ def verify_opset_10(ishape, scales, mode): ) model = helper.make_model(graph, producer_name="resize_test") - verify_with_ort(model, [ishape], [oshape], use_vm=True, freeze_params=True, opset=10) + verify_with_ort( + model, + [ishape], + [oshape], + use_vm=True, + freeze_params=True, + opset=10, + target=target, + dev=dev, + ) verify_opset_10([1, 16, 32, 32], [1, 1, 2, 2], "nearest") verify_opset_10([1, 16, 32, 32], [1, 1, 0.5, 0.5], "linear") -@tvm.testing.uses_gpu -def test_nonzero(): +@tvm.testing.parametrize_targets +def test_nonzero(target, dev): def verify_nonzero(indata, outdata, dtype): node = helper.make_node( "NonZero", @@ -3691,7 +3819,9 @@ def verify_nonzero(indata, outdata, dtype): model = helper.make_model(graph, producer_name="nonzero_test") - verify_with_ort_with_inputs(model, [indata], dtype="int64", use_vm=True, opset=9) + verify_with_ort_with_inputs( + model, [indata], dtype="int64", use_vm=True, opset=9, target=target, dev=dev + ) input_data = np.array([[1, 0], [1, 1]], dtype=np.int64) result = np.array((np.nonzero(input_data))) # expected output [[0, 1, 1], [0, 0, 1]] @@ -3702,8 +3832,8 @@ def verify_nonzero(indata, outdata, dtype): verify_nonzero(input_data, result, dtype=np.int64) -@tvm.testing.uses_gpu -def test_topk(): +@tvm.testing.parametrize_targets +def test_topk(target, dev): def verify_topk(input_dims, K, axis=-1): output_dims = list(input_dims) output_dims[axis] = K @@ -3734,7 +3864,9 @@ def verify_topk(input_dims, K, axis=-1): model = helper.make_model(graph, producer_name="topk_test") indata = np.random.uniform(-10, 10, input_dims).astype(np.float32) - verify_with_ort_with_inputs(model, [indata, np.array([K])], use_vm=True) + verify_with_ort_with_inputs( + model, [indata, np.array([K])], use_vm=True, target=target, dev=dev + ) for n in [12, 32]: for shape in [[n], [n, n], [n, n, n]]: @@ -3746,8 +3878,8 @@ def verify_topk(input_dims, K, axis=-1): verify_topk([n, n, n], 5, 2) -@tvm.testing.uses_gpu -def test_roi_align(): +@tvm.testing.parametrize_targets +def test_roi_align(target, dev): def verify_roi_align( input_dims, num_roi, @@ -3794,7 +3926,11 @@ def verify_roi_align( np_batch_indicies = np.random.randint(low=0, high=input_dims[0], size=num_roi) verify_with_ort_with_inputs( - model, [np_data, np_rois, np_batch_indicies], out_shape=[output_dims] + model, + [np_data, np_rois, np_batch_indicies], + out_shape=[output_dims], + target=target, + dev=dev, ) verify_roi_align((1, 4, 16, 16), 32, 7, 7, sampling_ratio=0, spatial_scale=1.0) @@ -3811,8 +3947,8 @@ def verify_roi_align( # ONNX implementation of roi_align with max mode is incorrect, so we don't compare outputs here. -@tvm.testing.uses_gpu -def test_non_max_suppression(): +@tvm.testing.parametrize_targets +def test_non_max_suppression(target, dev): def verify_nms( boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, output_dims ): @@ -3850,7 +3986,7 @@ def verify_nms( model = helper.make_model(graph, producer_name="nms_test") - verify_with_ort_with_inputs(model, inputs, use_vm=True) + verify_with_ort_with_inputs(model, inputs, use_vm=True, target=target, dev=dev) boxes = np.array( [ @@ -3904,204 +4040,238 @@ def verify_nms( ) -def verify_cond_loop(): - y_in = helper.make_tensor_value_info("y_in", TensorProto.FLOAT, [1]) - y_out = helper.make_tensor_value_info("y_out", TensorProto.FLOAT, [1]) - scan_out = helper.make_tensor_value_info("scan_out", TensorProto.FLOAT, [1]) - cond_in = helper.make_tensor_value_info("cond_in", TensorProto.BOOL, []) - cond_out = helper.make_tensor_value_info("cond_out", TensorProto.BOOL, []) - iter_count = helper.make_tensor_value_info("iter_count", TensorProto.INT64, []) - - y = np.array([-2]).astype(np.float32) - - five_const_node = helper.make_node( - "Constant", - inputs=[], - outputs=["five"], - value=helper.make_tensor( - name="const_tensor_five", data_type=TensorProto.FLOAT, dims=(), vals=[5] - ), - ) - - iter_cast_node = helper.make_node( - "Cast", inputs=["iter_count"], outputs=["iter_cast"], to=onnx.TensorProto.FLOAT - ) - - y_add_node = helper.make_node("Add", inputs=["y_in", "iter_cast"], outputs=["y_out"]) - - less_node = helper.make_node("Less", inputs=["y_out", "five"], outputs=["cond_less"]) +# @tvm.testing.parametrize_targets +@pytest.mark.skip( + "Test regressed due to not being run in CI" + + " tracked here: https://github.com/apache/tvm/pull/8274" +) +def test_loop(target, dev): + def verify_cond_loop(): + y_in = helper.make_tensor_value_info("y_in", TensorProto.FLOAT, [1]) + y_out = helper.make_tensor_value_info("y_out", TensorProto.FLOAT, [1]) + scan_out = helper.make_tensor_value_info("scan_out", TensorProto.FLOAT, [1]) + cond_in = helper.make_tensor_value_info("cond_in", TensorProto.BOOL, []) + cond_out = helper.make_tensor_value_info("cond_out", TensorProto.BOOL, []) + iter_count = helper.make_tensor_value_info("iter_count", TensorProto.INT64, []) + + y = np.array([-2]).astype(np.float32) + + five_const_node = helper.make_node( + "Constant", + inputs=[], + outputs=["five"], + value=helper.make_tensor( + name="const_tensor_five", data_type=TensorProto.FLOAT, dims=(), vals=[5] + ), + ) - squeeze_node = helper.make_node("Squeeze", inputs=["cond_less"], outputs=["cond_squeeze"]) + iter_cast_node = helper.make_node( + "Cast", inputs=["iter_count"], outputs=["iter_cast"], to=onnx.TensorProto.FLOAT + ) - cond_cast_node = helper.make_node( - "Cast", inputs=["cond_squeeze"], outputs=["cond_out"], to=onnx.TensorProto.BOOL - ) + y_add_node = helper.make_node("Add", inputs=["y_in", "iter_cast"], outputs=["y_out"]) - scan_identity_node = helper.make_node("Identity", inputs=["y_out"], outputs=["scan_out"]) + less_node = helper.make_node("Less", inputs=["y_out", "five"], outputs=["cond_less"]) - loop_body = helper.make_graph( - [ - five_const_node, - iter_cast_node, - y_add_node, - less_node, - squeeze_node, - cond_cast_node, - scan_identity_node, - ], - "loop_body", - [iter_count, cond_in, y_in], - [cond_out, y_out, scan_out], - ) + squeeze_node = helper.make_node("Squeeze", inputs=["cond_less"], outputs=["cond_squeeze"]) - loop_node = helper.make_node( - "Loop", inputs=["trip_count", "cond", "y"], outputs=["res_y", "res_scan"], body=loop_body - ) + cond_cast_node = helper.make_node( + "Cast", inputs=["cond_squeeze"], outputs=["cond_out"], to=onnx.TensorProto.BOOL + ) - trip_count = np.array(5).astype(np.int64) - res_y = np.array([13]).astype(np.float32) - cond = np.array(1).astype(bool) - loop_graph = onnx.helper.make_graph( - [loop_node], - "loop_outer", - inputs=[ - onnx.helper.make_tensor_value_info("trip_count", onnx.TensorProto.INT64, []), - onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), - onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT, [1]), - ], - outputs=[ - onnx.helper.make_tensor_value_info("res_y", onnx.TensorProto.FLOAT, [1]), - onnx.helper.make_tensor_value_info("res_scan", onnx.TensorProto.FLOAT, [5, 1]), - ], - ) - loop_model = onnx.helper.make_model(loop_graph) + scan_identity_node = helper.make_node("Identity", inputs=["y_out"], outputs=["scan_out"]) - # Set a high trip count so that condition trips first. - trip_count = np.array(40).astype(np.int64) - cond = np.array(1).astype(bool) - input_vals = [trip_count, cond, y] - verify_with_ort_with_inputs(loop_model, input_vals, use_vm=True, freeze_params=True, opset=11) + loop_body = helper.make_graph( + [ + five_const_node, + iter_cast_node, + y_add_node, + less_node, + squeeze_node, + cond_cast_node, + scan_identity_node, + ], + "loop_body", + [iter_count, cond_in, y_in], + [cond_out, y_out, scan_out], + ) + loop_node = helper.make_node( + "Loop", + inputs=["trip_count", "cond", "y"], + outputs=["res_y", "res_scan"], + body=loop_body, + ) -def verify_count_loop(): - y_in = helper.make_tensor_value_info("y_in", TensorProto.FLOAT, []) - y_out = helper.make_tensor_value_info("y_out", TensorProto.FLOAT, []) - scan_out = helper.make_tensor_value_info("scan_out", TensorProto.FLOAT, []) - cond_in = helper.make_tensor_value_info("cond_in", TensorProto.BOOL, []) - cond_out = helper.make_tensor_value_info("cond_out", TensorProto.BOOL, []) - iter_count = helper.make_tensor_value_info("iter_count", TensorProto.INT64, []) + trip_count = np.array(5).astype(np.int64) + res_y = np.array([13]).astype(np.float32) + cond = np.array(1).astype(bool) + loop_graph = onnx.helper.make_graph( + [loop_node], + "loop_outer", + inputs=[ + onnx.helper.make_tensor_value_info("trip_count", onnx.TensorProto.INT64, []), + onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), + onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT, [1]), + ], + outputs=[ + onnx.helper.make_tensor_value_info("res_y", onnx.TensorProto.FLOAT, [1]), + onnx.helper.make_tensor_value_info("res_scan", onnx.TensorProto.FLOAT, [5, 1]), + ], + ) + loop_model = onnx.helper.make_model(loop_graph) - y = np.array(-2).astype(np.float32) + # Set a high trip count so that condition trips first. + trip_count = np.array(40).astype(np.int64) + cond = np.array(1).astype(bool) + input_vals = [trip_count, cond, y] + verify_with_ort_with_inputs( + loop_model, + input_vals, + use_vm=True, + freeze_params=True, + opset=11, + target=target, + dev=dev, + ) - iter_cast_node = helper.make_node( - "Cast", inputs=["iter_count"], outputs=["iter_cast"], to=onnx.TensorProto.FLOAT - ) + def verify_count_loop(): + y_in = helper.make_tensor_value_info("y_in", TensorProto.FLOAT, []) + y_out = helper.make_tensor_value_info("y_out", TensorProto.FLOAT, []) + scan_out = helper.make_tensor_value_info("scan_out", TensorProto.FLOAT, []) + cond_in = helper.make_tensor_value_info("cond_in", TensorProto.BOOL, []) + cond_out = helper.make_tensor_value_info("cond_out", TensorProto.BOOL, []) + iter_count = helper.make_tensor_value_info("iter_count", TensorProto.INT64, []) - y_add_node = helper.make_node("Add", inputs=["y_in", "iter_cast"], outputs=["y_out"]) + y = np.array(-2).astype(np.float32) - identity_node = helper.make_node("Identity", inputs=["cond_in"], outputs=["cond_out"]) + iter_cast_node = helper.make_node( + "Cast", inputs=["iter_count"], outputs=["iter_cast"], to=onnx.TensorProto.FLOAT + ) - scan_identity_node = helper.make_node("Identity", inputs=["y_out"], outputs=["scan_out"]) + y_add_node = helper.make_node("Add", inputs=["y_in", "iter_cast"], outputs=["y_out"]) - loop_body = helper.make_graph( - [identity_node, iter_cast_node, y_add_node, scan_identity_node], - "loop_body", - [iter_count, cond_in, y_in], - [cond_out, y_out, scan_out], - ) + identity_node = helper.make_node("Identity", inputs=["cond_in"], outputs=["cond_out"]) - loop_node = helper.make_node( - "Loop", inputs=["trip_count", "cond", "y"], outputs=["res_y", "res_scan"], body=loop_body - ) + scan_identity_node = helper.make_node("Identity", inputs=["y_out"], outputs=["scan_out"]) - trip_count = np.array(5).astype(np.int64) - res_y = np.array([13]).astype(np.float32) - cond = np.array(1).astype(bool) - loop_graph = onnx.helper.make_graph( - [loop_node], - "loop_outer", - inputs=[ - onnx.helper.make_tensor_value_info("trip_count", onnx.TensorProto.INT64, []), - onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), - onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT, []), - ], - outputs=[ - onnx.helper.make_tensor_value_info("res_y", onnx.TensorProto.FLOAT, []), - onnx.helper.make_tensor_value_info("res_scan", onnx.TensorProto.FLOAT, [5]), - ], - ) - loop_model = onnx.helper.make_model(loop_graph) + loop_body = helper.make_graph( + [identity_node, iter_cast_node, y_add_node, scan_identity_node], + "loop_body", + [iter_count, cond_in, y_in], + [cond_out, y_out, scan_out], + ) - trip_count = np.array(5).astype(np.int64) - cond = np.array(1).astype(bool) - input_vals = [trip_count, cond, y] - verify_with_ort_with_inputs(loop_model, input_vals, use_vm=True, freeze_params=True, opset=11) + loop_node = helper.make_node( + "Loop", + inputs=["trip_count", "cond", "y"], + outputs=["res_y", "res_scan"], + body=loop_body, + ) + trip_count = np.array(5).astype(np.int64) + res_y = np.array([13]).astype(np.float32) + cond = np.array(1).astype(bool) + loop_graph = onnx.helper.make_graph( + [loop_node], + "loop_outer", + inputs=[ + onnx.helper.make_tensor_value_info("trip_count", onnx.TensorProto.INT64, []), + onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), + onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT, []), + ], + outputs=[ + onnx.helper.make_tensor_value_info("res_y", onnx.TensorProto.FLOAT, []), + onnx.helper.make_tensor_value_info("res_scan", onnx.TensorProto.FLOAT, [5]), + ], + ) + loop_model = onnx.helper.make_model(loop_graph) -def verify_tensor_loop(shapeless_output=False): - y_in = helper.make_tensor_value_info("y_in", TensorProto.FLOAT, [3, 3, 3, 3]) - y_out = helper.make_tensor_value_info("y_out", TensorProto.FLOAT, [3, 3, 3, 3]) - scan_out = helper.make_tensor_value_info("scan_out", TensorProto.FLOAT, [3, 3, 3, 3]) - cond_in = helper.make_tensor_value_info("cond_in", TensorProto.BOOL, []) - cond_out = helper.make_tensor_value_info("cond_out", TensorProto.BOOL, []) - iter_count = helper.make_tensor_value_info("iter_count", TensorProto.INT64, []) + trip_count = np.array(5).astype(np.int64) + cond = np.array(1).astype(bool) + input_vals = [trip_count, cond, y] + verify_with_ort_with_inputs( + loop_model, + input_vals, + use_vm=True, + freeze_params=True, + opset=11, + target=target, + dev=dev, + ) - y = np.random.normal(size=[3, 3, 3, 3]).astype(np.float32) + def verify_tensor_loop(shapeless_output=False): + y_in = helper.make_tensor_value_info("y_in", TensorProto.FLOAT, [3, 3, 3, 3]) + y_out = helper.make_tensor_value_info("y_out", TensorProto.FLOAT, [3, 3, 3, 3]) + scan_out = helper.make_tensor_value_info("scan_out", TensorProto.FLOAT, [3, 3, 3, 3]) + cond_in = helper.make_tensor_value_info("cond_in", TensorProto.BOOL, []) + cond_out = helper.make_tensor_value_info("cond_out", TensorProto.BOOL, []) + iter_count = helper.make_tensor_value_info("iter_count", TensorProto.INT64, []) - iter_cast_node = helper.make_node( - "Cast", inputs=["iter_count"], outputs=["iter_cast"], to=onnx.TensorProto.FLOAT - ) + y = np.random.normal(size=[3, 3, 3, 3]).astype(np.float32) - y_add_node = helper.make_node("Add", inputs=["y_in", "iter_cast"], outputs=["y_out"]) + iter_cast_node = helper.make_node( + "Cast", inputs=["iter_count"], outputs=["iter_cast"], to=onnx.TensorProto.FLOAT + ) - identity_node = helper.make_node("Identity", inputs=["cond_in"], outputs=["cond_out"]) + y_add_node = helper.make_node("Add", inputs=["y_in", "iter_cast"], outputs=["y_out"]) - scan_identity_node = helper.make_node("Identity", inputs=["y_out"], outputs=["scan_out"]) + identity_node = helper.make_node("Identity", inputs=["cond_in"], outputs=["cond_out"]) - loop_body = helper.make_graph( - [identity_node, iter_cast_node, y_add_node, scan_identity_node], - "loop_body", - [iter_count, cond_in, y_in], - [cond_out, y_out, scan_out], - ) + scan_identity_node = helper.make_node("Identity", inputs=["y_out"], outputs=["scan_out"]) - loop_node = helper.make_node( - "Loop", inputs=["trip_count", "cond", "y"], outputs=["res_y", "res_scan"], body=loop_body - ) + loop_body = helper.make_graph( + [identity_node, iter_cast_node, y_add_node, scan_identity_node], + "loop_body", + [iter_count, cond_in, y_in], + [cond_out, y_out, scan_out], + ) - trip_count = np.array(5).astype(np.int64) - cond = np.array(1).astype(bool) + loop_node = helper.make_node( + "Loop", + inputs=["trip_count", "cond", "y"], + outputs=["res_y", "res_scan"], + body=loop_body, + ) - # Allow testing of malformed nodes since pytorch likes to create these. - if shapeless_output: - scan_shape = None - else: - scan_shape = [5, 3, 3, 3, 3] + trip_count = np.array(5).astype(np.int64) + cond = np.array(1).astype(bool) - loop_graph = onnx.helper.make_graph( - [loop_node], - "loop_outer", - inputs=[ - onnx.helper.make_tensor_value_info("trip_count", onnx.TensorProto.INT64, []), - onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), - onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT, [3, 3, 3, 3]), - ], - outputs=[ - onnx.helper.make_tensor_value_info("res_y", onnx.TensorProto.FLOAT, [3, 3, 3, 3]), - onnx.helper.make_tensor_value_info("res_scan", onnx.TensorProto.FLOAT, scan_shape), - ], - ) - loop_model = onnx.helper.make_model(loop_graph) + # Allow testing of malformed nodes since pytorch likes to create these. + if shapeless_output: + scan_shape = None + else: + scan_shape = [5, 3, 3, 3, 3] - trip_count = np.array(5).astype(np.int64) - cond = np.array(1).astype(bool) - input_vals = [trip_count, cond, y] - verify_with_ort_with_inputs( - loop_model, input_vals, use_vm=True, freeze_params=True, convert_to_static=True, opset=11 - ) + loop_graph = onnx.helper.make_graph( + [loop_node], + "loop_outer", + inputs=[ + onnx.helper.make_tensor_value_info("trip_count", onnx.TensorProto.INT64, []), + onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), + onnx.helper.make_tensor_value_info("y", onnx.TensorProto.FLOAT, [3, 3, 3, 3]), + ], + outputs=[ + onnx.helper.make_tensor_value_info("res_y", onnx.TensorProto.FLOAT, [3, 3, 3, 3]), + onnx.helper.make_tensor_value_info("res_scan", onnx.TensorProto.FLOAT, scan_shape), + ], + ) + loop_model = onnx.helper.make_model(loop_graph) + trip_count = np.array(5).astype(np.int64) + cond = np.array(1).astype(bool) + input_vals = [trip_count, cond, y] + verify_with_ort_with_inputs( + loop_model, + input_vals, + use_vm=True, + freeze_params=True, + convert_to_static=True, + opset=11, + target=target, + dev=dev, + ) -def test_loop(): # Test a loop that exits once a condition is met. verify_cond_loop() # Test a loop that exits after a fixed number of iterations with scalar outputs. @@ -4112,71 +4282,72 @@ def test_loop(): verify_tensor_loop(shapeless_output=True) -def verify_if(cond_array, num_outputs): - # Given a bool scalar input cond. - # return constant tensor x if cond is True, otherwise return constant tensor y. +@tvm.testing.parametrize_targets +def test_if(target, dev): + def verify_if(cond_array, num_outputs): + # Given a bool scalar input cond. + # return constant tensor x if cond is True, otherwise return constant tensor y. - def append_constant_nodes(nodes, outputs, expected, name): - outputs.append(onnx.helper.make_tensor_value_info(name, onnx.TensorProto.FLOAT, [5])) + def append_constant_nodes(nodes, outputs, expected, name): + outputs.append(onnx.helper.make_tensor_value_info(name, onnx.TensorProto.FLOAT, [5])) - expected.append(np.random.randn(5).astype("float32")) + expected.append(np.random.randn(5).astype("float32")) - nodes.append( - onnx.helper.make_node( - "Constant", inputs=[], outputs=[name], value=numpy_helper.from_array(expected[-1]) + nodes.append( + onnx.helper.make_node( + "Constant", + inputs=[], + outputs=[name], + value=numpy_helper.from_array(expected[-1]), + ) ) - ) - if_outputs = [] - graph_outputs = [] + if_outputs = [] + graph_outputs = [] - then_nodes, then_outs, then_expected = [], [], [] - else_nodes, else_outs, else_expected = [], [], [] + then_nodes, then_outs, then_expected = [], [], [] + else_nodes, else_outs, else_expected = [], [], [] - for i in range(num_outputs): - append_constant_nodes(then_nodes, then_outs, then_expected, "then_out{}".format(i)) - append_constant_nodes(else_nodes, else_outs, else_expected, "else_out{}".format(i)) + for i in range(num_outputs): + append_constant_nodes(then_nodes, then_outs, then_expected, "then_out{}".format(i)) + append_constant_nodes(else_nodes, else_outs, else_expected, "else_out{}".format(i)) - if_outputs.append("res{}".format(i)) - graph_outputs.append( - onnx.helper.make_tensor_value_info("res{}".format(i), onnx.TensorProto.FLOAT, [5]), - ) + if_outputs.append("res{}".format(i)) + graph_outputs.append( + onnx.helper.make_tensor_value_info("res{}".format(i), onnx.TensorProto.FLOAT, [5]), + ) - then_body = onnx.helper.make_graph(then_nodes, "then_body", [], then_outs) - else_body = onnx.helper.make_graph(else_nodes, "else_body", [], else_outs) + then_body = onnx.helper.make_graph(then_nodes, "then_body", [], then_outs) + else_body = onnx.helper.make_graph(else_nodes, "else_body", [], else_outs) - if_node = onnx.helper.make_node( - "If", inputs=["cond"], outputs=if_outputs, then_branch=then_body, else_branch=else_body - ) + if_node = onnx.helper.make_node( + "If", inputs=["cond"], outputs=if_outputs, then_branch=then_body, else_branch=else_body + ) - if_graph = onnx.helper.make_graph( - [if_node], - "if_outer", - inputs=[ - onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), - ], - outputs=graph_outputs, - ) + if_graph = onnx.helper.make_graph( + [if_node], + "if_outer", + inputs=[ + onnx.helper.make_tensor_value_info("cond", onnx.TensorProto.BOOL, []), + ], + outputs=graph_outputs, + ) - if_model = onnx.helper.make_model(if_graph) - if cond_array: - cond = np.array([1]).astype("bool") - else: - cond = np.array(1).astype("bool") - correct_out = then_expected if cond else else_expected + if_model = onnx.helper.make_model(if_graph) + if cond_array: + cond = np.array([1]).astype("bool") + else: + cond = np.array(1).astype("bool") + correct_out = then_expected if cond else else_expected - # TODO(jwfromm): Onnxruntime 1.0.0 is buggy with If statements. Replace this with - # verify_with_ort once we update versions. - for target, dev in tvm.testing.enabled_targets(): + # TODO(jwfromm): Onnxruntime 1.0.0 is buggy with If statements. Replace this with + # verify_with_ort once we update versions. tvm_out = get_tvm_output_with_vm(if_model, [cond], target, dev, freeze_params=True) if not isinstance(tvm_out, list): tvm_out = [tvm_out] for i in range(len(tvm_out)): tvm.testing.assert_allclose(correct_out[i], tvm_out[i], rtol=1e-05, atol=1e-05) - -@tvm.testing.uses_gpu -def test_if(): # Confirm that if works with cond as an array or scalar. verify_if(cond_array=False, num_outputs=1) verify_if(cond_array=False, num_outputs=2) @@ -4184,8 +4355,8 @@ def test_if(): verify_if(cond_array=True, num_outputs=2) -@tvm.testing.uses_gpu -def test_size(): +@tvm.testing.parametrize_targets +def test_size(target, dev): def verify_size(indata): node = helper.make_node( "Size", @@ -4202,7 +4373,9 @@ def verify_size(indata): model = helper.make_model(graph, producer_name="size_test") - verify_with_ort_with_inputs(model, [indata], dtype="int64", use_vm=True, opset=11) + verify_with_ort_with_inputs( + model, [indata], dtype="int64", use_vm=True, opset=11, target=target, dev=dev + ) input_data = np.array([[1, 0], [1, 1]], dtype=np.int64) verify_size(input_data) @@ -4211,8 +4384,8 @@ def verify_size(indata): verify_size(input_data) -@tvm.testing.uses_gpu -def test_maxunpool(): +@tvm.testing.parametrize_targets +def test_maxunpool(target, dev): def verify_maxunpool(data, indices, kernel_shape, strides, output_shape=None, pads=None): input_names = ["xT", "xI"] input_info = [ @@ -4261,7 +4434,9 @@ def verify_maxunpool(data, indices, kernel_shape, strides, output_shape=None, pa model = helper.make_model(graph, producer_name="size_test") - verify_with_ort_with_inputs(model, input_values, use_vm=True, opset=11) + verify_with_ort_with_inputs( + model, input_values, use_vm=True, opset=11, target=target, dev=dev + ) # Basic test xT = np.array([[[[5, 6], [7, 8]]]], dtype=np.float32) @@ -4279,8 +4454,8 @@ def verify_maxunpool(data, indices, kernel_shape, strides, output_shape=None, pa verify_maxunpool(xT, xI, [2, 2], strides=[2, 2], pads=pads) -@tvm.testing.uses_gpu -def test_softplus(): +@tvm.testing.parametrize_targets +def test_softplus(target, dev): def verify_softplus(indata): node = helper.make_node( "Softplus", @@ -4297,7 +4472,9 @@ def verify_softplus(indata): model = helper.make_model(graph, producer_name="softplus_test") - verify_with_ort_with_inputs(model, [indata], dtype="float32", use_vm=True, opset=11) + verify_with_ort_with_inputs( + model, [indata], dtype="float32", use_vm=True, opset=11, target=target, dev=dev + ) # Simple case with all signs. input_data = np.array([[-1, 0, 1]], dtype=np.float32) @@ -4307,8 +4484,8 @@ def verify_softplus(indata): verify_softplus(input_data) -@tvm.testing.uses_gpu -def test_cumsum(): +@tvm.testing.parametrize_targets +def test_cumsum(target, dev): def verify_cumsum(indata, axis, exclusive=0, reverse=0, type="float32"): cumsum_node = onnx.helper.make_node( "CumSum", @@ -4342,7 +4519,9 @@ def verify_cumsum(indata, axis, exclusive=0, reverse=0, type="float32"): model = helper.make_model(graph, producer_name="cumsum_test") - verify_with_ort_with_inputs(model, [indata], dtype=type, use_vm=True, opset=11) + verify_with_ort_with_inputs( + model, [indata], dtype=type, use_vm=True, opset=11, target=target, dev=dev + ) data = ( np.array( @@ -4384,8 +4563,8 @@ def verify_cumsum(indata, axis, exclusive=0, reverse=0, type="float32"): verify_cumsum(data, 1, 1, 1, type="int32") -@tvm.testing.uses_gpu -def test_eyelike(): +@tvm.testing.parametrize_targets +def test_eyelike(target, dev): def verify_eyelike(indata): node = helper.make_node( "EyeLike", @@ -4402,24 +4581,23 @@ def verify_eyelike(indata): model = helper.make_model(graph, producer_name="eyelike_test") - verify_with_ort_with_inputs(model, [indata], dtype="float32", opset=9) + verify_with_ort_with_inputs( + model, [indata], dtype="float32", opset=9, target=target, dev=dev + ) input_data = np.zeros((5, 5), dtype=np.float32) verify_eyelike(input_data) """ - The following parameterized tests loads the tests that ONNX ships as + The following parametrized tests loads the tests that ONNX ships as serialized ONNX files, inputs, and outputs. The goal of this test is to ensure the ONNX importer is in line with the ONNX specification. To allow these tests to run in CI before all pass, a number of tests that are not yet supported are skipped. """ -from onnx import numpy_helper - f = onnx.__file__ -import glob onnx_test_folders = sorted(glob.glob("/".join(f.split("/")[0:-1]) + "/backend/test/data/node/*/")) @@ -4552,6 +4730,8 @@ def verify_eyelike(indata): "test_pow_types_int64_int64/", "test_qlinearmatmul_2D/", "test_qlinearmatmul_3D/", + "test_range_float_type_positive_delta_expanded/", + "test_range_int32_type_negative_delta_expanded/", "test_reduce_sum_default_axes_keepdims_example/", "test_reduce_sum_default_axes_keepdims_random/", "test_reduce_sum_do_not_keepdims_example/", @@ -4696,10 +4876,10 @@ def verify_eyelike(indata): ] -targets = [tgt for (tgt, _) in tvm.testing.enabled_targets()] - target_skips = { "cuda": [ + "test_basic_convinteger/", + "test_convinteger_with_padding/", "test_mod_mixed_sign_float16/", "test_qlinearconv/", "test_resize_upsample_sizes_nearest/", @@ -4707,9 +4887,9 @@ def verify_eyelike(indata): } -@pytest.mark.parametrize("target", targets) @pytest.mark.parametrize("test", onnx_test_folders) -def test_onnx_nodes(test, target): +@tvm.testing.parametrize_targets +def test_onnx_nodes(test, target, dev): if target in target_skips: for failure in target_skips[target]: if failure in test: @@ -4741,7 +4921,6 @@ def test_onnx_nodes(test, target): else: raise ImportError(str(tensor) + " not labeled as an import or an output") - dev = tvm.device(target, 0) tvm_val = get_tvm_output_with_vm(onnx_model, inputs, target, dev) if len(outputs) == 1: tvm.testing.assert_allclose(outputs[0], tvm_val, rtol=rtol, atol=atol) @@ -4775,7 +4954,8 @@ def test_wrong_input(): relay.frontend.from_onnx(model, shape=wrong_shape_dict) -def test_aten(): +@tvm.testing.parametrize_targets +def test_aten(target, dev): torch.set_grad_enabled(False) def _convert_to_onnx(model, inputs): @@ -4799,43 +4979,46 @@ def verify_embedding_bag(num_embedding, embedding_dim, data_shape, num_bags=None model = torch.nn.EmbeddingBag(num_embedding, embedding_dim) onnx_model = _convert_to_onnx(model, dummy_data) torch_out = model(dummy_data) - for target, ctx in tvm.testing.enabled_targets(): - tvm_out = get_tvm_output_with_vm( - onnx_model, tvm_inputs, target, ctx, freeze_params=True, convert_to_static=True - ) - tvm.testing.assert_allclose(torch_out.numpy(), tvm_out) + tvm_out = get_tvm_output_with_vm( + onnx_model, + tvm_inputs, + freeze_params=True, + convert_to_static=True, + target=target, + dev=dev, + ) + tvm.testing.assert_allclose(torch_out.numpy(), tvm_out) verify_embedding_bag(10, 3, [2, 10]) verify_embedding_bag(32, 2, [3, 3]) -def verify_reverse_sequence(x, sequence_lens, batch_axis, time_axis): - node = onnx.helper.make_node( - "ReverseSequence", - inputs=["x", "sequence_lens"], - outputs=["y"], - time_axis=time_axis, - batch_axis=batch_axis, - ) - - graph = helper.make_graph( - [node], - "reverse_sequence_test", - inputs=[ - helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x.shape)), - helper.make_tensor_value_info( - "sequence_lens", TensorProto.INT64, list(sequence_lens.shape) - ), - ], - outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(x.shape))], - ) +@tvm.testing.parametrize_targets +def test_reverse_sequence(target, dev): + def verify_reverse_sequence(x, sequence_lens, batch_axis, time_axis): + node = onnx.helper.make_node( + "ReverseSequence", + inputs=["x", "sequence_lens"], + outputs=["y"], + time_axis=time_axis, + batch_axis=batch_axis, + ) - model = helper.make_model(graph, producer_name="reverse_sequence_test") - verify_with_ort_with_inputs(model, [x, sequence_lens], [x.shape]) + graph = helper.make_graph( + [node], + "reverse_sequence_test", + inputs=[ + helper.make_tensor_value_info("x", TensorProto.FLOAT, list(x.shape)), + helper.make_tensor_value_info( + "sequence_lens", TensorProto.INT64, list(sequence_lens.shape) + ), + ], + outputs=[helper.make_tensor_value_info("y", TensorProto.FLOAT, list(x.shape))], + ) + model = helper.make_model(graph, producer_name="reverse_sequence_test") + verify_with_ort_with_inputs(model, [x, sequence_lens], [x.shape], target=target, dev=dev) -@tvm.testing.uses_gpu -def test_reverse_sequence(): x = np.array( [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]], dtype=np.float32, @@ -4847,95 +5030,98 @@ def test_reverse_sequence(): verify_reverse_sequence(x, sequence_lens, 1, 0) -def verify_qlinearconv( - x_shape, - w_shape, - y_shape, - padding, - kernel_shape, - strides, - dilations, - auto_pad="NOTSET", - bias=False, -): +@tvm.testing.parametrize_targets +def test_qlinearconv(target, dev): + if "cuda" in target: + pytest.skip("Fails on CUDA") + + def verify_qlinearconv( + x_shape, + w_shape, + y_shape, + padding, + kernel_shape, + strides, + dilations, + auto_pad="NOTSET", + bias=False, + ): - x_array = np.random.randint(low=0, high=255, size=x_shape).astype("uint8") - w_array = np.random.uniform(low=0, high=255, size=w_shape).astype("uint8") + x_array = np.random.randint(low=0, high=255, size=x_shape).astype("uint8") + w_array = np.random.uniform(low=0, high=255, size=w_shape).astype("uint8") - initializer = [ - helper.make_tensor("x_scale", TensorProto.FLOAT, (), [np.random.rand()]), - helper.make_tensor("x_zero_point", TensorProto.UINT8, (), [np.random.randint(0, 255)]), - helper.make_tensor("w_scale", TensorProto.FLOAT, (), [np.random.rand()]), - helper.make_tensor("w_zero_point", TensorProto.UINT8, (), [np.random.randint(0, 255)]), - helper.make_tensor("y_scale", TensorProto.FLOAT, (), [np.random.rand()]), - helper.make_tensor("y_zero_point", TensorProto.UINT8, (), [np.random.randint(0, 255)]), - ] + initializer = [ + helper.make_tensor("x_scale", TensorProto.FLOAT, (), [np.random.rand()]), + helper.make_tensor("x_zero_point", TensorProto.UINT8, (), [np.random.randint(0, 255)]), + helper.make_tensor("w_scale", TensorProto.FLOAT, (), [np.random.rand()]), + helper.make_tensor("w_zero_point", TensorProto.UINT8, (), [np.random.randint(0, 255)]), + helper.make_tensor("y_scale", TensorProto.FLOAT, (), [np.random.rand()]), + helper.make_tensor("y_zero_point", TensorProto.UINT8, (), [np.random.randint(0, 255)]), + ] - input_nodes = [ - helper.make_tensor_value_info("x", TensorProto.UINT8, list(x_shape)), - helper.make_tensor_value_info("w", TensorProto.UINT8, list(w_shape)), - ] - input_names = [ - "x", - "x_scale", - "x_zero_point", - "w", - "w_scale", - "w_zero_point", - "y_scale", - "y_zero_point", - ] - input_values = [x_array, w_array] - - if bias is True: - b_shape = w_shape[0:1] - b_array = np.random.randint(low=0, high=65536, size=b_shape).astype("int32") - input_nodes.append(helper.make_tensor_value_info("B", TensorProto.INT32, list(b_shape))) - input_names.append("B") - input_values.append(b_array) - - if padding is None: - ## autopadding with unset default attributes - kwargs = {} - if not all([s == 1 for s in strides]): - kwargs["strides"] = strides - if not all([d == 1 for d in dilations]): - kwargs["dilations"] = dilations + input_nodes = [ + helper.make_tensor_value_info("x", TensorProto.UINT8, list(x_shape)), + helper.make_tensor_value_info("w", TensorProto.UINT8, list(w_shape)), + ] + input_names = [ + "x", + "x_scale", + "x_zero_point", + "w", + "w_scale", + "w_zero_point", + "y_scale", + "y_zero_point", + ] + input_values = [x_array, w_array] - node = helper.make_node( - "QLinearConv", - inputs=input_names, - outputs=["y"], - # Default values for other attributes: - auto_pad=auto_pad, - **kwargs, - ) - else: - node = helper.make_node( - "QLinearConv", - inputs=input_names, - outputs=["y"], - kernel_shape=kernel_shape, - # Default values for other attributes: - strides=strides, - dilations=dilations, - # groups=1 - pads=padding, - ) + if bias is True: + b_shape = w_shape[0:1] + b_array = np.random.randint(low=0, high=65536, size=b_shape).astype("int32") + input_nodes.append(helper.make_tensor_value_info("B", TensorProto.INT32, list(b_shape))) + input_names.append("B") + input_values.append(b_array) - graph = helper.make_graph( - [node], - "conv_test", - inputs=input_nodes, - outputs=[helper.make_tensor_value_info("y", TensorProto.UINT8, list(y_shape))], - initializer=initializer, - ) - model = helper.make_model(graph, producer_name="qlinearconv_test") - # opt_level=1 will cause error - verify_with_ort_with_inputs(model, input_values, opt_level=2) + if padding is None: + ## autopadding with unset default attributes + kwargs = {} + if not all([s == 1 for s in strides]): + kwargs["strides"] = strides + if not all([d == 1 for d in dilations]): + kwargs["dilations"] = dilations + + node = helper.make_node( + "QLinearConv", + inputs=input_names, + outputs=["y"], + # Default values for other attributes: + auto_pad=auto_pad, + **kwargs, + ) + else: + node = helper.make_node( + "QLinearConv", + inputs=input_names, + outputs=["y"], + kernel_shape=kernel_shape, + # Default values for other attributes: + strides=strides, + dilations=dilations, + # groups=1 + pads=padding, + ) + graph = helper.make_graph( + [node], + "conv_test", + inputs=input_nodes, + outputs=[helper.make_tensor_value_info("y", TensorProto.UINT8, list(y_shape))], + initializer=initializer, + ) + model = helper.make_model(graph, producer_name="qlinearconv_test") + # opt_level=1 will cause error + verify_with_ort_with_inputs(model, input_values, opt_level=2, target=target, dev=dev) -def test_qlinearconv(): def repeat(N, D): return tuple([N for _ in range(D)]) @@ -5030,197 +5216,198 @@ def repeat(N, D): ) -def verify_qlinearadd(a_shape, b_shape, c_shape): +@tvm.testing.parametrize_targets +def test_qlinearadd(target, dev): + def verify_qlinearadd(a_shape, b_shape, c_shape): - a_array = np.random.random(a_shape).astype("float32") - b_array = np.random.random(b_shape).astype("float32") + a_array = np.random.random(a_shape).astype("float32") + b_array = np.random.random(b_shape).astype("float32") - input_nodes = [ - helper.make_tensor_value_info("a", TensorProto.FLOAT, list(a_shape)), - helper.make_tensor_value_info("b", TensorProto.FLOAT, list(b_shape)), - ] - input_names = [ - "a", - "b", - ] - input_values = [a_array, b_array] + input_nodes = [ + helper.make_tensor_value_info("a", TensorProto.FLOAT, list(a_shape)), + helper.make_tensor_value_info("b", TensorProto.FLOAT, list(b_shape)), + ] + input_names = [ + "a", + "b", + ] + input_values = [a_array, b_array] - node = helper.make_node("QLinearAdd", inputs=input_names, outputs=["C"]) + node = helper.make_node("QLinearAdd", inputs=input_names, outputs=["C"]) - node = helper.make_node("Add", ["a", "b"], ["C"]) - graph = helper.make_graph( - [node], - "qlinearadd_test", - inputs=input_nodes, - outputs=[helper.make_tensor_value_info("C", TensorProto.FLOAT, list(c_shape))], - ) - model = helper.make_model(graph, producer_name="qlinearconv_test") - from onnxruntime.quantization import quantize_static, CalibrationDataReader, QuantType - - class RandomDataReader(CalibrationDataReader): - def __init__(self, n=10): - self.data = iter( - [ - { - "a": np.random.random(a_shape).astype("float32"), - "b": np.random.random(b_shape).astype("float32"), - } - for _ in range(n) - ] - ) + node = helper.make_node("Add", ["a", "b"], ["C"]) + graph = helper.make_graph( + [node], + "qlinearadd_test", + inputs=input_nodes, + outputs=[helper.make_tensor_value_info("C", TensorProto.FLOAT, list(c_shape))], + ) + model = helper.make_model(graph, producer_name="qlinearconv_test") + from onnxruntime.quantization import quantize_static, CalibrationDataReader, QuantType - def get_next(self): - return next(self.data, None) + class RandomDataReader(CalibrationDataReader): + def __init__(self, n=10): + self.data = iter( + [ + { + "a": np.random.random(a_shape).astype("float32"), + "b": np.random.random(b_shape).astype("float32"), + } + for _ in range(n) + ] + ) - d = tvm.contrib.utils.tempdir() - model_fp32 = os.path.join(d.temp_dir, "model.onnx") - onnx.save_model(model, model_fp32) - model_quant = os.path.join(d.temp_dir, "model.quant.onnx") - quantized_model = quantize_static(model_fp32, model_quant, RandomDataReader()) - # opt_level=1 will cause error with qnn lowering - model = onnx.load(model_quant) - verify_with_ort_with_inputs(model, input_values, opt_level=2) + def get_next(self): + return next(self.data, None) + d = tvm.contrib.utils.tempdir() + model_fp32 = os.path.join(d.temp_dir, "model.onnx") + onnx.save_model(model, model_fp32) + model_quant = os.path.join(d.temp_dir, "model.quant.onnx") + quantized_model = quantize_static(model_fp32, model_quant, RandomDataReader()) + # opt_level=1 will cause error with qnn lowering + model = onnx.load(model_quant) + verify_with_ort_with_inputs(model, input_values, opt_level=2, target=target, dev=dev) -def test_qlinearadd(): verify_qlinearadd([4, 2], [4, 2], [4, 2]) verify_qlinearadd([4, 2], [2], [4, 2]) verify_qlinearadd([5, 1, 7], [2, 7], [5, 2, 7]) -def get_random_uniform(shape, dtype="float32", high=1.0, low=0.0, seed=None, target="llvm"): - ONNX_DTYPE = mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)] - node = helper.make_node( - "RandomUniform", [], ["out"], shape=shape, dtype=ONNX_DTYPE, high=high, low=low - ) - if seed is not None: - seed_attr = helper.make_attribute("seed", seed) - node.attribute.append(seed_attr) +@tvm.testing.parametrize_targets +def test_random_uniform(target, dev): + def get_random_uniform(shape, dtype="float32", high=1.0, low=0.0, seed=None): + ONNX_DTYPE = mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)] + node = helper.make_node( + "RandomUniform", [], ["out"], shape=shape, dtype=ONNX_DTYPE, high=high, low=low + ) + if seed is not None: + seed_attr = helper.make_attribute("seed", seed) + node.attribute.append(seed_attr) - graph = helper.make_graph( - [node], - "random_uniform_test", - inputs=[], - outputs=[helper.make_tensor_value_info("out", ONNX_DTYPE, shape)], - ) - model = helper.make_model(graph, producer_name="random_uniform_test") - return get_tvm_output_with_vm(model, [], target=target, device=tvm.device(target, 0)) - - -def test_random_uniform(): - targets = [tgt for (tgt, _) in tvm.testing.enabled_targets()] - for target in targets: - # Check that function runs and produces proper shape. - vals = get_random_uniform([10], dtype="float32", target=target) - assert list(vals.shape) == [10] - assert vals.dtype == "float32" - - # Test N-D tensor generation. - vals = get_random_uniform([1, 3, 100, 100], dtype="float32", target=target) - assert list(vals.shape) == [1, 3, 100, 100] - - # Check that bounds aren't exceeded. - vals = get_random_uniform(shape=[100], high=100, low=-100) - assert list(vals.shape) == [100] - assert all(vals >= -100) and all(vals <= 100) - - # Check that a fixed seed produces the same values when run twice. - vals_1 = get_random_uniform(shape=[10], seed=1) - vals_2 = get_random_uniform(shape=[10], seed=1) - assert all(vals_1 == vals_2) - - # Test against an expected output with a fixed seed. - real = get_random_uniform(shape=[10], seed=5) - expected = np.asarray( - [ - 0.8614111, - 0.46572232, - 0.6007328, - 0.21619737, - 0.6361222, - 0.7298056, - 0.13094282, - 0.03556716, - 0.32997167, - 0.2977605, - ] + graph = helper.make_graph( + [node], + "random_uniform_test", + inputs=[], + outputs=[helper.make_tensor_value_info("out", ONNX_DTYPE, shape)], ) - tvm.testing.assert_allclose(real, expected, rtol=1e-5) + model = helper.make_model(graph, producer_name="random_uniform_test") + return get_tvm_output_with_vm(model, [], target=target, dev=dev) + + # Check that function runs and produces proper shape. + vals = get_random_uniform([10], dtype="float32") + assert list(vals.shape) == [10] + assert vals.dtype == "float32" + + # Test N-D tensor generation. + vals = get_random_uniform([1, 3, 100, 100], dtype="float32") + assert list(vals.shape) == [1, 3, 100, 100] + + # Check that bounds aren't exceeded. + vals = get_random_uniform(shape=[100], high=100, low=-100) + assert list(vals.shape) == [100] + assert all(vals >= -100) and all(vals <= 100) + + # Check that a fixed seed produces the same values when run twice. + vals_1 = get_random_uniform(shape=[10], seed=1) + vals_2 = get_random_uniform(shape=[10], seed=1) + assert all(vals_1 == vals_2) + + # Test against an expected output with a fixed seed. + real = get_random_uniform(shape=[10], seed=5) + expected = np.asarray( + [ + 0.8614111, + 0.46572232, + 0.6007328, + 0.21619737, + 0.6361222, + 0.7298056, + 0.13094282, + 0.03556716, + 0.32997167, + 0.2977605, + ] + ) + tvm.testing.assert_allclose(real, expected, rtol=1e-5) -def verify_convinteger( - x_shape, - w_shape, - y_shape, - padding, - kernel_shape, - strides, - dilations, - auto_pad="NOTSET", - dtype="uint8", -): +@tvm.testing.parametrize_targets +def test_convinteger(target, dev): + if "cuda" in target: + pytest.skip("Fails on CUDA") - x_array = np.random.randint(low=0, high=255, size=x_shape).astype(dtype) - w_array = np.random.uniform(low=0, high=255, size=w_shape).astype(dtype) - x_zero_point_array = np.random.randint(0, 255, size=[]).astype(dtype) - w_zero_point_array = np.random.randint(0, 255, size=[]).astype(dtype) - - ONNX_DTYPE = mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)] - input_nodes = [ - helper.make_tensor_value_info("x", ONNX_DTYPE, list(x_shape)), - helper.make_tensor_value_info("w", ONNX_DTYPE, list(w_shape)), - helper.make_tensor_value_info("x_zero_point", ONNX_DTYPE, []), - helper.make_tensor_value_info("w_zero_point", ONNX_DTYPE, []), - ] - input_names = [ - "x", - "w", - "x_zero_point", - "w_zero_point", - ] - input_values = [x_array, w_array, x_zero_point_array, w_zero_point_array] + def verify_convinteger( + x_shape, + w_shape, + y_shape, + padding, + kernel_shape, + strides, + dilations, + auto_pad="NOTSET", + dtype="uint8", + ): - if padding is None: - ## autopadding with unset default attributes - kwargs = {} - if not all([s == 1 for s in strides]): - kwargs["strides"] = strides - if not all([d == 1 for d in dilations]): - kwargs["dilations"] = dilations + x_array = np.random.randint(low=0, high=255, size=x_shape).astype(dtype) + w_array = np.random.uniform(low=0, high=255, size=w_shape).astype(dtype) + x_zero_point_array = np.random.randint(0, 255, size=[]).astype(dtype) + w_zero_point_array = np.random.randint(0, 255, size=[]).astype(dtype) - node = helper.make_node( - "ConvInteger", - inputs=input_names, - outputs=["y"], - # Default values for other attributes: - auto_pad=auto_pad, - **kwargs, - ) - else: - node = helper.make_node( - "ConvInteger", - inputs=input_names, - outputs=["y"], - kernel_shape=kernel_shape, - # Default values for other attributes: - strides=strides, - dilations=dilations, - # groups=1 - pads=padding, - ) + ONNX_DTYPE = mapping.NP_TYPE_TO_TENSOR_TYPE[np.dtype(dtype)] + input_nodes = [ + helper.make_tensor_value_info("x", ONNX_DTYPE, list(x_shape)), + helper.make_tensor_value_info("w", ONNX_DTYPE, list(w_shape)), + helper.make_tensor_value_info("x_zero_point", ONNX_DTYPE, []), + helper.make_tensor_value_info("w_zero_point", ONNX_DTYPE, []), + ] + input_names = [ + "x", + "w", + "x_zero_point", + "w_zero_point", + ] + input_values = [x_array, w_array, x_zero_point_array, w_zero_point_array] - graph = helper.make_graph( - [node], - "convinteger_test", - inputs=input_nodes, - outputs=[helper.make_tensor_value_info("y", TensorProto.INT32, list(y_shape))], - ) - model = helper.make_model(graph, producer_name="convinteger_test") - # opt_level=1 will cause error - verify_with_ort_with_inputs(model, input_values, opt_level=2) + if padding is None: + ## autopadding with unset default attributes + kwargs = {} + if not all([s == 1 for s in strides]): + kwargs["strides"] = strides + if not all([d == 1 for d in dilations]): + kwargs["dilations"] = dilations + + node = helper.make_node( + "ConvInteger", + inputs=input_names, + outputs=["y"], + # Default values for other attributes: + auto_pad=auto_pad, + **kwargs, + ) + else: + node = helper.make_node( + "ConvInteger", + inputs=input_names, + outputs=["y"], + kernel_shape=kernel_shape, + # Default values for other attributes: + strides=strides, + dilations=dilations, + # groups=1 + pads=padding, + ) + graph = helper.make_graph( + [node], + "convinteger_test", + inputs=input_nodes, + outputs=[helper.make_tensor_value_info("y", TensorProto.INT32, list(y_shape))], + ) + model = helper.make_model(graph, producer_name="convinteger_test") + # opt_level=1 will cause error + verify_with_ort_with_inputs(model, input_values, opt_level=2, target=target, dev=dev) -def test_convinteger(): def repeat(N, D): return tuple([N for _ in range(D)]) diff --git a/tests/scripts/task_python_frontend.sh b/tests/scripts/task_python_frontend.sh index fb388a6b7edd..62a0fa1e7fc8 100755 --- a/tests/scripts/task_python_frontend.sh +++ b/tests/scripts/task_python_frontend.sh @@ -35,10 +35,7 @@ echo "Running relay MXNet frontend test..." run_pytest cython python-frontend-mxnet tests/python/frontend/mxnet echo "Running relay ONNX frontend test..." -# Enable tvm.testing decorators in the ONNX importer test (not enabling in the other tests because we -# they do not consistently use the decorators to indicate that tests should run on GPU) -# In the future, we should enable tvm.testing decorators for all the test files. -PYTEST_ADDOPTS="-m gpu $PYTEST_ADDOPTS" run_pytest cython python-frontend-onnx tests/python/frontend/onnx +run_pytest cython python-frontend-onnx tests/python/frontend/onnx echo "Running relay CoreML frontend test..." run_pytest cython python-frontend-coreml tests/python/frontend/coreml