Txing

欢迎来到 | 伽蓝之堂

0%

onnx转换踩坑记录

1. 背景

前期我们利用torch框架实现了一个python版本的轨迹预测模型,经过近1个月的训练样本迭代,形成了一个性能基本稳定的模型版本。之后我们尝试将这个python模型转为onnx模型进行工程部署,遇到了很多问题,在此做个踩坑记录。

2. 问题

2.1 如何转为onnx模型

  • 报错显示被覆盖

    log显示有行数限制,转换报错后看不到具体报错内容;可直接导出全部log信息到本地进行查看

    1
    Python torch_to_onnx.py > error.log 2>&1
  • opset和torch版本

    根据工程部门要求设置对应的 opset 和 torch 版本,修改 torch 版本可能涉及修改模型结构,会相对繁琐,opset 直接修改版本号后尝试运行即可;

  • c++算子修改

    模型代码中涉及一部分结构使用c++编译实现,在进行ONNX转换的时候需要将这部分功能用Python重新实现,相关修改可能会降低程序运行效率;

  • argsort()算子用topk()替代

    ONNX模型不支持argsort()操作,需要使用其它算子进行等效替换,这里推荐使用topk()进行替换;

  • layernorm算子不支持

    首先需要明白layernorm的作用,layernorm是对每个样本的特征进行归一化,batchnorm是对每个batch的样本进行归一化;

    layernorm算子不影响ONNX模型的导出,但是会影响后续模型的转换,需要去除网络中的layernorm层;这一步肯呢个降低模型指标,可以尝试在训练的时候添加layernorm但在转换onnx模型的时候去除layernorm;

2.2 转qualcomm平台的问题

  • nonzero算子不支持

    加mask操作不支持,与tensor对应元素的检索方式有关,去除mask相关语句,如traj[traj_mask]

  • scatterND算子不支持

    每个Tensor的索引不可缺省,检索的时候需要补全;维度索引缺省不支持;

  • Gather算子不支持

    tensor类型不匹配,相应数据类型改为torch.float即可;

2.3 算力与内存

  • 算力的定义

    • 算力的概念可以理解为机器每秒进行多少次操作,一般使用单位TOPS(Tera Operations Per Second),1TOPS表示每秒进行10^12次计算;

    • FLOPS与OPS类似,OPS表示的是操作次数,而FLOPS是浮点操作次数;

    • 单位换算:

      • 1 PFLOPS = 1024 TFLOPS (T的数量级10^12)
      • 1 TFLOPS = 1024 GFLOPS (G的数量级10^9)
      • 1 GFLOPS = 1024 MFLOPS (M的数量级10^6)
  • onnx测算力的方法

    测算力需要使用专门的onnx tools,因此要先完成Python模型到onnx模型的转换;

    转换完成后,得到.onnx模型文件,然后执行以下代码:

    1
    2
    3
    import onnx_tool
    modelpath = "onnx_data/torch_v1_9_0_v1_3.onnx"
    onnx_tool.model_profile(modelpath, savenode='node_table_v1_3.csv') # save profile table to txt file

    执行完成后得到.csv文件,文件内容为整个网络中每个算子的输入输出size和消耗的计算量;

  • onnx算力和内存的表示

    csv文件中浮点计算量MACs指累加数量(1 MAC=2 FLOPs),内存计算单位是bytes,参数单位是元素个数;所以,得到MAC是算力后需要乘以2,换算为FLOPs的单位;

    1
    2
    3
    4
    1 B(bytes) = 8 b(位)
    1 KB = 1024 B
    1 MB = 1024 KB
    1 GB = 1024 MB