diff --git a/python/tvm/relay/frontend/onnx.py b/python/tvm/relay/frontend/onnx.py index 997aa6240..abfa5629d 100644 --- a/python/tvm/relay/frontend/onnx.py +++ b/python/tvm/relay/frontend/onnx.py @@ -5061,10 +5061,27 @@ class Momentum(OnnxOpConverter): return _expr.TupleWrapper(_expr.Tuple(result), len(result)) +class Round(OnnxOpConverter): + """Operator converter for round op.""" + + @classmethod + def _impl_v11(cls, inputs, attr, params): + # Onnx round uses Banker's rounding which rounds .5 to the nearest even integer + + x = inputs[0] + half = _expr.const(0.5, dtype="float32") + one = _expr.const(1, dtype="float32") + two = _expr.const(2, dtype="float32") + + rounded = _op.ceil(x - half) + bankers_mask = one - (_op.ceil(x + half) - _op.floor(x + half)) + non_even = _op.abs(_op.mod(rounded, two)) + return rounded + (bankers_mask * non_even) + + # compatible operators that do NOT require any conversion. _identity_list = [] - # _convert_map defines maps of name to converter functor(callable) # for 1 to 1 mapping, use Renamer if nothing but name is different # use AttrCvt if attributes need to be converted @@ -5109,7 +5126,7 @@ def _get_convert_map(opset): "Reciprocal": Reciprocal.get_converter(opset), "Floor": Renamer("floor"), "Ceil": Renamer("ceil"), - "Round": Renamer("round"), + "Round": Round.get_converter(opset), "IsInf": IsInf.get_converter(opset), "IsNaN": Renamer("isnan"), "Sqrt": Renamer("sqrt"), diff --git a/tests/python/frontend/onnx/test_forward.py b/tests/python/frontend/onnx/test_forward.py index c4cd93aa7..ebaad9b4c 100644 --- a/tests/python/frontend/onnx/test_forward.py +++ b/tests/python/frontend/onnx/test_forward.py @@ -5183,7 +5183,6 @@ unsupported_onnx_tests = [ "test_reduce_sum_negative_axes_keepdims_example", "test_reduce_sum_negative_axes_keepdims_random", "test_rnn_seq_length", - "test_round", "test_sequence_insert_at_back", "test_sequence_insert_at_front", "test_simple_rnn_batchwise",