import unittest from typing import Any, Tuple from onnx.backend.base import Backend, BackendRep import onnx.backend.test import numpy as np from tinygrad import Tensor, Device, dtypes from tinygrad.helpers import getenv, OSX from tinygrad.device import is_dtype_supported # pip3 install tabulate pytest_plugins = 'onnx.backend.test.report', from tinygrad.frontend.onnx import OnnxRunner class TinygradModel(BackendRep): def __init__(self, run_onnx, input_names): super().__init__() self.fxn = run_onnx self.input_names = input_names def run(self, inputs: Any, **kwargs: Any) -> Tuple[Any, ...]: real_inputs = dict(zip(self.input_names, inputs)) ret = self.fxn(real_inputs, debug=2) return tuple(x.numpy() if isinstance(x, Tensor) else [i.numpy() for i in x] if isinstance(x, list) else np.array(x) for x in ret.values()) class TinygradBackend(Backend): @classmethod def prepare(cls, model, device): input_all = [x.name for x in model.graph.input] input_initializer = [x.name for x in model.graph.initializer] net_feed_input = [x for x in input_all if x not in input_initializer] print("prepare", cls, device, net_feed_input) run_onnx = OnnxRunner(model) return TinygradModel(run_onnx, net_feed_input) @classmethod def supports_device(cls, device: str) -> bool: # NOTE: this is onnx CPU return device == "CPU" backend_test = onnx.backend.test.BackendTest(TinygradBackend, __name__) # BUG: buggy onnx tests backend_test.exclude('test_adam_multiple_cpu') backend_test.exclude('test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_True_cpu') # BUG: onnxruntime 1.20.1 fails these tests too backend_test.exclude('test_qlinearmatmul_2D_int8_float16_cpu') backend_test.exclude('test_qlinearmatmul_3D_int8_float16_cpu') backend_test.exclude('test_qlinearmatmul_2D_int8_float32_cpu') backend_test.exclude('test_qlinearmatmul_3D_int8_float32_cpu') # BUG: we don't match ORT here due to some div inaccuracy with floats backend_test.exclude('test_dynamicquantizelinear_cpu') backend_test.exclude('test_dynamicquantizelinear_expanded_cpu') # BUG: we match ORT, tested in TestMainOnnxOps.test_maxunpool backend_test.exclude('test_maxunpool_export_with_output_shape_cpu') # about different dtypes if not is_dtype_supported(dtypes.float64): backend_test.exclude('float64') backend_test.exclude('DOUBLE') # these have float64 inputs backend_test.exclude('test_eyelike_with_dtype_cpu') backend_test.exclude('test_reduce_log_sum_exp*') backend_test.exclude('test_operator_add*') backend_test.exclude('test_einsum_*') backend_test.exclude('test_cumsum_*') if not is_dtype_supported(dtypes.float16): backend_test.exclude('float16') backend_test.exclude('FLOAT16') # dtype cast backend_test.exclude('STRING') backend_test.exclude('FLOAT8') backend_test.exclude('INT4') backend_test.exclude('UINT4') backend_test.exclude('BFLOAT16') # not supported in numpy # TODO: fix these with true onnx float16 backend_test.exclude('to_FLOAT16') backend_test.exclude('cast_no_saturate') backend_test.exclude('test_dequantizelinear_e4m3fn_float16_cpu') backend_test.exclude('test_max_float16_cpu') backend_test.exclude('test_min_float16_cpu') backend_test.exclude('test_mod_mixed_sign_float16_cpu') backend_test.exclude('test_dequantizelinear_int4_cpu') backend_test.exclude('test_dequantizelinear_uint4_cpu') backend_test.exclude('test_quantizelinear_int4_cpu') backend_test.exclude('test_quantizelinear_uint4_cpu') # no support for FLOAT8 backend_test.exclude('test_quantizelinear_e4m3fn_cpu') backend_test.exclude('test_quantizelinear_e5m2_cpu') backend_test.exclude('test_quantizelinear_e4m3fn_cpu') backend_test.exclude('test_quantizelinear_e5m2_cpu') backend_test.exclude('test_dequantizelinear_e4m3fn_cpu') backend_test.exclude('test_dequantizelinear_e4m3fn_zero_point_cpu') backend_test.exclude('test_dequantizelinear_e5m2_cpu') # we don't support indexes backend_test.exclude('test_nonzero_*') # no support for int pow backend_test.exclude('test_pow_types_int32_int32_cpu') backend_test.exclude('test_pow_types_int64_int64_cpu') # no boolean ops (2d, 3d, 4d) backend_test.exclude('test_bitshift_*') # no string ops backend_test.exclude('string') backend_test.exclude('test_strnorm_*') backend_test.exclude('test_regex_*') # no rnn backend_test.exclude('test_gru_*') backend_test.exclude('test_rnn_*') backend_test.exclude('test_lstm_*') backend_test.exclude('test_simple_rnn_*') # no control flow # control flow uses AttributeProto.GRAPH backend_test.exclude('test_if_*') backend_test.exclude('test_loop*') backend_test.exclude('test_range_float_type_positive_delta_expanded_cpu') # requires loop backend_test.exclude('test_affine_grid_2d_align_corners_expanded_cpu') backend_test.exclude('test_affine_grid_2d_expanded_cpu') backend_test.exclude('test_affine_grid_3d_align_corners_expanded_cpu') backend_test.exclude('test_affine_grid_3d_expanded_cpu') backend_test.exclude('test_range_int32_type_negative_delta_expanded_cpu') # unsupported (strange) ops backend_test.exclude('test_blackmanwindow_*') backend_test.exclude('test_bernoulli_*') backend_test.exclude('test_det_*') backend_test.exclude('test_col2im_*') backend_test.exclude('test_hammingwindow_*') backend_test.exclude('test_hannwindow_*') backend_test.exclude('test_hardmax_*') backend_test.exclude('test_gridsample_*') backend_test.exclude('test_dft_*') backend_test.exclude('test_einsum_batch_diagonal_cpu*') # TODO: equation = '...ii ->...i' backend_test.exclude('test_einsum_inner_prod_cpu*') # TODO: equation = 'i,i' backend_test.exclude('test_unique_*') backend_test.exclude('test_sequence_*') backend_test.exclude('test_nonmaxsuppression_*') backend_test.exclude('test_reversesequence_*') backend_test.exclude('test_roialign_*') backend_test.exclude('test_tfidfvectorizer_*') backend_test.exclude('test_stft_*') backend_test.exclude('test_melweightmatrix_*') # more strange ops backend_test.exclude('test_basic_deform_conv_*') backend_test.exclude('test_deform_conv_*') backend_test.exclude('test_lppool_*') backend_test.exclude('test_scan_*') backend_test.exclude('test_split_to_sequence_*') backend_test.exclude('test_resize_downsample_scales_cubic_*') # unsure how to implement cubic backend_test.exclude('test_resize_downsample_sizes_cubic_*') # unsure how to implement cubic backend_test.exclude('test_resize_upsample_scales_cubic_*') # unsure how to implement cubic backend_test.exclude('test_resize_upsample_sizes_cubic_*') # unsure how to implement cubic backend_test.exclude('test_ai_onnx_ml_tree_ensemble_*') # https://github.com/onnx/onnx/blob/main/onnx/reference/ops/aionnxml/op_tree_ensemble.py#L121 # rest of the failing tests backend_test.exclude('test_resize_tf_crop_and_resize_cpu') # tf_crop_and_resize not implemented backend_test.exclude('test_resize_tf_crop_and_resize_axes_2_3_cpu') # tf_crop_and_resize not implemented backend_test.exclude('test_resize_tf_crop_and_resize_axes_3_2_cpu') # tf_crop_and_resize not implemented backend_test.exclude('test_resize_tf_crop_and_resize_extrapolation_value_cpu') # tf_crop_and_resize value not implemented backend_test.exclude('test_resize_downsample_scales_linear_antialias_cpu') # antialias not implemented backend_test.exclude('test_resize_downsample_sizes_linear_antialias_cpu') # antialias not implemented backend_test.exclude('test_ai_onnx_ml_label_encoder_tensor_value_only_mapping_cpu') # bad data type string backend_test.exclude('test_ai_onnx_ml_label_encoder_tensor_mapping_cpu') # bad data type string backend_test.exclude('test_scatternd_min_cpu') # min not yet supported backend_test.exclude('test_scatternd_max_cpu') # max not yet supported if Device.DEFAULT in ['GPU', 'METAL']: backend_test.exclude('test_resize_upsample_sizes_nearest_axes_2_3_cpu') backend_test.exclude('test_resize_upsample_sizes_nearest_axes_3_2_cpu') backend_test.exclude('test_resize_upsample_sizes_nearest_cpu') if Device.DEFAULT == "METAL" or (OSX and Device.DEFAULT == "GPU"): # numerical inaccuracy backend_test.exclude('test_mish_cpu') backend_test.exclude('test_mish_expanded_cpu') # disable model tests for now since they are slow if not getenv("MODELTESTS"): for x in backend_test.test_suite: if 'OnnxBackendRealModelTest' in str(type(x)): backend_test.exclude(str(x).split(" ")[0]) else: # model tests all pass! backend_test.include('test_resnet50') backend_test.include('test_inception_v1') backend_test.include('test_inception_v2') backend_test.include('test_densenet121') backend_test.include('test_shufflenet') backend_test.include('test_squeezenet') backend_test.include('test_bvlc_alexnet') backend_test.include('test_zfnet512') backend_test.include('test_vgg19') globals().update(backend_test.enable_report().test_cases) if __name__ == '__main__': unittest.main()