有这想法,感觉是必然的,很多年前,了解过人工智能,当时还没有深度学习,都是经典的机器学习,网络还是很简单的神经网络,当初,就有一个想法,是否可以写一个通用的神经网络框架呢,经过较长时间评估,发现目标不明确,实现难度太大,理论薄弱,就放弃了。
后来深度学习火起来了,也了解这个行业的发展的如火如荼,但基本都是大公司在引领人工智能热潮,觉得泡沫吹得太大,遂等凉了再说。现在2020年了,自认为该凉了,就可以静下心来,好好思考下,这个东西在技术上究竟该怎么做。各大框架趋于稳定,功能开始雷同,变现需求越来越迫切,大家都想在部署在低端设备上。
研究了一大圈,现在各种框架基本都是Python和C++等大型框架,基本不适合低端嵌入式设备,那种无操作系统的设备,更是无从谈起,翻遍整个了网络,也没有找到纯C的,低端嵌入式设备友好的微型推理框架。特别是ONNX标准的流行,让我觉得有必要自己开发一个微型推理框架,不为别的,就只为能在低端嵌入式设备上运行各种开源的预训练模型,且不要对模型动刀,况且训练模型,吃力不讨好,还不如用现成的,本来,好用的深度学习模型,就那么些,大家基本都差不多。
说了这么多,再说点技术架构:
首先,选择ONNX模型,作为推理模型,原因也比较简单,毕竟是各种框架互换模型,有较强的通用性,且容易转换到,不选这个就是脑袋被驴踢了。
其次,采用纯C语言,C99标准,原因也比较简单,只有C才是拥有最强可移植性的。
再次,支持硬件加速接口,特别是运行在低端嵌入式芯片上。以后的AI芯片,都会集成NPU,而这高性能,就只能靠NPU了。
最后,程序文件随便复制到各种工程,包括各种MCU,不带货,绝对最小依赖。
以上,就是计划自己手写AI推理引擎的背景,项目名称叫libonnx,github地址:https://github.com/xboot/libonnx
现在项目框架已搭完,不到一万行纯C代码,不包含各种算子。
下一阶段的主要工作,就是手写各种算子,里面集成onnx标准的完整测试用例,节点部分总共755个,现在通过了4个,也就是说,才完成了4 / 755。
嗯,不知人工智能类的,该放到哪个版块,就先放这儿吧,如果不对,麻烦晕哥挪挪位置。
写这个贴,还请大家,都给给建议,毕竟一个人思路狭隘,容易走进死胡同。当然,如果觉得这个项目还不错,也别忘记给颗星星,你们的支持,是我开发的动力。
开源不易!开源不易!开源不易!
最近编辑记录 xboot (2020-10-16 15:09:25)
离线
C用得熟,适应性强些,开发环境依赖少,特别是MCU,用C++来个模板试试,一下就爆了,更主要的一点,C语言我比较熟,控制力强,可以写出优化层次极高的代码。
离线
额,本以为仅会开源xboot这一个项目的,考虑到xboot还需要一个深度学习推理框架,没找到合适的,就只能自己写了,也考虑到libonnx这个库,不仅仅适合xboot,也可能适合其他场景,所以,还是决定独立出来成一个单独的项目,方便大家直接使用。
离线
完全支持用C来写。当然,这里面包含个人偏好。
其一,确如LZ所言,可移植性强,与硬件交互能力强,未来可针对特定硬件进行底层优化
其二,C语言入门门槛低,平台搭建简单,理工大学生或程序员几乎都接触过C语言,意味着受众广,或者说潜在市场大平台有规划,LZ已经做的很好了。要说建议的话,那就是做demo case,找个场景先落地,或者让受众可以实践一下。毕竟开发过程可能比较长,或者说是持续的过程,广大群众急切需要有个hello world体验下。另外一个就是,适时更新文档,一是记录自己的思路,二是让大伙也跟得上开发者的思路,用得起来
建议很在理,demo case优先,先用得起来才可能发现问题,计划,等基础算子写完,就先开发一个相对完整的demo,用于演示。文档什么的,这个看来还是特别重要,一定不能拉下。
还有哪些模型实用性强,优先级高呢,可以先考虑实现这些模型里的算子,实用优先,慢慢补全。
离线
中文注释,扬国威?
离线
周末加班码字,补充了一些简单的算子,柿子还是先捡软的捏。贴一个标准测试集的测试结果,还空缺一大片。
[test_abs](test_data_set_0) [OKAY]
[test_acos](test_data_set_0) [OKAY]
[test_acos_example](test_data_set_0) [OKAY]
[test_acosh](test_data_set_0) [OKAY]
[test_acosh_example](test_data_set_0) [OKAY]
[test_adagrad](test_data_set_0) [FAIL]
[test_adagrad_multiple](test_data_set_0) [FAIL]
[test_adam](test_data_set_0) [FAIL]
[test_adam_multiple](test_data_set_0) [FAIL]
[test_add](test_data_set_0) [FAIL]
[test_add_bcast](test_data_set_0) [FAIL]
[test_and2d](test_data_set_0) [FAIL]
[test_and3d](test_data_set_0) [FAIL]
[test_and4d](test_data_set_0) [FAIL]
[test_and_bcast3v1d](test_data_set_0) [FAIL]
[test_and_bcast3v2d](test_data_set_0) [FAIL]
[test_and_bcast4v2d](test_data_set_0) [FAIL]
[test_and_bcast4v3d](test_data_set_0) [FAIL]
[test_and_bcast4v4d](test_data_set_0) [FAIL]
[test_argmax_default_axis_example](test_data_set_0) [FAIL]
[test_argmax_default_axis_example_select_last_index](test_data_set_0) [FAIL]
[test_argmax_default_axis_random](test_data_set_0) [FAIL]
[test_argmax_default_axis_random_select_last_index](test_data_set_0) [FAIL]
[test_argmax_keepdims_example](test_data_set_0) [FAIL]
[test_argmax_keepdims_example_select_last_index](test_data_set_0) [FAIL]
[test_argmax_keepdims_random](test_data_set_0) [FAIL]
[test_argmax_keepdims_random_select_last_index](test_data_set_0) [FAIL]
[test_argmax_negative_axis_keepdims_example](test_data_set_0) [FAIL]
[test_argmax_negative_axis_keepdims_example_select_last_index](test_data_set_0) [FAIL]
[test_argmax_negative_axis_keepdims_random](test_data_set_0) [FAIL]
[test_argmax_negative_axis_keepdims_random_select_last_index](test_data_set_0) [FAIL]
[test_argmax_no_keepdims_example](test_data_set_0) [FAIL]
[test_argmax_no_keepdims_example_select_last_index](test_data_set_0) [FAIL]
[test_argmax_no_keepdims_random](test_data_set_0) [FAIL]
[test_argmax_no_keepdims_random_select_last_index](test_data_set_0) [FAIL]
[test_argmin_default_axis_example](test_data_set_0) [OKAY]
[test_argmin_default_axis_example_select_last_index](test_data_set_0) [OKAY]
[test_argmin_default_axis_random](test_data_set_0) [FAIL]
[test_argmin_default_axis_random_select_last_index](test_data_set_0) [FAIL]
[test_argmin_keepdims_example](test_data_set_0) [FAIL]
[test_argmin_keepdims_example_select_last_index](test_data_set_0) [FAIL]
[test_argmin_keepdims_random](test_data_set_0) [FAIL]
[test_argmin_keepdims_random_select_last_index](test_data_set_0) [FAIL]
[test_argmin_negative_axis_keepdims_example](test_data_set_0) [FAIL]
[test_argmin_negative_axis_keepdims_example_select_last_index](test_data_set_0) [FAIL]
[test_argmin_negative_axis_keepdims_random](test_data_set_0) [FAIL]
[test_argmin_negative_axis_keepdims_random_select_last_index](test_data_set_0) [FAIL]
[test_argmin_no_keepdims_example](test_data_set_0) [FAIL]
[test_argmin_no_keepdims_example_select_last_index](test_data_set_0) [FAIL]
[test_argmin_no_keepdims_random](test_data_set_0) [FAIL]
[test_argmin_no_keepdims_random_select_last_index](test_data_set_0) [FAIL]
[test_asin](test_data_set_0) [OKAY]
[test_asin_example](test_data_set_0) [OKAY]
[test_asinh](test_data_set_0) [OKAY]
[test_asinh_example](test_data_set_0) [OKAY]
[test_atan](test_data_set_0) [OKAY]
[test_atan_example](test_data_set_0) [OKAY]
[test_atanh](test_data_set_0) [OKAY]
[test_atanh_example](test_data_set_0) [OKAY]
[test_averagepool_1d_default](test_data_set_0) [FAIL]
[test_averagepool_2d_ceil](test_data_set_0) [FAIL]
[test_averagepool_2d_default](test_data_set_0) [FAIL]
[test_averagepool_2d_pads](test_data_set_0) [FAIL]
[test_averagepool_2d_pads_count_include_pad](test_data_set_0) [FAIL]
[test_averagepool_2d_precomputed_pads](test_data_set_0) [FAIL]
[test_averagepool_2d_precomputed_pads_count_include_pad](test_data_set_0) [FAIL]
[test_averagepool_2d_precomputed_same_upper](test_data_set_0) [FAIL]
[test_averagepool_2d_precomputed_strides](test_data_set_0) [FAIL]
[test_averagepool_2d_same_lower](test_data_set_0) [FAIL]
[test_averagepool_2d_same_upper](test_data_set_0) [FAIL]
[test_averagepool_2d_strides](test_data_set_0) [FAIL]
[test_averagepool_3d_default](test_data_set_0) [FAIL]
[test_basic_conv_with_padding](test_data_set_0) [FAIL]
[test_basic_conv_without_padding](test_data_set_0) [FAIL]
[test_basic_convinteger](test_data_set_0) [FAIL]
[test_batchnorm_epsilon](test_data_set_0) [FAIL]
[test_batchnorm_example](test_data_set_0) [FAIL]
[test_bitshift_left_uint16](test_data_set_0) [FAIL]
[test_bitshift_left_uint32](test_data_set_0) [FAIL]
[test_bitshift_left_uint64](test_data_set_0) [FAIL]
[test_bitshift_left_uint8](test_data_set_0) [FAIL]
[test_bitshift_right_uint16](test_data_set_0) [FAIL]
[test_bitshift_right_uint32](test_data_set_0) [FAIL]
[test_bitshift_right_uint64](test_data_set_0) [FAIL]
[test_bitshift_right_uint8](test_data_set_0) [FAIL]
[test_cast_BFLOAT16_to_FLOAT](test_data_set_0) [FAIL]
[test_cast_DOUBLE_to_FLOAT](test_data_set_0) [FAIL]
[test_cast_DOUBLE_to_FLOAT16](test_data_set_0) [FAIL]
[test_cast_FLOAT16_to_DOUBLE](test_data_set_0) [FAIL]
[test_cast_FLOAT16_to_FLOAT](test_data_set_0) [FAIL]
[test_cast_FLOAT_to_BFLOAT16](test_data_set_0) [FAIL]
[test_cast_FLOAT_to_DOUBLE](test_data_set_0) [FAIL]
[test_cast_FLOAT_to_FLOAT16](test_data_set_0) [FAIL]
[test_cast_FLOAT_to_STRING](test_data_set_0) [OKAY]
[test_cast_STRING_to_FLOAT](test_data_set_0) [FAIL]
[test_ceil](test_data_set_0) [FAIL]
[test_ceil_example](test_data_set_0) [FAIL]
[test_celu](test_data_set_0) [FAIL]
[test_celu_expanded](test_data_set_0) [FAIL]
[test_clip](test_data_set_0) [FAIL]
[test_clip_default_int8_min](test_data_set_0) [FAIL]
[test_clip_default_min](test_data_set_0) [FAIL]
[test_clip_example](test_data_set_0) [FAIL]
[test_clip_inbounds](test_data_set_0) [FAIL]
[test_clip_outbounds](test_data_set_0) [FAIL]
[test_clip_splitbounds](test_data_set_0) [FAIL]
[test_compress_0](test_data_set_0) [FAIL]
[test_compress_1](test_data_set_0) [FAIL]
[test_compress_default_axis](test_data_set_0) [FAIL]
[test_compress_negative_axis](test_data_set_0) [FAIL]
[test_concat_1d_axis_0](test_data_set_0) [FAIL]
[test_concat_1d_axis_negative_1](test_data_set_0) [FAIL]
[test_concat_2d_axis_0](test_data_set_0) [FAIL]
[test_concat_2d_axis_1](test_data_set_0) [FAIL]
[test_concat_2d_axis_negative_1](test_data_set_0) [FAIL]
[test_concat_2d_axis_negative_2](test_data_set_0) [FAIL]
[test_concat_3d_axis_0](test_data_set_0) [FAIL]
[test_concat_3d_axis_1](test_data_set_0) [FAIL]
[test_concat_3d_axis_2](test_data_set_0) [FAIL]
[test_concat_3d_axis_negative_1](test_data_set_0) [FAIL]
[test_concat_3d_axis_negative_2](test_data_set_0) [FAIL]
[test_concat_3d_axis_negative_3](test_data_set_0) [FAIL]
[test_constant](test_data_set_0) [FAIL]
[test_constant_pad](test_data_set_0) [FAIL]
[test_constantofshape_float_ones](test_data_set_0) [FAIL]
[test_constantofshape_int_shape_zero](test_data_set_0) [OKAY]
[test_constantofshape_int_zeros](test_data_set_0) [OKAY]
[test_conv_with_strides_and_asymmetric_padding](test_data_set_0) [FAIL]
[test_conv_with_strides_no_padding](test_data_set_0) [FAIL]
[test_conv_with_strides_padding](test_data_set_0) [FAIL]
[test_convinteger_with_padding](test_data_set_0) [FAIL]
[test_convtranspose](test_data_set_0) [FAIL]
[test_convtranspose_1d](test_data_set_0) [FAIL]
[test_convtranspose_3d](test_data_set_0) [FAIL]
[test_convtranspose_dilations](test_data_set_0) [FAIL]
[test_convtranspose_kernel_shape](test_data_set_0) [FAIL]
[test_convtranspose_output_shape](test_data_set_0) [FAIL]
[test_convtranspose_pad](test_data_set_0) [FAIL]
[test_convtranspose_pads](test_data_set_0) [FAIL]
[test_convtranspose_with_kernel](test_data_set_0) [FAIL]
[test_cos](test_data_set_0) [OKAY]
[test_cos_example](test_data_set_0) [OKAY]
[test_cosh](test_data_set_0) [OKAY]
[test_cosh_example](test_data_set_0) [OKAY]
[test_cumsum_1d](test_data_set_0) [FAIL]
[test_cumsum_1d_exclusive](test_data_set_0) [FAIL]
[test_cumsum_1d_reverse](test_data_set_0) [FAIL]
[test_cumsum_1d_reverse_exclusive](test_data_set_0) [FAIL]
[test_cumsum_2d_axis_0](test_data_set_0) [FAIL]
[test_cumsum_2d_axis_1](test_data_set_0) [FAIL]
[test_cumsum_2d_negative_axis](test_data_set_0) [FAIL]
[test_depthtospace_crd_mode](test_data_set_0) [FAIL]
[test_depthtospace_crd_mode_example](test_data_set_0) [FAIL]
[test_depthtospace_dcr_mode](test_data_set_0) [FAIL]
[test_depthtospace_example](test_data_set_0) [FAIL]
[test_dequantizelinear](test_data_set_0) [FAIL]
[test_dequantizelinear_axis](test_data_set_0) [FAIL]
[test_det_2d](test_data_set_0) [OKAY]
[test_det_nd](test_data_set_0) [FAIL]
[test_div](test_data_set_0) [FAIL]
[test_div_bcast](test_data_set_0) [FAIL]
[test_div_example](test_data_set_0) [FAIL]
[test_dropout_default](test_data_set_0) [FAIL]
[test_dropout_default_mask](test_data_set_0) [FAIL]
[test_dropout_default_mask_ratio](test_data_set_0) [FAIL]
[test_dropout_default_old](test_data_set_0) [FAIL]
[test_dropout_default_ratio](test_data_set_0) [FAIL]
[test_dropout_random_old](test_data_set_0) [FAIL]
[test_dynamicquantizelinear](test_data_set_0) [FAIL]
[test_dynamicquantizelinear_expanded](test_data_set_0) [FAIL]
[test_dynamicquantizelinear_max_adjusted](test_data_set_0) [FAIL]
[test_dynamicquantizelinear_max_adjusted_expanded](test_data_set_0) [FAIL]
[test_dynamicquantizelinear_min_adjusted](test_data_set_0) [FAIL]
[test_dynamicquantizelinear_min_adjusted_expanded](test_data_set_0) [FAIL]
[test_edge_pad](test_data_set_0) [FAIL]
[test_einsum_batch_diagonal](test_data_set_0) [FAIL]
[test_einsum_batch_matmul](test_data_set_0) [FAIL]
[test_einsum_inner_prod](test_data_set_0) [OKAY]
[test_einsum_sum](test_data_set_0) [FAIL]
[test_einsum_transpose](test_data_set_0) [FAIL]
[test_elu](test_data_set_0) [OKAY]
[test_elu_default](test_data_set_0) [OKAY]
[test_elu_example](test_data_set_0) [OKAY]
[test_equal](test_data_set_0) [FAIL]
[test_equal_bcast](test_data_set_0) [FAIL]
[test_erf](test_data_set_0) [FAIL]
[test_exp](test_data_set_0) [OKAY]
[test_exp_example](test_data_set_0) [OKAY]
[test_expand_dim_changed](test_data_set_0) [FAIL]
[test_expand_dim_unchanged](test_data_set_0) [FAIL]
[test_eyelike_populate_off_main_diagonal](test_data_set_0) [FAIL]
[test_eyelike_with_dtype](test_data_set_0) [FAIL]
[test_eyelike_without_dtype](test_data_set_0) [FAIL]
[test_flatten_axis0](test_data_set_0) [FAIL]
[test_flatten_axis1](test_data_set_0) [FAIL]
[test_flatten_axis2](test_data_set_0) [FAIL]
[test_flatten_axis3](test_data_set_0) [FAIL]
[test_flatten_default_axis](test_data_set_0) [FAIL]
[test_flatten_negative_axis1](test_data_set_0) [FAIL]
[test_flatten_negative_axis2](test_data_set_0) [FAIL]
[test_flatten_negative_axis3](test_data_set_0) [FAIL]
[test_flatten_negative_axis4](test_data_set_0) [FAIL]
[test_floor](test_data_set_0) [FAIL]
[test_floor_example](test_data_set_0) [FAIL]
[test_gather_0](test_data_set_0) [FAIL]
[test_gather_1](test_data_set_0) [FAIL]
[test_gather_2d_indices](test_data_set_0) [FAIL]
[test_gather_elements_0](test_data_set_0) [FAIL]
[test_gather_elements_1](test_data_set_0) [FAIL]
[test_gather_elements_negative_indices](test_data_set_0) [FAIL]
[test_gather_negative_indices](test_data_set_0) [FAIL]
[test_gathernd_example_float32](test_data_set_0) [FAIL]
[test_gathernd_example_int32](test_data_set_0) [FAIL]
[test_gathernd_example_int32_batch_dim1](test_data_set_0) [FAIL]
[test_gemm_all_attributes](test_data_set_0) [FAIL]
[test_gemm_alpha](test_data_set_0) [FAIL]
[test_gemm_beta](test_data_set_0) [FAIL]
[test_gemm_default_matrix_bias](test_data_set_0) [FAIL]
[test_gemm_default_no_bias](test_data_set_0) [FAIL]
[test_gemm_default_scalar_bias](test_data_set_0) [FAIL]
[test_gemm_default_single_elem_vector_bias](test_data_set_0) [FAIL]
[test_gemm_default_vector_bias](test_data_set_0) [FAIL]
[test_gemm_default_zero_bias](test_data_set_0) [FAIL]
[test_gemm_transposeA](test_data_set_0) [FAIL]
[test_gemm_transposeB](test_data_set_0) [FAIL]
[test_globalaveragepool](test_data_set_0) [FAIL]
[test_globalaveragepool_precomputed](test_data_set_0) [FAIL]
[test_globalmaxpool](test_data_set_0) [FAIL]
[test_globalmaxpool_precomputed](test_data_set_0) [FAIL]
[test_greater](test_data_set_0) [FAIL]
[test_greater_bcast](test_data_set_0) [FAIL]
[test_greater_equal](test_data_set_0) [FAIL]
[test_greater_equal_bcast](test_data_set_0) [FAIL]
[test_greater_equal_bcast_expanded](test_data_set_0) [FAIL]
[test_greater_equal_expanded](test_data_set_0) [FAIL]
[test_gru_defaults](test_data_set_0) [FAIL]
[test_gru_seq_length](test_data_set_0) [FAIL]
[test_gru_with_initial_bias](test_data_set_0) [FAIL]
[test_hardmax_axis_0](test_data_set_0) [FAIL]
[test_hardmax_axis_1](test_data_set_0) [FAIL]
[test_hardmax_axis_2](test_data_set_0) [FAIL]
[test_hardmax_default_axis](test_data_set_0) [FAIL]
[test_hardmax_example](test_data_set_0) [FAIL]
[test_hardmax_negative_axis](test_data_set_0) [FAIL]
[test_hardmax_one_hot](test_data_set_0) [FAIL]
[test_hardsigmoid](test_data_set_0) [OKAY]
[test_hardsigmoid_default](test_data_set_0) [OKAY]
[test_hardsigmoid_example](test_data_set_0) [OKAY]
[test_identity](test_data_set_0) [FAIL]
[test_if](test_data_set_0) [FAIL]
[test_if_seq](test_data_set_0) [FAIL]
[test_instancenorm_epsilon](test_data_set_0) [FAIL]
[test_instancenorm_example](test_data_set_0) [FAIL]
[test_isinf](test_data_set_0) [FAIL]
[test_isinf_negative](test_data_set_0) [FAIL]
[test_isinf_positive](test_data_set_0) [FAIL]
[test_isnan](test_data_set_0) [FAIL]
[test_leakyrelu](test_data_set_0) [OKAY]
[test_leakyrelu_default](test_data_set_0) [OKAY]
[test_leakyrelu_example](test_data_set_0) [OKAY]
[test_less](test_data_set_0) [FAIL]
[test_less_bcast](test_data_set_0) [FAIL]
[test_less_equal](test_data_set_0) [FAIL]
[test_less_equal_bcast](test_data_set_0) [FAIL]
[test_less_equal_bcast_expanded](test_data_set_0) [FAIL]
[test_less_equal_expanded](test_data_set_0) [FAIL]
[test_log](test_data_set_0) [FAIL]
[test_log_example](test_data_set_0) [FAIL]
[test_logsoftmax_axis_0](test_data_set_0) [FAIL]
[test_logsoftmax_axis_0_expanded](test_data_set_0) [FAIL]
[test_logsoftmax_axis_1](test_data_set_0) [FAIL]
[test_logsoftmax_axis_1_expanded](test_data_set_0) [FAIL]
[test_logsoftmax_axis_2](test_data_set_0) [FAIL]
[test_logsoftmax_axis_2_expanded](test_data_set_0) [FAIL]
[test_logsoftmax_default_axis](test_data_set_0) [FAIL]
[test_logsoftmax_default_axis_expanded](test_data_set_0) [FAIL]
[test_logsoftmax_example_1](test_data_set_0) [FAIL]
[test_logsoftmax_example_1_expanded](test_data_set_0) [FAIL]
[test_logsoftmax_large_number](test_data_set_0) [FAIL]
[test_logsoftmax_large_number_expanded](test_data_set_0) [FAIL]
[test_logsoftmax_negative_axis](test_data_set_0) [FAIL]
[test_logsoftmax_negative_axis_expanded](test_data_set_0) [FAIL]
[test_loop11](test_data_set_0) [FAIL]
[test_lrn](test_data_set_0) [FAIL]
[test_lrn_default](test_data_set_0) [FAIL]
[test_lstm_defaults](test_data_set_0) [FAIL]
[test_lstm_with_initial_bias](test_data_set_0) [FAIL]
[test_lstm_with_peepholes](test_data_set_0) [FAIL]
[test_matmul_2d](test_data_set_0) [FAIL]
[test_matmul_3d](test_data_set_0) [FAIL]
[test_matmul_4d](test_data_set_0) [FAIL]
[test_matmulinteger](test_data_set_0) [FAIL]
[test_max_example](test_data_set_0) [FAIL]
[test_max_float16](test_data_set_0) [FAIL]
[test_max_float32](test_data_set_0) [FAIL]
[test_max_float64](test_data_set_0) [FAIL]
[test_max_int16](test_data_set_0) [FAIL]
[test_max_int32](test_data_set_0) [FAIL]
[test_max_int64](test_data_set_0) [FAIL]
[test_max_int8](test_data_set_0) [FAIL]
[test_max_one_input](test_data_set_0) [FAIL]
[test_max_two_inputs](test_data_set_0) [FAIL]
[test_max_uint16](test_data_set_0) [FAIL]
[test_max_uint32](test_data_set_0) [FAIL]
[test_max_uint64](test_data_set_0) [FAIL]
[test_max_uint8](test_data_set_0) [FAIL]
[test_maxpool_1d_default](test_data_set_0) [FAIL]
[test_maxpool_2d_ceil](test_data_set_0) [FAIL]
[test_maxpool_2d_default](test_data_set_0) [FAIL]
[test_maxpool_2d_dilations](test_data_set_0) [FAIL]
[test_maxpool_2d_pads](test_data_set_0) [FAIL]
[test_maxpool_2d_precomputed_pads](test_data_set_0) [FAIL]
[test_maxpool_2d_precomputed_same_upper](test_data_set_0) [FAIL]
[test_maxpool_2d_precomputed_strides](test_data_set_0) [FAIL]
[test_maxpool_2d_same_lower](test_data_set_0) [FAIL]
[test_maxpool_2d_same_upper](test_data_set_0) [FAIL]
[test_maxpool_2d_strides](test_data_set_0) [FAIL]
[test_maxpool_2d_uint8](test_data_set_0) [FAIL]
[test_maxpool_3d_default](test_data_set_0) [FAIL]
[test_maxpool_with_argmax_2d_precomputed_pads](test_data_set_0) [FAIL]
[test_maxpool_with_argmax_2d_precomputed_strides](test_data_set_0) [FAIL]
[test_maxunpool_export_with_output_shape](test_data_set_0) [FAIL]
[test_maxunpool_export_without_output_shape](test_data_set_0) [FAIL]
[test_mean_example](test_data_set_0) [FAIL]
[test_mean_one_input](test_data_set_0) [FAIL]
[test_mean_two_inputs](test_data_set_0) [FAIL]
[test_min_example](test_data_set_0) [FAIL]
[test_min_float16](test_data_set_0) [FAIL]
[test_min_float32](test_data_set_0) [FAIL]
[test_min_float64](test_data_set_0) [FAIL]
[test_min_int16](test_data_set_0) [FAIL]
[test_min_int32](test_data_set_0) [FAIL]
[test_min_int64](test_data_set_0) [FAIL]
[test_min_int8](test_data_set_0) [FAIL]
[test_min_one_input](test_data_set_0) [FAIL]
[test_min_two_inputs](test_data_set_0) [FAIL]
[test_min_uint16](test_data_set_0) [FAIL]
[test_min_uint32](test_data_set_0) [FAIL]
[test_min_uint64](test_data_set_0) [FAIL]
[test_min_uint8](test_data_set_0) [FAIL]
[test_mod_broadcast](test_data_set_0) [FAIL]
[test_mod_int64_fmod](test_data_set_0) [FAIL]
[test_mod_mixed_sign_float16](test_data_set_0) [FAIL]
[test_mod_mixed_sign_float32](test_data_set_0) [FAIL]
[test_mod_mixed_sign_float64](test_data_set_0) [FAIL]
[test_mod_mixed_sign_int16](test_data_set_0) [FAIL]
[test_mod_mixed_sign_int32](test_data_set_0) [FAIL]
[test_mod_mixed_sign_int64](test_data_set_0) [FAIL]
[test_mod_mixed_sign_int8](test_data_set_0) [FAIL]
[test_mod_uint16](test_data_set_0) [FAIL]
[test_mod_uint32](test_data_set_0) [FAIL]
[test_mod_uint64](test_data_set_0) [FAIL]
[test_mod_uint8](test_data_set_0) [FAIL]
[test_momentum](test_data_set_0) [FAIL]
[test_momentum_multiple](test_data_set_0) [FAIL]
[test_mul](test_data_set_0) [FAIL]
[test_mul_bcast](test_data_set_0) [FAIL]
[test_mul_example](test_data_set_0) [FAIL]
[test_mvn](test_data_set_0) [FAIL]
[test_mvn_expanded](test_data_set_0) [FAIL]
[test_neg](test_data_set_0) [FAIL]
[test_neg_example](test_data_set_0) [FAIL]
[test_nesterov_momentum](test_data_set_0) [FAIL]
[test_nllloss_NC](test_data_set_0) [FAIL]
[test_nllloss_NC_expanded](test_data_set_0) [FAIL]
[test_nllloss_NCd1](test_data_set_0) [OKAY]
[test_nllloss_NCd1_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1_ii](test_data_set_0) [OKAY]
[test_nllloss_NCd1_ii_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1_mean_weight_negative_ii](test_data_set_0) [OKAY]
[test_nllloss_NCd1_mean_weight_negative_ii_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1_weight](test_data_set_0) [OKAY]
[test_nllloss_NCd1_weight_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1_weight_ii](test_data_set_0) [OKAY]
[test_nllloss_NCd1_weight_ii_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2_expanded](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2_no_weight_reduction_mean_ii](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_no_weight_reduction_mean_ii_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_reduction_mean](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_reduction_mean_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_reduction_sum](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_reduction_sum_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_with_weight](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2_with_weight_expanded](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2_with_weight_reduction_mean](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_with_weight_reduction_mean_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_with_weight_reduction_sum](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_with_weight_reduction_sum_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_with_weight_reduction_sum_ii](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2_with_weight_reduction_sum_ii_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2d3_none_no_weight_negative_ii](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2d3_none_no_weight_negative_ii_expanded](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2d3_sum_weight_high_ii](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2d3_sum_weight_high_ii_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2d3d4d5_mean_weight](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2d3d4d5_mean_weight_expanded](test_data_set_0) [OKAY]
[test_nllloss_NCd1d2d3d4d5_none_no_weight](test_data_set_0) [FAIL]
[test_nllloss_NCd1d2d3d4d5_none_no_weight_expanded](test_data_set_0) [FAIL]
[test_nonmaxsuppression_center_point_box_format](test_data_set_0) [FAIL]
[test_nonmaxsuppression_flipped_coordinates](test_data_set_0) [FAIL]
[test_nonmaxsuppression_identical_boxes](test_data_set_0) [OKAY]
[test_nonmaxsuppression_limit_output_size](test_data_set_0) [FAIL]
[test_nonmaxsuppression_single_box](test_data_set_0) [OKAY]
[test_nonmaxsuppression_suppress_by_IOU](test_data_set_0) [FAIL]
[test_nonmaxsuppression_suppress_by_IOU_and_scores](test_data_set_0) [FAIL]
[test_nonmaxsuppression_two_batches](test_data_set_0) [FAIL]
[test_nonmaxsuppression_two_classes](test_data_set_0) [FAIL]
[test_nonzero_example](test_data_set_0) [FAIL]
[test_not_2d](test_data_set_0) [FAIL]
[test_not_3d](test_data_set_0) [FAIL]
[test_not_4d](test_data_set_0) [FAIL]
[test_onehot_negative_indices](test_data_set_0) [FAIL]
[test_onehot_with_axis](test_data_set_0) [FAIL]
[test_onehot_with_negative_axis](test_data_set_0) [FAIL]
[test_onehot_without_axis](test_data_set_0) [FAIL]
[test_or2d](test_data_set_0) [FAIL]
[test_or3d](test_data_set_0) [FAIL]
[test_or4d](test_data_set_0) [FAIL]
[test_or_bcast3v1d](test_data_set_0) [FAIL]
[test_or_bcast3v2d](test_data_set_0) [FAIL]
[test_or_bcast4v2d](test_data_set_0) [FAIL]
[test_or_bcast4v3d](test_data_set_0) [FAIL]
[test_or_bcast4v4d](test_data_set_0) [FAIL]
[test_pow](test_data_set_0) [FAIL]
[test_pow_bcast_array](test_data_set_0) [FAIL]
[test_pow_bcast_scalar](test_data_set_0) [FAIL]
[test_pow_example](test_data_set_0) [FAIL]
[test_pow_types_float](test_data_set_0) [FAIL]
[test_pow_types_float32_int32](test_data_set_0) [FAIL]
[test_pow_types_float32_int64](test_data_set_0) [FAIL]
[test_pow_types_float32_uint32](test_data_set_0) [FAIL]
[test_pow_types_float32_uint64](test_data_set_0) [FAIL]
[test_pow_types_int](test_data_set_0) [FAIL]
[test_pow_types_int32_float32](test_data_set_0) [FAIL]
[test_pow_types_int32_int32](test_data_set_0) [FAIL]
[test_pow_types_int64_float32](test_data_set_0) [FAIL]
[test_pow_types_int64_int64](test_data_set_0) [FAIL]
[test_prelu_broadcast](test_data_set_0) [FAIL]
[test_prelu_example](test_data_set_0) [FAIL]
[test_qlinearconv](test_data_set_0) [FAIL]
[test_qlinearmatmul_2D](test_data_set_0) [FAIL]
[test_qlinearmatmul_3D](test_data_set_0) [FAIL]
[test_quantizelinear](test_data_set_0) [FAIL]
[test_quantizelinear_axis](test_data_set_0) [FAIL]
[test_range_float_type_positive_delta](test_data_set_0) [FAIL]
[test_range_float_type_positive_delta_expanded](test_data_set_0) [FAIL]
[test_range_int32_type_negative_delta](test_data_set_0) [FAIL]
[test_range_int32_type_negative_delta_expanded](test_data_set_0) [FAIL]
[test_reciprocal](test_data_set_0) [FAIL]
[test_reciprocal_example](test_data_set_0) [FAIL]
[test_reduce_l1_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_l1_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_l1_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_l1_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_l1_keep_dims_example](test_data_set_0) [FAIL]
[test_reduce_l1_keep_dims_random](test_data_set_0) [FAIL]
[test_reduce_l1_negative_axes_keep_dims_example](test_data_set_0) [FAIL]
[test_reduce_l1_negative_axes_keep_dims_random](test_data_set_0) [FAIL]
[test_reduce_l2_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_l2_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_l2_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_l2_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_l2_keep_dims_example](test_data_set_0) [FAIL]
[test_reduce_l2_keep_dims_random](test_data_set_0) [FAIL]
[test_reduce_l2_negative_axes_keep_dims_example](test_data_set_0) [FAIL]
[test_reduce_l2_negative_axes_keep_dims_random](test_data_set_0) [FAIL]
[test_reduce_log_sum](test_data_set_0) [FAIL]
[test_reduce_log_sum_asc_axes](test_data_set_0) [FAIL]
[test_reduce_log_sum_default](test_data_set_0) [FAIL]
[test_reduce_log_sum_desc_axes](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_log_sum_exp_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_log_sum_negative_axes](test_data_set_0) [FAIL]
[test_reduce_max_default_axes_keepdim_example](test_data_set_0) [FAIL]
[test_reduce_max_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_max_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_max_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_max_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_max_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_max_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_max_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_mean_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_mean_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_mean_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_mean_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_mean_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_mean_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_mean_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_mean_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_min_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_min_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_min_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_min_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_min_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_min_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_min_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_min_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_prod_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_prod_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_prod_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_prod_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_prod_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_prod_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_prod_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_prod_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_empty_axes_input_noop_example](test_data_set_0) [FAIL]
[test_reduce_sum_empty_axes_input_noop_random](test_data_set_0) [FAIL]
[test_reduce_sum_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_square_default_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_square_default_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_square_do_not_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_square_do_not_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_square_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_square_keepdims_random](test_data_set_0) [FAIL]
[test_reduce_sum_square_negative_axes_keepdims_example](test_data_set_0) [FAIL]
[test_reduce_sum_square_negative_axes_keepdims_random](test_data_set_0) [FAIL]
[test_reflect_pad](test_data_set_0) [FAIL]
[test_relu](test_data_set_0) [OKAY]
[test_reshape_extended_dims](test_data_set_0) [FAIL]
[test_reshape_negative_dim](test_data_set_0) [FAIL]
[test_reshape_negative_extended_dims](test_data_set_0) [FAIL]
[test_reshape_one_dim](test_data_set_0) [FAIL]
[test_reshape_reduced_dims](test_data_set_0) [FAIL]
[test_reshape_reordered_all_dims](test_data_set_0) [FAIL]
[test_reshape_reordered_last_dims](test_data_set_0) [FAIL]
[test_reshape_zero_and_negative_dim](test_data_set_0) [FAIL]
[test_reshape_zero_dim](test_data_set_0) [FAIL]
[test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn](test_data_set_0) [FAIL]
[test_reversesequence_batch](test_data_set_0) [FAIL]
[test_reversesequence_time](test_data_set_0) [FAIL]
[test_rnn_seq_length](test_data_set_0) [FAIL]
[test_roialign](test_data_set_0) [FAIL]
[test_round](test_data_set_0) [FAIL]
[test_scan9_sum](test_data_set_0) [FAIL]
[test_scatter_elements_with_axis](test_data_set_0) [FAIL]
[test_scatter_elements_with_negative_indices](test_data_set_0) [FAIL]
[test_scatter_elements_without_axis](test_data_set_0) [FAIL]
[test_scatter_with_axis](test_data_set_0) [FAIL]
[test_scatter_without_axis](test_data_set_0) [FAIL]
[test_scatternd](test_data_set_0) [FAIL]
[test_sce_NCd1_mean_weight_negative_ii](test_data_set_0) [OKAY]
[test_sce_NCd1_mean_weight_negative_ii_expanded](test_data_set_0) [OKAY]
[test_sce_NCd1_mean_weight_negative_ii_log_prob](test_data_set_0) [FAIL]
[test_sce_NCd1_mean_weight_negative_ii_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3_none_no_weight_negative_ii](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3_none_no_weight_negative_ii_expanded](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3_none_no_weight_negative_ii_log_prob](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3_none_no_weight_negative_ii_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3_sum_weight_high_ii](test_data_set_0) [OKAY]
[test_sce_NCd1d2d3_sum_weight_high_ii_expanded](test_data_set_0) [OKAY]
[test_sce_NCd1d2d3_sum_weight_high_ii_log_prob](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3_sum_weight_high_ii_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3d4d5_mean_weight](test_data_set_0) [OKAY]
[test_sce_NCd1d2d3d4d5_mean_weight_expanded](test_data_set_0) [OKAY]
[test_sce_NCd1d2d3d4d5_mean_weight_log_prob](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3d4d5_mean_weight_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3d4d5_none_no_weight](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3d4d5_none_no_weight_expanded](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3d4d5_none_no_weight_log_prob](test_data_set_0) [FAIL]
[test_sce_NCd1d2d3d4d5_none_no_weight_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean](test_data_set_0) [OKAY]
[test_sce_mean_3d](test_data_set_0) [OKAY]
[test_sce_mean_3d_expanded](test_data_set_0) [OKAY]
[test_sce_mean_3d_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_3d_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_expanded](test_data_set_0) [OKAY]
[test_sce_mean_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_no_weight_ii](test_data_set_0) [OKAY]
[test_sce_mean_no_weight_ii_3d](test_data_set_0) [OKAY]
[test_sce_mean_no_weight_ii_3d_expanded](test_data_set_0) [OKAY]
[test_sce_mean_no_weight_ii_3d_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_no_weight_ii_3d_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_no_weight_ii_4d](test_data_set_0) [OKAY]
[test_sce_mean_no_weight_ii_4d_expanded](test_data_set_0) [OKAY]
[test_sce_mean_no_weight_ii_4d_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_no_weight_ii_4d_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_no_weight_ii_expanded](test_data_set_0) [OKAY]
[test_sce_mean_no_weight_ii_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_no_weight_ii_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_weight](test_data_set_0) [OKAY]
[test_sce_mean_weight_expanded](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii_3d](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii_3d_expanded](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii_3d_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_weight_ii_3d_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_weight_ii_4d](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii_4d_expanded](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii_4d_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_weight_ii_4d_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_weight_ii_expanded](test_data_set_0) [OKAY]
[test_sce_mean_weight_ii_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_weight_ii_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_mean_weight_log_prob](test_data_set_0) [FAIL]
[test_sce_mean_weight_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_none](test_data_set_0) [FAIL]
[test_sce_none_expanded](test_data_set_0) [FAIL]
[test_sce_none_log_prob](test_data_set_0) [FAIL]
[test_sce_none_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_none_weights](test_data_set_0) [FAIL]
[test_sce_none_weights_expanded](test_data_set_0) [FAIL]
[test_sce_none_weights_log_prob](test_data_set_0) [FAIL]
[test_sce_none_weights_log_prob_expanded](test_data_set_0) [FAIL]
[test_sce_sum](test_data_set_0) [OKAY]
[test_sce_sum_expanded](test_data_set_0) [OKAY]
[test_sce_sum_log_prob](test_data_set_0) [FAIL]
[test_sce_sum_log_prob_expanded](test_data_set_0) [FAIL]
[test_selu](test_data_set_0) [FAIL]
[test_selu_default](test_data_set_0) [FAIL]
[test_selu_example](test_data_set_0) [FAIL]
[test_shape](test_data_set_0) [FAIL]
[test_shape_example](test_data_set_0) [FAIL]
[test_shrink_hard](test_data_set_0) [FAIL]
[test_shrink_soft](test_data_set_0) [FAIL]
[test_sigmoid](test_data_set_0) [OKAY]
[test_sigmoid_example](test_data_set_0) [OKAY]
[test_sign](test_data_set_0) [OKAY]
[test_simple_rnn_defaults](test_data_set_0) [FAIL]
[test_simple_rnn_with_initial_bias](test_data_set_0) [FAIL]
[test_sin](test_data_set_0) [OKAY]
[test_sin_example](test_data_set_0) [OKAY]
[test_sinh](test_data_set_0) [OKAY]
[test_sinh_example](test_data_set_0) [OKAY]
[test_size](test_data_set_0) [OKAY]
[test_size_example](test_data_set_0) [OKAY]
[test_slice](test_data_set_0) [FAIL]
[test_slice_default_axes](test_data_set_0) [FAIL]
[test_slice_default_steps](test_data_set_0) [FAIL]
[test_slice_end_out_of_bounds](test_data_set_0) [FAIL]
[test_slice_neg](test_data_set_0) [FAIL]
[test_slice_neg_steps](test_data_set_0) [FAIL]
[test_slice_negative_axes](test_data_set_0) [FAIL]
[test_slice_start_out_of_bounds](test_data_set_0) [OKAY]
[test_softmax_axis_0](test_data_set_0) [FAIL]
[test_softmax_axis_0_expanded](test_data_set_0) [FAIL]
[test_softmax_axis_1](test_data_set_0) [FAIL]
[test_softmax_axis_1_expanded](test_data_set_0) [FAIL]
[test_softmax_axis_2](test_data_set_0) [FAIL]
[test_softmax_axis_2_expanded](test_data_set_0) [FAIL]
[test_softmax_default_axis](test_data_set_0) [FAIL]
[test_softmax_default_axis_expanded](test_data_set_0) [FAIL]
[test_softmax_example](test_data_set_0) [FAIL]
[test_softmax_example_expanded](test_data_set_0) [FAIL]
[test_softmax_large_number](test_data_set_0) [FAIL]
[test_softmax_large_number_expanded](test_data_set_0) [FAIL]
[test_softmax_negative_axis](test_data_set_0) [FAIL]
[test_softmax_negative_axis_expanded](test_data_set_0) [FAIL]
[test_softplus](test_data_set_0) [FAIL]
[test_softplus_example](test_data_set_0) [FAIL]
[test_softsign](test_data_set_0) [FAIL]
[test_softsign_example](test_data_set_0) [FAIL]
[test_split_equal_parts_1d](test_data_set_0) [FAIL]
[test_split_equal_parts_2d](test_data_set_0) [FAIL]
[test_split_equal_parts_default_axis](test_data_set_0) [FAIL]
[test_split_variable_parts_1d](test_data_set_0) [FAIL]
[test_split_variable_parts_2d](test_data_set_0) [FAIL]
[test_split_variable_parts_default_axis](test_data_set_0) [FAIL]
[test_split_zero_size_splits](test_data_set_0) [OKAY]
[test_sqrt](test_data_set_0) [FAIL]
[test_sqrt_example](test_data_set_0) [FAIL]
[test_squeeze](test_data_set_0) [FAIL]
[test_squeeze_negative_axes](test_data_set_0) [FAIL]
[test_strnormalizer_export_monday_casesensintive_lower](test_data_set_0) [OKAY]
[test_strnormalizer_export_monday_casesensintive_nochangecase](test_data_set_0) [OKAY]
[test_strnormalizer_export_monday_casesensintive_upper](test_data_set_0) [OKAY]
[test_strnormalizer_export_monday_empty_output](test_data_set_0) [OKAY]
[test_strnormalizer_export_monday_insensintive_upper_twodim](test_data_set_0) [OKAY]
[test_strnormalizer_nostopwords_nochangecase](test_data_set_0) [OKAY]
[test_sub](test_data_set_0) [FAIL]
[test_sub_bcast](test_data_set_0) [FAIL]
[test_sub_example](test_data_set_0) [FAIL]
[test_sum_example](test_data_set_0) [FAIL]
[test_sum_one_input](test_data_set_0) [FAIL]
[test_sum_two_inputs](test_data_set_0) [FAIL]
[test_tan](test_data_set_0) [OKAY]
[test_tan_example](test_data_set_0) [OKAY]
[test_tanh](test_data_set_0) [OKAY]
[test_tanh_example](test_data_set_0) [OKAY]
[test_tfidfvectorizer_tf_batch_onlybigrams_skip0](test_data_set_0) [FAIL]
[test_tfidfvectorizer_tf_batch_onlybigrams_skip5](test_data_set_0) [FAIL]
[test_tfidfvectorizer_tf_batch_uniandbigrams_skip5](test_data_set_0) [FAIL]
[test_tfidfvectorizer_tf_only_bigrams_skip0](test_data_set_0) [FAIL]
[test_tfidfvectorizer_tf_onlybigrams_levelempty](test_data_set_0) [FAIL]
[test_tfidfvectorizer_tf_onlybigrams_skip5](test_data_set_0) [FAIL]
[test_tfidfvectorizer_tf_uniandbigrams_skip5](test_data_set_0) [FAIL]
[test_thresholdedrelu](test_data_set_0) [OKAY]
[test_thresholdedrelu_default](test_data_set_0) [OKAY]
[test_thresholdedrelu_example](test_data_set_0) [OKAY]
[test_tile](test_data_set_0) [FAIL]
[test_tile_precomputed](test_data_set_0) [FAIL]
[test_top_k](test_data_set_0) [FAIL]
[test_top_k_negative_axis](test_data_set_0) [FAIL]
[test_top_k_smallest](test_data_set_0) [FAIL]
[test_training_dropout](test_data_set_0) [FAIL]
[test_training_dropout_default](test_data_set_0) [FAIL]
[test_training_dropout_default_mask](test_data_set_0) [FAIL]
[test_training_dropout_mask](test_data_set_0) [FAIL]
[test_training_dropout_zero_ratio](test_data_set_0) [FAIL]
[test_training_dropout_zero_ratio_mask](test_data_set_0) [FAIL]
[test_transpose_all_permutations_0](test_data_set_0) [FAIL]
[test_transpose_all_permutations_1](test_data_set_0) [FAIL]
[test_transpose_all_permutations_2](test_data_set_0) [FAIL]
[test_transpose_all_permutations_3](test_data_set_0) [FAIL]
[test_transpose_all_permutations_4](test_data_set_0) [FAIL]
[test_transpose_all_permutations_5](test_data_set_0) [FAIL]
[test_transpose_default](test_data_set_0) [FAIL]
[test_unique_not_sorted_without_axis](test_data_set_0) [FAIL]
[test_unique_sorted_with_axis](test_data_set_0) [FAIL]
[test_unique_sorted_with_axis_3d](test_data_set_0) [FAIL]
[test_unique_sorted_with_negative_axis](test_data_set_0) [FAIL]
[test_unique_sorted_without_axis](test_data_set_0) [FAIL]
[test_unsqueeze_axis_0](test_data_set_0) [FAIL]
[test_unsqueeze_axis_1](test_data_set_0) [FAIL]
[test_unsqueeze_axis_2](test_data_set_0) [FAIL]
[test_unsqueeze_axis_3](test_data_set_0) [FAIL]
[test_unsqueeze_negative_axes](test_data_set_0) [FAIL]
[test_unsqueeze_three_axes](test_data_set_0) [FAIL]
[test_unsqueeze_two_axes](test_data_set_0) [FAIL]
[test_unsqueeze_unsorted_axes](test_data_set_0) [FAIL]
[test_upsample_nearest](test_data_set_0) [FAIL]
[test_where_example](test_data_set_0) [FAIL]
[test_where_long_example](test_data_set_0) [FAIL]
[test_xor2d](test_data_set_0) [FAIL]
[test_xor3d](test_data_set_0) [FAIL]
[test_xor4d](test_data_set_0) [FAIL]
[test_xor_bcast3v1d](test_data_set_0) [FAIL]
[test_xor_bcast3v2d](test_data_set_0) [FAIL]
[test_xor_bcast4v2d](test_data_set_0) [FAIL]
[test_xor_bcast4v3d](test_data_set_0) [FAIL]
[test_xor_bcast4v4d](test_data_set_0) [FAIL]
离线
其实这个测试集是不充分的,不知是不是因为官方偷懒了,还是什么情况,很多数据类型的实现,都没有覆盖到,如果要全覆盖,估计测试集需要增加近10倍,才可能做到全覆盖。
离线
大神厉害,中国的钢铁侠!但是里面写什么我一半看不懂。能说说具体应用吗?
可以干什么,就先直接体验下,这个链接,https://microsoft.github.io/onnxjs-demo/#/mnist相信能给你 一个直观的认识。Mnist模型可以说是深度学习届的helloworld,干这行的估计都跑过这个模型。
这个是浏览器里的demo,是基于JS版的ONNX推理引擎,我现在要做的就是实现C版的ONNX推理引擎。
光这一个demo不过瘾?这里还有更多的体验,https://microsoft.github.io/onnxjs-demo/
ONNX模型哪里来呢,也别想着自己训练了,别人都训练好了,直接下载推理就行。https://github.com/onnx/models
最近编辑记录 xboot (2020-10-19 11:42:53)
离线
这个帖子就变成libonnx项目开发帖好了,用来做些项目记录,让对这个项目感兴趣的人能了解整个开发过程。
今天刚刚解决一个问题,ONNX IsInf算子,不仅仅需要能判断出无穷,而且还需要判断出是正无穷大还是负无穷大,而isinf函数,大部分平台实现上仅仅返回1或者0,有些则返回1,0或者-1三种返回值,为了兼容性,肯定用前者来实现,这就需要自己解决正无穷大和负无穷大的判定问题,经过热心网友的提示,找到完美解决思路,先判断是否是无穷大,然后再判断正负,一下就搞定。
相关代码如下:
for(i = 0, l = y->ndata; i < l; i++)
{
if(isinff(px[i]))
{
if((pdat->detect_negative && (px[i] < 0)) || (pdat->detect_positive && (px[i] > 0)))
py[i] = 1;
else
py[i] = 0;
}
else
{
py[i] = 0;
}
}
离线
review了下,实现24个算子,从7:30到11:30,差不多4个小时,平均写一个算子10分钟,大概100行代码,这效率杠杆的,当然这仅仅是软柿子,容易捏。
之所以可以这么快捷,还是得益于框架,基本就是复制粘贴的事。想了解架构的,可以直接翻看源码,这种技巧很实用,解决类似问题,基本手到擒来。
离线
应该是测试集的问题,这些训练图片都是外国人的手写体,跟国人的风格差异较大,特别是数字9,我写的基本不认。
离线
关于libonnx加速问题,其实有一个更优的方案,就是提供多种struct resolver_t backend同时使用,比如一个内置NPU,一个外置的加速棒,或者GPU,或者CPU内部向量指令之类的,然后前面的优先级最高,也是最快的,也是你最期望用于执行模型的加速器,越排到后面的,优先级越低,算后补。
因为算子较多,硬加速仅能支持部分算子,不同的硬件支持的算子还不太一样,通过这种机制,就可以使用上所有的硬件加速能力。
比如一个典型的场景,一个ARM COTREX-A7的CPU,立即集成了场景的NPU,而且它还有NEON指令加速能力,要发挥硬件所有能力,需要有三个backend
1,一个NPU backend
2,一个NEON指令加速的backend
3,还有一个libonnx默认纯C实现的后补型backend
最前面的能力最强,但可能支持的算子最少,这个时候就可以用上NEON加速了,当NEON加速也不支持时,就只能是default了,而default,速度不是最快的,但是一定是支持最完整的。
离线
这一点先有框架是做不到的,如果要想做到这一点,就必须支持多线程推理,那么可移植性就大打折扣,大概思路是,将计算图拆分成可并行的部分,然后每个部分创建一个线程,这一个线程又可以根据当前硬件负载情况切换到不同的推理硬件,就相当于做一个任务调度器,这种问题就是操作系统里典型的M:N问题,M个任务,N个CPU,这种优化可以榨干所有硬件资源。
这种优化几乎没有可移植性,所以也不会考虑走这条路。
离线
tensorflow开始没落了,pytorch基本有代替之势,tflite在两年前是最优选择,在现阶段而言不是最优方案,同级别的推理库比tflite好用的很多,当然,虽然叫lite但我个人觉得还是重量了些,嵌入式我觉得需要更轻量的。
离线
今天实现三个算子,两个比较简单的Ceil,Celu,还有一个稍微麻烦的Clip,Clip在运算时除了需要一个张量外还需要提供两个标量,一个min,一个max,而这标量按我的理解是可以用张量来描述的,但现在直接读pb文件,未能将标量映射到张量,这个问题估计是解析pb文件还需做些处理,先提交下,做个记录,后面分析下这个异常。
最近编辑记录 xboot (2020-10-20 21:32:57)
离线
线性代数中用到的几个基本的数学概念:
标量(scalar)
一个标量就是一个单独的数,我们在使用标量时,一般都要明确给出它是那种类型的数,例如 s∈ℝ,n∈ℕ
。
向量(vector)
一个向量是一列数。这些数是有序排列的。可以通过次序的索引,我们可以确定向量中每一个单独数。优势互,我们也要注明存储在向量中的元素是什么类型的,如果每个元素都属于 ℝ
且该向量有 n
个元素,那么该向量属于实数集 ℝ
的 n
次笛卡尔乘积构成的集合,记作 x∈ℝn
.
矩阵(matrix)
矩阵是一个二维数组,其中每一个元素由两个索引所确定。一个有m行,n列,每个元素都属于 ℝ
的矩阵记作 A∈ℝm×n
。
张量 (tensor)
超过两维的数组叫做张量。一般的,一个数组中的元素分布在若干维坐标的规则网格中,我们就称之为张量。
离线
难道onnx里面的零维张量就是标量,pytorch就将张量和变量做了合并,这个问题理解清楚了,上面的clip算子问题就解决了
离线
扩展了下现在的张量结构体,以统一张量和标量,零维的张量就代表标量。
union onnx_scalar_t {
uint8_t v_bool;
int8_t v_int8;
int16_t v_int16;
int32_t v_int32;
int64_t v_int64;
uint8_t v_uint8;
uint16_t v_uint16;
uint32_t v_uint32;
uint64_t v_uint64;
uint16_t v_bfloat16;
uint16_t v_float16;
float v_float32;
double v_float64;
struct {
float real;
float imaginary;
} v_complex64;
struct {
double real;
double imaginary;
} v_complex128;
};
struct onnx_tensor_t {
char * name;
enum onnx_tensor_type_t type;
int64_t * dims, * datas;
int ndim, ndata;
union onnx_scalar_t scalar;
};
经过以上改造,clip算子单元测试,顺利通过。
[test_clip](test_data_set_0) [OKAY]
[test_clip_default_int8_min](test_data_set_0) [OKAY]
[test_clip_default_min](test_data_set_0) [OKAY]
[test_clip_example](test_data_set_0) [OKAY]
[test_clip_inbounds](test_data_set_0) [OKAY]
[test_clip_outbounds](test_data_set_0) [OKAY]
[test_clip_splitbounds](test_data_set_0) [OKAY]
顺便查了一下,ONNX需要使用标量的地方,不仅仅是clip操作,还有其他算子也使用到了标量。
离线
从NNVM和ONNX看AI芯片的基础运算算子
这篇文章说得很到位,将核心算子做了个总结。
https://zhuanlan.zhihu.com/p/32711259
离线
总共160个算子需要实现,现在实现了34个,34 / 160 = 0.2125,完成度百分之二十一,越到后面的算子,复杂度会越来越高,现在都是挑简单的来先实现的。
离线
NNOM这个我在调研的时候,简单翻阅了下,对于小内存MCU而言,直接生成C是最优的方式,而且优化级别基本没有上限,就看PC端工具链优化能力了,是一个特别适合现有MCU场景的解决方案。
libonnx基本定位在SOC级别的AI芯片,具体实现上也是操作系统无关的。此类芯片跟MCU有本质区别,内存容量大,带有各种硬件加速资源,不然基本不能 称之为AI芯片,很多实用的模型都装不下,至少F1C100S或V3S这些级别以上配置。
关于难点,说得很到位,这些难点实现起来是有相当大的挑战,我这里再补充几个难点,onnx支持IF,LOOP,还有子图等流程控制算子,这些要做完整支持,就必须在框架设计上下狠功夫,还有所有的操作对象都是张量,onnx很多算子操作张量时支持双向广播,类似与numpy的实现,这就要求要用C实现numpy类似的功能,算需要用C写一个计算库。还有一个就是张量的阶数和和维度,是可能动态变化的,如果支持张量的动态变化,就需要每个算子里,都需做个检测,以便先申请好内存后,再让算子运算,这个就会严重影响推理的效率。我现在的实现是,在模型加载好后,认为每一个张量的阶数和维度是确定的。我现在还不敢肯定张量是否有可能随着运行,阶数和维度在变化,但看到有if流程控制算子,估计大概率是可能的,这个地方还需要深入研究下。
一句话,搞深度学习,就没有什么时候容易过。
大佬好,我一直也在维护一个轻量的定点推理库NNoM。https://github.com/majianjia/nnom
跟楼主的目标有部分重合。NNoM 的初衷只是为了简化ARM这套CMSIS-NN的使用,针对10~100kB RAM的单片机做的。不考虑支持现有的各种模型文件或者protobuf因为他们太大,并且需要文件系统的支持。
ONNX 也是我之前考虑的框架,不过我一直没有精力能做下来,现在只支持了Keras的模型。看了楼主的libonnx源码相当有感触。以我的经历,大概有几个难点
1. 支持绝大部分onnx的ops 需要相当大的工作量。
尤其是以后要适配各种硬件NPU时。各类单片机(比如K210)的硬件加速有着非常多的限制,输入层数,输出层数,卷积核大小等等。2. 定点算子。常见的8bit, 16bit等定点算子在计算时要考虑各种溢出问题,因为有一些量化方法是允许计算结果大于定点数值,所以在做算子时还需要做计算的“饱和”而不是任其“溢出”。这部分如果不能使用相关的汇编指令,会降低算子的效率。定点算子还会牵扯到很多浮点没有的操作,比如qformat,offset 和 per channel quantization 等。
3. 定点RNN 类型的算子,相当麻烦。包括量化和算子本身。
以上难点基本上在定点算子部分,如果考虑先做一套浮点算子,应该很快能完成。
如果考虑到MCU级别的应用,还需要内存上做文章,做层与层之间的内存复用,避免运行态的动态内存分配等。楼主已经迈出第一步,感觉做下去意义非常大,我之后有时间也会在github上给libonnx贡献代码:D
离线
今天移除了dump.c,dump.h,重新实现三个最重要对象的dump函数。
void onnx_tensor_dump(struct onnx_tensor_t * t, int detail);
void onnx_node_dump(struct onnx_node_t * n, int detail);
void onnx_context_dump(struct onnx_context_t * ctx, int detail);
张量本质上是一个多维数组,如何更好的格式化输出,这个还有待思考,现在仅仅按存储结构打印出来了。
离线
实现张量格式化输出,张量的理解有点烧脑。
input: float32[3 x 5 x 2] =
[[[0.548814, 0.715189,]
[0.602763, 0.544883,]
[0.423655, 0.645894,]
[0.437587, 0.891773,]
[0.963663, 0.383442,]]
[[0.791725, 0.528895,]
[0.568045, 0.925597,]
[0.0710361, 0.0871293,]
[0.0202184, 0.83262,]
[0.778157, 0.870012,]]
[[0.978618, 0.799159,]
[0.461479, 0.780529,]
[0.118274, 0.639921,]
[0.143353, 0.944669,]
[0.521848, 0.414662,]]]
发现一个很特别的情况,测试用例里输入的张量有可能是1阶0维的,而之前标量的判断标准是0阶0维,这个地方表现不太一致,还有待深入思考,难道需要将1阶0维和0阶0维统一对待,还是根本就不存在所谓的0阶。
离线
搜索了下1阶0维的张量还不少,先记录下,后面debug
X: float32[1 x 1 x 4 x 4] =
[[[[1, 2, 3, 4,]
[5, 6, 7, 8,]
[9, 10, 11, 12,]
[13, 14, 15, 16,]]]]
roi: float32[0] =
scales: float32[0] =
sizes: int64[4] =
[1, 1, 3, 2,]
[test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn](test_data_set_0) [FAIL]
离线
实现张量的坐标与索引互换。
static inline int onnx_tensor_get_index(struct onnx_tensor_t * t, int * coords)
{
int index, i;
for(i = 0, index = coords[0]; i < t->ndim - 1; i++)
index = t->dims[i + 1] * index + coords[i + 1];
return index;
}
static inline void onnx_tensor_get_coords(struct onnx_tensor_t * t, int index, int * coords)
{
int i;
for(i = t->ndim - 1; i >= 0; i--)
{
coords[i] = index % t->dims[i];
index /= t->dims[i];
}
}
离线
实现张量转置算子,利用了上面实现的onnx_tensor_get_coords和onnx_tensor_get_index内联函数,这两个内联函数是可以优化的,尽量避免使用除法运算来实现。
[test_transpose_all_permutations_0](test_data_set_0) [OKAY]
[test_transpose_all_permutations_1](test_data_set_0) [OKAY]
[test_transpose_all_permutations_2](test_data_set_0) [OKAY]
[test_transpose_all_permutations_3](test_data_set_0) [OKAY]
[test_transpose_all_permutations_4](test_data_set_0) [OKAY]
[test_transpose_all_permutations_5](test_data_set_0) [OKAY]
[test_transpose_default](test_data_set_0) [OKAY]
离线
开源第10天,项目进展回报:现总共实现了44个算子,完成度44 / 160=27.5%,越到后面,算子复杂度越高,一个看起来不那么复杂的Cast算子,类型强制转换用的,代码量也达到了1800行,只因ONNX的算子抽象层次较高,很多算子就是numpy的api接口,参数种类也较多。如果按照这种代码量,一天能写一个算子,算很高效了,任重道远。
最近编辑记录 xboot (2020-10-26 16:15:32)
离线
需要研究并实现numpy的广播机制了,太多算子用到这种特性,高阶API,实现起来不会太轻松。
离线
广播的规则:
让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
输出数组的形状是输入数组形状的各个维度上的最大值。
如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
简单理解:
对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
数组拥有相同形状。
当前维度的值相等。
当前维度的值有一个是 1。
离线
搞定张量多播机制,这个太烧脑了。
static inline int onnx_tensor_multi_broadcast_reshape(struct onnx_tensor_t * a, struct onnx_tensor_t * b, struct onnx_tensor_t * y, enum onnx_tensor_type_t type)
{
int ndim = max(a->ndim, b->ndim);
int dims[ndim];
int i, j, k;
if(ndim > 0)
{
for(i = a->ndim - 1, j = b->ndim - 1, k = ndim - 1; k >= 0; k--)
{
if(i < 0)
dims[k] = b->dims[j--];
else if(j < 0)
dims[k] = a->dims[i--];
else
{
if(a->dims[i] == b->dims[j])
dims[k] = a->dims[i];
else if((a->dims[i] == 1) || (b->dims[j] == 1))
dims[k] = (a->dims[i] > b->dims[j]) ? a->dims[i] : b->dims[j];
else
return 0;
i--;
j--;
}
}
}
if((y->type != type) || (y->ndim != ndim) || (memcmp(y->dims, dims, sizeof(int) * ndim) != 0))
onnx_tensor_reinit(y, type, dims, ndim);
return 1;
}
static inline void * onnx_tensor_broadcast_map_address(struct onnx_tensor_t * x, struct onnx_tensor_t * y, int offset)
{
int xndim = x->ndim;
int yndim = y->ndim;
int dndim = yndim - xndim;
int ix[xndim];
int iy[yndim];
int i;
onnx_tensor_offset_to_indices(y, offset, iy);
for(i = 0; i < xndim; i++)
ix[i] = iy[dndim + i] % x->dims[i];
return x->datas + onnx_tensor_indices_to_offset(x, ix) * onnx_tensor_type_sizeof(x->type);
}
核心就这两个函数,如果谁能半天内看懂这两个函数,绝对是数学系毕业的。
先拿Xor算子开刀,利用上面这两个函数,顺利通过单元测试。
static void Xor_bool(struct onnx_node_t * n)
{
struct onnx_tensor_t * y = n->outputs[0];
struct onnx_tensor_t * a = n->inputs[0];
struct onnx_tensor_t * b = n->inputs[1];
uint8_t * py = (uint8_t *)y->datas;
uint8_t * pa;
uint8_t * pb;
int i, l;
if(onnx_tensor_multi_broadcast_reshape(a, b, y, a->type))
{
for(i = 0, l = y->ndata; i < l; i++)
{
pa = onnx_tensor_broadcast_map_address(a, y, i);
pb = onnx_tensor_broadcast_map_address(b, y, i);
py[i] = (*pa != *pb) ? 1 : 0;
}
}
}
单元测试结果
[test_xor2d](test_data_set_0) [OKAY]
[test_xor3d](test_data_set_0) [OKAY]
[test_xor4d](test_data_set_0) [OKAY]
[test_xor_bcast3v1d](test_data_set_0) [OKAY]
[test_xor_bcast3v2d](test_data_set_0) [OKAY]
[test_xor_bcast4v2d](test_data_set_0) [OKAY]
[test_xor_bcast4v3d](test_data_set_0) [OKAY]
[test_xor_bcast4v4d](test_data_set_0) [OKAY]
最近编辑记录 xboot (2020-10-27 18:04:47)
离线
已实现60个算子,还剩整整100个,完成度 60 / 160 = 37.5%
离线
现在的总代码量,2万行。
172 text files.
172 unique files.
0 files ignored.
github.com/AlDanial/cloc v 1.82 T=0.11 s (1533.6 files/s, 215931.1 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 165 1383 825 17885
C/C++ Header 6 299 1708 2057
make 1 15 3 43
-------------------------------------------------------------------------------
SUM: 172 1697 2536 19985
-------------------------------------------------------------------------------
离线
已支持的算子,现在61个,其中一个Sub暂时屏蔽了,因为测试集依赖Reduce算子,Reduce算子还未实现。
.
├── Abs.c
├── Acos.c
├── Acosh.c
├── Add.c
├── And.c
├── Asin.c
├── Asinh.c
├── Atan.c
├── Atanh.c
├── BatchNormalization.c
├── BitShift.c
├── Cast.c
├── Ceil.c
├── Celu.c
├── Clip.c
├── Constant.c
├── ConstantOfShape.c
├── Cos.c
├── Cosh.c
├── Div.c
├── Elu.c
├── Equal.c
├── Erf.c
├── Exp.c
├── Floor.c
├── Greater.c
├── GreaterOrEqual.c
├── HardSigmoid.c
├── Identity.c
├── IsInf.c
├── IsNaN.c
├── LeakyRelu.c
├── Less.c
├── LessOrEqual.c
├── Log.c
├── Mod.c
├── Mul.c
├── Neg.c
├── Not.c
├── Or.c
├── Reciprocal.c
├── Relu.c
├── Reshape.c
├── Round.c
├── Selu.c
├── Shape.c
├── Shrink.c
├── Sigmoid.c
├── Sign.c
├── Sin.c
├── Sinh.c
├── Size.c
├── Softplus.c
├── Softsign.c
├── Sqrt.c
├── Sub.c
├── Tan.c
├── Tanh.c
├── ThresholdedRelu.c
├── Transpose.c
└── Xor.c
0 directories, 61 files
离线
已实现65个算子,完成度,65 / 160 = 40.6%, 新增加如下四个算子,并通过单元测试。
InstanceNormalization
PRelu
ArgMax
ArgMin
离线
已实现68个算子,再新增三个,还有92个算子,其中有部分是训练用的,大概率是无需实现的。
Flatten
Expand
Pow
离线
已实现74个算子,完成度 74 / 160 = 46.25%,其中Softmax算子,实现的是11版本的操作集,但最新的操作集是13版本,这个函数行为被修改了,导致单元测试未能全部通过。新增如下算子:
Softmax
Sum
Mean
Max
Min
Range
离线
离线
看着好适合嵌入式,请问不带NPU的F1C200S这种芯片跑起推测算法来会吃力吗?
吃力那是肯定的,当然还是看模型,小模型,纯cpu跑,是没有太大压力的。
离线
修改Softmax函数,支持13版操作集,新增两个算子,已实现77个算子,完成度77 / 160 = 48.125%
Concat
LogSoftmax
离线
今天新增如下三个算子,节奏越来越慢了。
GlobalAveragePool
GlobalLpPool
GlobalMaxPool
离线
onnx算子支持列表文档,直接点击下面的链接,此文档会持续更新,跟实际支持情况保持同步。
https://github.com/xboot/libonnx/blob/master/documents/the-supported-operator-table.md
最近编辑记录 xboot (2020-11-04 11:17:14)
离线
是否支持深度可分离卷积,就看ONNX规范是否会增加这种算子,跟ONNX规范同步。
离线
已实现83个算子,完成度 83 / 160 = 51.875%,终于完成一半了。
增加如下算子:
RandomNormal
RandomNormalLike
RandomUniform
RandomUniformLike
离线
今天增加一个算子LRN,慢慢来,持久战。
离线
今天增加Multinomial算子支持
离线
再增加Squeeze,Unsqueeze两个算子,现在共实现了87个,完成度87 / 160 = 54.375%
最近编辑记录 xboot (2020-11-06 19:39:05)
离线
增加Tile算子和dropout算子支持,其中dropout实现不完整,训练功能,就不支持了。
离线
增加where,MatMul,Gemm三个算子,其中Where暂时屏蔽。
离线
修复round算子,用rint代替round函数,round算子不是四舍五入,而是四舍六入五偶。
离线
现在实现了92个算子,写够100个算子,就差不多了,剩下的算子留给有心人继续了,勤勤恳恳一个月,该需要做些demo,出点成果了。
离线
增加8个算子,正好100个了
ReduceL1
ReduceL2
ReduceLogSum
ReduceLogSumExp
ReduceMean
ReduceProd
ReduceSum
ReduceSumSquare
离线
再增加2个算子,共计102个完成度 102 / 160 = 63.75 %
ReduceMax
ReduceMin
离线
移除张量结构体里面的标量定义,如果区别对待的话,会导致编写算子时复杂度提升,现在统一对待标量及张量,0维的张量就是标量,即ndim = 0, ndatas = 1。这样改造后,现有实现的算子,就支持标量运算了。
struct onnx_tensor_t {
char * name;
enum onnx_tensor_type_t type;
int * strides;
int * dims;
int ndim;
void * datas;
int ndata;
};
离线
是否支持加速,就看你有没有实现struct onnx_resolver_t 对象,现在仅仅实现了一个cpu版的struct onnx_resolver_t,这个接口总共160个算子,你填多少个算子,就加速多少个算子,没有填的,就用默认cpu版的。完整接口如下:
struct onnx_resolver_t {
const char * name;
void * (*create)(void);
void (*destroy)(void * rctx);
void (*op_Abs)(struct onnx_node_t * n);
void (*op_Acos)(struct onnx_node_t * n);
void (*op_Acosh)(struct onnx_node_t * n);
void (*op_Add)(struct onnx_node_t * n);
void (*op_And)(struct onnx_node_t * n);
void (*op_ArgMax)(struct onnx_node_t * n);
void (*op_ArgMin)(struct onnx_node_t * n);
void (*op_Asin)(struct onnx_node_t * n);
void (*op_Asinh)(struct onnx_node_t * n);
void (*op_Atan)(struct onnx_node_t * n);
void (*op_Atanh)(struct onnx_node_t * n);
void (*op_AveragePool)(struct onnx_node_t * n);
void (*op_BatchNormalization)(struct onnx_node_t * n);
void (*op_BitShift)(struct onnx_node_t * n);
void (*op_Cast)(struct onnx_node_t * n);
void (*op_Ceil)(struct onnx_node_t * n);
void (*op_Clip)(struct onnx_node_t * n);
void (*op_Compress)(struct onnx_node_t * n);
void (*op_Concat)(struct onnx_node_t * n);
void (*op_ConcatFromSequence)(struct onnx_node_t * n);
void (*op_Constant)(struct onnx_node_t * n);
void (*op_ConstantOfShape)(struct onnx_node_t * n);
void (*op_Conv)(struct onnx_node_t * n);
void (*op_ConvInteger)(struct onnx_node_t * n);
void (*op_ConvTranspose)(struct onnx_node_t * n);
void (*op_Cos)(struct onnx_node_t * n);
void (*op_Cosh)(struct onnx_node_t * n);
void (*op_CumSum)(struct onnx_node_t * n);
void (*op_DepthToSpace)(struct onnx_node_t * n);
void (*op_DequantizeLinear)(struct onnx_node_t * n);
void (*op_Det)(struct onnx_node_t * n);
void (*op_Div)(struct onnx_node_t * n);
void (*op_Dropout)(struct onnx_node_t * n);
void (*op_Einsum)(struct onnx_node_t * n);
void (*op_Elu)(struct onnx_node_t * n);
void (*op_Equal)(struct onnx_node_t * n);
void (*op_Erf)(struct onnx_node_t * n);
void (*op_Exp)(struct onnx_node_t * n);
void (*op_Expand)(struct onnx_node_t * n);
void (*op_EyeLike)(struct onnx_node_t * n);
void (*op_Flatten)(struct onnx_node_t * n);
void (*op_Floor)(struct onnx_node_t * n);
void (*op_GRU)(struct onnx_node_t * n);
void (*op_Gather)(struct onnx_node_t * n);
void (*op_GatherElements)(struct onnx_node_t * n);
void (*op_GatherND)(struct onnx_node_t * n);
void (*op_Gemm)(struct onnx_node_t * n);
void (*op_GlobalAveragePool)(struct onnx_node_t * n);
void (*op_GlobalLpPool)(struct onnx_node_t * n);
void (*op_GlobalMaxPool)(struct onnx_node_t * n);
void (*op_Greater)(struct onnx_node_t * n);
void (*op_HardSigmoid)(struct onnx_node_t * n);
void (*op_Hardmax)(struct onnx_node_t * n);
void (*op_Identity)(struct onnx_node_t * n);
void (*op_If)(struct onnx_node_t * n);
void (*op_InstanceNormalization)(struct onnx_node_t * n);
void (*op_IsInf)(struct onnx_node_t * n);
void (*op_IsNaN)(struct onnx_node_t * n);
void (*op_LRN)(struct onnx_node_t * n);
void (*op_LSTM)(struct onnx_node_t * n);
void (*op_LeakyRelu)(struct onnx_node_t * n);
void (*op_Less)(struct onnx_node_t * n);
void (*op_Log)(struct onnx_node_t * n);
void (*op_Loop)(struct onnx_node_t * n);
void (*op_LpNormalization)(struct onnx_node_t * n);
void (*op_LpPool)(struct onnx_node_t * n);
void (*op_MatMul)(struct onnx_node_t * n);
void (*op_MatMulInteger)(struct onnx_node_t * n);
void (*op_Max)(struct onnx_node_t * n);
void (*op_MaxPool)(struct onnx_node_t * n);
void (*op_MaxRoiPool)(struct onnx_node_t * n);
void (*op_MaxUnpool)(struct onnx_node_t * n);
void (*op_Mean)(struct onnx_node_t * n);
void (*op_Min)(struct onnx_node_t * n);
void (*op_Mod)(struct onnx_node_t * n);
void (*op_Mul)(struct onnx_node_t * n);
void (*op_Multinomial)(struct onnx_node_t * n);
void (*op_Neg)(struct onnx_node_t * n);
void (*op_NonMaxSuppression)(struct onnx_node_t * n);
void (*op_NonZero)(struct onnx_node_t * n);
void (*op_Not)(struct onnx_node_t * n);
void (*op_OneHot)(struct onnx_node_t * n);
void (*op_Or)(struct onnx_node_t * n);
void (*op_PRelu)(struct onnx_node_t * n);
void (*op_Pad)(struct onnx_node_t * n);
void (*op_Pow)(struct onnx_node_t * n);
void (*op_QLinearConv)(struct onnx_node_t * n);
void (*op_QLinearMatMul)(struct onnx_node_t * n);
void (*op_QuantizeLinear)(struct onnx_node_t * n);
void (*op_RNN)(struct onnx_node_t * n);
void (*op_RandomNormal)(struct onnx_node_t * n);
void (*op_RandomNormalLike)(struct onnx_node_t * n);
void (*op_RandomUniform)(struct onnx_node_t * n);
void (*op_RandomUniformLike)(struct onnx_node_t * n);
void (*op_Reciprocal)(struct onnx_node_t * n);
void (*op_ReduceL1)(struct onnx_node_t * n);
void (*op_ReduceL2)(struct onnx_node_t * n);
void (*op_ReduceLogSum)(struct onnx_node_t * n);
void (*op_ReduceLogSumExp)(struct onnx_node_t * n);
void (*op_ReduceMax)(struct onnx_node_t * n);
void (*op_ReduceMean)(struct onnx_node_t * n);
void (*op_ReduceMin)(struct onnx_node_t * n);
void (*op_ReduceProd)(struct onnx_node_t * n);
void (*op_ReduceSum)(struct onnx_node_t * n);
void (*op_ReduceSumSquare)(struct onnx_node_t * n);
void (*op_Relu)(struct onnx_node_t * n);
void (*op_Reshape)(struct onnx_node_t * n);
void (*op_Resize)(struct onnx_node_t * n);
void (*op_ReverseSequence)(struct onnx_node_t * n);
void (*op_RoiAlign)(struct onnx_node_t * n);
void (*op_Round)(struct onnx_node_t * n);
void (*op_Scan)(struct onnx_node_t * n);
void (*op_ScatterElements)(struct onnx_node_t * n);
void (*op_ScatterND)(struct onnx_node_t * n);
void (*op_Selu)(struct onnx_node_t * n);
void (*op_SequenceAt)(struct onnx_node_t * n);
void (*op_SequenceConstruct)(struct onnx_node_t * n);
void (*op_SequenceEmpty)(struct onnx_node_t * n);
void (*op_SequenceErase)(struct onnx_node_t * n);
void (*op_SequenceInsert)(struct onnx_node_t * n);
void (*op_SequenceLength)(struct onnx_node_t * n);
void (*op_Shape)(struct onnx_node_t * n);
void (*op_Shrink)(struct onnx_node_t * n);
void (*op_Sigmoid)(struct onnx_node_t * n);
void (*op_Sign)(struct onnx_node_t * n);
void (*op_Sin)(struct onnx_node_t * n);
void (*op_Sinh)(struct onnx_node_t * n);
void (*op_Size)(struct onnx_node_t * n);
void (*op_Slice)(struct onnx_node_t * n);
void (*op_Softplus)(struct onnx_node_t * n);
void (*op_Softsign)(struct onnx_node_t * n);
void (*op_SpaceToDepth)(struct onnx_node_t * n);
void (*op_Split)(struct onnx_node_t * n);
void (*op_SplitToSequence)(struct onnx_node_t * n);
void (*op_Sqrt)(struct onnx_node_t * n);
void (*op_Squeeze)(struct onnx_node_t * n);
void (*op_StringNormalizer)(struct onnx_node_t * n);
void (*op_Sub)(struct onnx_node_t * n);
void (*op_Sum)(struct onnx_node_t * n);
void (*op_Tan)(struct onnx_node_t * n);
void (*op_Tanh)(struct onnx_node_t * n);
void (*op_TfIdfVectorizer)(struct onnx_node_t * n);
void (*op_ThresholdedRelu)(struct onnx_node_t * n);
void (*op_Tile)(struct onnx_node_t * n);
void (*op_TopK)(struct onnx_node_t * n);
void (*op_Transpose)(struct onnx_node_t * n);
void (*op_Unique)(struct onnx_node_t * n);
void (*op_Unsqueeze)(struct onnx_node_t * n);
void (*op_Where)(struct onnx_node_t * n);
void (*op_Xor)(struct onnx_node_t * n);
void (*op_Celu)(struct onnx_node_t * n);
void (*op_DynamicQuantizeLinear)(struct onnx_node_t * n);
void (*op_GreaterOrEqual)(struct onnx_node_t * n);
void (*op_LessOrEqual)(struct onnx_node_t * n);
void (*op_LogSoftmax)(struct onnx_node_t * n);
void (*op_MeanVarianceNormalization)(struct onnx_node_t * n);
void (*op_NegativeLogLikelihoodLoss)(struct onnx_node_t * n);
void (*op_Range)(struct onnx_node_t * n);
void (*op_Softmax)(struct onnx_node_t * n);
void (*op_SoftmaxCrossEntropyLoss)(struct onnx_node_t * n);
};
离线
补充一下,struct onnx_resolver_t对象其实就是所谓的backend,后端什么,在这里结构体取名为struct onnx_resolver_t,其实想表达的是求解器,后端这个词用烂了,感觉并不能看其名知其意,所以换成了求解器,个人觉得,这个词更能表达深度学习加速接口,你可以定义很多求解器,可以优先选择某个求解器,也可以混用求解器。这样表达更到位点。
离线
增加AveragePool及MaxPool两个算子,但有部分测试选项未能通过,onnx文档在描述这两个算子时表达不太清楚,很多细节只能猜测。
离线
发现现存的预训练模型,太多使用旧版本操作集,而libonnx之前的预想的是仅仅支持最新版操作集,比如当前最新的opset 13,经过仔细研究,如果仅支持最新版操作集,libonnx就很难实用化,各种训练框架或者模型转换工具还没有一个能支持opset 13操作集的,这就显得太尴尬了,在此刻,根本没有采用最新操作集版本的模型。就像厨师练就了一身刀工,却发现没有切菜板了。
所以,还是听从大老师的意见,计划开始支持旧版本算子,争取能达到,只要是onnx模型,我就能给你跑起来。当然了,开了这个坑,又得辛苦一段时间了。支持旧版本算子的工作量不低,平均一个算子,三个版本的话,那工作量就增加了量两倍了。当然因为写过一个版本,所以支持起来,代价肯定没有第一次开荒时的代价高。
但愿libonnx能实用化,不如所有精力都白费了。
现在dev分支,已增加旧版本算子兼容机制,后面主要的工作,就是填空,并同步更新算子支持文档,开始细化各个版本的支持情况。
https://github.com/xboot/libonnx/blob/master/documents/the-supported-operator-table.md
跑demo本以为很快可以进行,这下又得往后延了,没有旧版本算子的支持,就跑不了任何一个现存的模型。所以没有退路,只能勇往直前。
离线
已完成细化旧版本算子支持文档,将能支持的,可以兼容的算子同步做了更新,剩下的未填的,都是无法兼容的算子。这种填空,就按缺什么,就补什么这种思路来开发了。
离线
有三个重要的算子,需要完善,并加强测试。
AveragePool
MaxPool
Conv
现在这几个算子无法完全通过测试集的测试,急需修复此问题,很关键的任务。
最近编辑记录 xboot (2020-11-19 17:59:39)
离线
完善了下上面三个算子,稍完善了点。还需加强测试。
离线
现在总代码量4万2千行了
174 text files.
174 unique files.
0 files ignored.
github.com/AlDanial/cloc v 1.82 T=0.32 s (543.2 files/s, 147711.0 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 167 2390 824 39969
C/C++ Header 6 303 1708 2062
make 1 15 3 43
-------------------------------------------------------------------------------
SUM: 174 2708 2535 42074
-------------------------------------------------------------------------------
离线
新增加了pytorch-operator和pytorch-converted测试集,这两个测试集很多都是使用的旧版本算子,可以顺便验证旧版本算子支持情况。
离线
添加benchmark性能测试工具,代码路径为https://github.com/xboot/libonnx/tree/master/examples/benchmark
传递onnx模型路径,以及 一个可选的运行次数,程序会自动计算出各种算子的平均消耗时间。输出格式如下:
左边是算子名,中间时执行了多少次,最右边是平均消耗时间,单位是微秒。
Profiler analysis:
Add-8 300 186.717(us)
Conv-8 200 10716.635(us)
MatMul-8 100 2.400(us)
MaxPool-8 200 53.395(us)
Relu-8 200 0.875(us)
Reshape-8 200 0.375(us)
可以看到卷集运算是最耗cpu的。
离线
mnist手写数字识别模型终于测试通过了,算是里程碑事件,可以开始写demo了。
[test_mnist_8](test_data_set_0) [OKAY]
[test_mnist_8](test_data_set_1) [OKAY]
[test_mnist_8](test_data_set_2) [OKAY]
为了跑这个小模型,编写了4万行代码,杀鸡用上牛刀。
离线
优化卷集算子,用benchmark性能测试,速度提升20倍。
$ ./examples/benchmark/benchmark tests/model/test_mnist_8/model.onnx 100
Profiler analysis:
Add-8 default 300 187.523(us)
Conv-8 default 200 531.945(us)
MatMul-8 default 100 2.110(us)
MaxPool-8 default 200 51.390(us)
Relu-8 default 200 0.755(us)
Reshape-8 default 200 0.205(us)
离线
onnx还没见到深度可分离卷积这种算子,估计后面会有人commit吧。
离线
超分辨率模型super_resolution_10测试通过,不过推理时间比较慢,大概需要近2秒,大部分时间都消耗在卷积算子上。
./examples/benchmark/benchmark tests/model/super_resolution_10/model.onnx
Profiler analysis:
Constant-10 default 20 0.700(us)
Conv-10 default 40 1723833.375(us)
Relu-10 default 30 2309.867(us)
Reshape-10 default 20 332.750(us)
Transpose-10 default 10 19598.700(us)
离线
转换出来的模型树看看,看叫啥名
离线
合并了下ReinForce-II大佬的pull request,采用跨内核共享数据的方式继续优化Conv卷积算子,在各个平台下的性能指标对比如下:
benchmark: super_resolution_10
5900X:
before:
Constant-10 default 10 0.000(us)
Conv-10 default 20 1496819.700(us)
Relu-10 default 15 964.000(us)
Reshape-10 default 10 124.800(us)
Transpose-10 default 5 6619.800(us)
after:
Constant-10 default 10 0.200(us)
Conv-10 default 20 692877.650(us)
Relu-10 default 15 795.733(us)
Reshape-10 default 10 129.200(us)
Transpose-10 default 5 6785.200(us)
M1:
before:
Constant-10 default 10 0.000(us)
Conv-10 default 20 650797.950(us)
Relu-10 default 15 411.600(us)
Reshape-10 default 10 37.600(us)
Transpose-10 default 5 3822.400(us)
after:
Profiler analysis:
Constant-10 default 10 0.000(us)
Conv-10 default 20 640919.200(us)
Relu-10 default 15 368.800(us)
Reshape-10 default 10 37.200(us)
Transpose-10 default 5 3711.400(us)
RK3399:
A72:
before:
Constant-10 default 2 0.500(us)
Conv-10 default 4 4831419.250(us)
Relu-10 default 3 2834.000(us)
Reshape-10 default 2 504.000(us)
Transpose-10 default 1 18659.000(us)
after:
Constant-10 default 2 1.000(us)
Conv-10 default 4 2608700.000(us)
Relu-10 default 3 2887.333(us)
Reshape-10 default 2 525.000(us)
Transpose-10 default 1 18725.000(us)
A53:
before:
Constant-10 default 2 1.000(us)
Conv-10 default 4 15421956.500(us)
Relu-10 default 3 6136.667(us)
Reshape-10 default 2 971.000(us)
Transpose-10 default 1 47123.000(us)
after:
Constant-10 default 2 0.500(us)
Conv-10 default 4 7815257.500(us)
Relu-10 default 3 6194.667(us)
Reshape-10 default 2 964.500(us)
Transpose-10 default 1 47420.000(us)
一声叹息,ARM的性能跟X86相比,差异巨大。
离线
ReinForce-II大佬再次发力优化Conv算子,有个5倍的性能提升。
Profiler analysis:
Constant-10 default 20 0.150(us)
Conv-10 default 40 156774.525(us)
Relu-10 default 30 1776.433(us)
Reshape-10 default 20 135.900(us)
Transpose-10 default 10 12992.800(us)
离线
添加了1及11版本的Softmax低版本算子以及LogSoftmax的低版本算子,补全后shufflenet_v1_9模型测试,顺利通过。
[shufflenet_v1_9](test_data_set_0) [OKAY]
[shufflenet_v1_9](test_data_set_1) [OKAY]
[shufflenet_v1_9](test_data_set_2) [OKAY]
[super_resolution_10](test_data_set_0) [OKAY]
离线
shufflenet_v1_9模型性能测试
./examples/benchmark/benchmark tests/model/shufflenet_v1_9/model.onnx
Profiler analysis:
AveragePool-9 default 40 1245.100(us)
BatchNormalization-9default 490 260.143(us)
Concat-9 default 30 145.500(us)
Conv-9 default 490 1080.606(us)
Gemm-9 default 10 427.400(us)
MaxPool-9 default 10 7839.200(us)
Relu-9 default 330 32.142(us)
Reshape-9 default 330 18.033(us)
Softmax-9 default 10 7.500(us)
Sum-9 default 130 3798.515(us)
Transpose-9 default 160 1887.519(us)
离线
squeezenet_v1.1 模型测试顺利通过。
[squeezenet_v11_7](test_data_set_0) [OKAY]
[squeezenet_v11_7](test_data_set_1) [OKAY]
[squeezenet_v11_7](test_data_set_2) [OKAY]
squeezenet_v1.1模型性能测试
$ ./examples/benchmark/benchmark tests/model/squeezenet_v11_7/model.onnx
Profiler analysis:
AveragePool-7 default 10 1458.500(us)
Concat-7 default 80 624.675(us)
Conv-7 default 260 2106.223(us)
Dropout-7 default 10 34.700(us)
MaxPool-7 default 30 11657.733(us)
Relu-7 default 260 53.819(us)
Reshape-7 default 10 0.800(us)
离线
libonnx现在可以跑5个模型了
[mnist_8](test_data_set_0) [OKAY]
[mnist_8](test_data_set_1) [OKAY]
[mnist_8](test_data_set_2) [OKAY]
[mobilenet_v2_7](test_data_set_0) [OKAY]
[mobilenet_v2_7](test_data_set_1) [OKAY]
[mobilenet_v2_7](test_data_set_2) [OKAY]
[shufflenet_v1_9](test_data_set_0) [OKAY]
[shufflenet_v1_9](test_data_set_1) [OKAY]
[shufflenet_v1_9](test_data_set_2) [OKAY]
[squeezenet_v11_7](test_data_set_0) [OKAY]
[squeezenet_v11_7](test_data_set_1) [OKAY]
[squeezenet_v11_7](test_data_set_2) [OKAY]
[super_resolution_10](test_data_set_0) [OKAY]
离线
再增加一个模型,测试通过 tiny yolo v2,共计6个了
[tinyyolo_v2_8](test_data_set_0) [OKAY]
[tinyyolo_v2_8](test_data_set_1) [OKAY]
[tinyyolo_v2_8](test_data_set_2) [OKAY]
离线
yolo v2 性能测试分析
$ ./examples/benchmark/benchmark tests/model/tinyyolo_v2_8/model.onnx
Profiler analysis:
Add-8 default 10 30385.700(us)
BatchNormalization-8default 80 2643.350(us)
Conv-8 default 90 113841.089(us)
LeakyRelu-8 default 80 524.700(us)
MaxPool-8 default 60 11425.350(us)
Mul-8 default 10 28094.300(us)
离线
有些模型未能测试通过,需要进一步debug,估计是有些算子计算错误,从一个模型里找出哪里计算错误,简直大海捞针,幸好大老师帮忙制作了一些py工具,方便查看模型内部节点的正确数据,有了这个工具,就可以方便的debug了,找出哪些算子异常。
最近编辑记录 xboot (2020-11-25 09:15:27)
离线
只要保证default版的求解器完全正确,后面的各种NPU求解器验证就相对简单了,可以很方便的编写自动化工具,自动比对NPU的实现,是否完全正确。所有的前提就是default版是经过千锤百炼,通过各种测试。这些,还是期望大家多提交些issue,不断完善default版的实现。
离线
nvdia,省时省力,很封闭
离线
第一个demo,mnist手写数字识别
MNIST demo源码路径:
https://github.com/xboot/libonnx/tree/master/examples/mnist
离线
libonnx的完善工作临时搁置下,先开发下V831这个芯片的BSP包。见下面这个链接。
https://whycan.com/t_5647.html
离线
直接用Windows版的GCC吧
离线
valloc这个函数的引用,后面完全去掉,不是很必要,但memalign这个函数,还是必须要调用的,现在没有比较好的解决方案来实现跨平台。
离线
有一种方案是,在创建onnx_context_t对象时,提供内存管理接口回调来实现跨平台,不过这样会增加用户使用上的复杂性。这个问题还需要仔细琢磨。
最近编辑记录 xboot (2020-12-12 21:14:24)
离线
已将valloc删除,改用malloc函数,如果malloc函数分配出来的内存能保证double类型对齐,那么在不考虑avx512指令加速的情况时,所有的内存分配都可以使用malloc实现,但申请对齐内存这个如何实现跨平台,待考虑。
最近编辑记录 xboot (2020-12-12 22:09:13)
离线
来光线追踪吧,1000行就可以了。
离线
移除helper相关文件,增加onnxconf.h可配置头文件,用于增强系统可移植性,还有需要调用memalign的地方现在都换成malloc函数了。
离线
修改benchmark程序,统计模型的运行消耗,mnist模型纯CPU版跑,千帧无压力。
~/libonnx/libonnx$ ./examples/benchmark/benchmark ./tests/model/mnist_8/model.onnx 2000
Profiler analysis:
Add-8 default 6000 182.201(us)
Conv-8 default 4000 102.606(us)
MatMul-8 default 2000 2.110(us)
MaxPool-8 default 4000 51.152(us)
Relu-8 default 4000 0.819(us)
Reshape-8 default 4000 0.235(us)
----------------------------------------------------------------
Running counts: 2000, Average time: 858.336(us), Frame rates: 1165.046(fps)
离线
只要是实用的代码,都会有有参考价值的
离线
参考这个程序,
https://github.com/xboot/libonnx/blob/master/examples/hello/main.c
打印下看是什么情况,如果ctx是null,估计是文件不合规吧
/*
* Dump onnx context
*/
onnx_context_dump(ctx, 0);
离线
估计是你导出的问题,用netron查看吧
离线
我觉得不需要太多背景知识,只要懂张量的概念,就足够了,具体怎么算的,也没必要研究,由搞数学的人来填坑,会用就行了,剩下的全是C语言知识了。
最近编辑记录 xboot (2022-02-23 10:29:14)
离线