ONNX是一种开放的深度学习模型交换格式,可让模型在不同平台和框架间无缝转换与部署,Paddle2ONNX开源仓库支持将飞桨的推理模型表示转换到ONNX算子协议以实现对接ONNX生态。飞桨在3.0Beta发布了新一代的中间表示(即Paddle IR),并升级了所有的算子定义形式,取代了2.x版本基于protobuf的中间表示。因此我们期望能够基于飞桨新一代Paddle IR的算子定义,升级Paddle2ONNX中的转换规则,支持Paddle IR 协议下的ONNX模型转换。
对于新增的算子,或者某算子不存在相关单测,则需要新增单测文件,可参考tests/test_auto_scan_matmul.py文件的实现方式,首先创建一个网络结构类Net并继承BaseNet,实现其forward函数,然后创建一个测试类,并继承OPConvertAutoScanTest,实现sample_convert_config方法和test方法。完成后再按照上述添加@_test_with_pir 即可
Note: 在对某算子对应的单测文件进行完善时,可能会遇到一种情况,该单测中不仅仅涉及你要支持的算子,还涉及其它算子,可以在日志中看到[Paddle2ONNX] There are some ops not supported yet, including xxx,此时需要一并支持其它未支持的算子。
1. 需求背景
ONNX是一种开放的深度学习模型交换格式,可让模型在不同平台和框架间无缝转换与部署,Paddle2ONNX开源仓库支持将飞桨的推理模型表示转换到ONNX算子协议以实现对接ONNX生态。飞桨在3.0Beta发布了新一代的中间表示(即Paddle IR),并升级了所有的算子定义形式,取代了2.x版本基于protobuf的中间表示。因此我们期望能够基于飞桨新一代Paddle IR的算子定义,升级Paddle2ONNX中的转换规则,支持Paddle IR 协议下的ONNX模型转换。
2. 当前进展
目前在Paddle2ONNX的
test_pir
分支已经完成了基本的机制建设,包括PIR下对模型文件的解析,输入输出变量对齐,算子的注册机制,获取算子输入、输出、属性,PIR下单测执行等。Resnet50在当前机制下可以正确转化为onnx模型文件,并通过了精度验证。3. 任务划分
Paddle2ONNX适配Paddle IR的模型转化任务按照算子级别进行划分
认领方式
填写Excel表进行认领 🚩任务认领登记表🚩
【P2O-PIR】
开头,具体要求请见【4.8 PR提交】任务要求
4. 开发流程
4.1 本地环境搭建
protobuf
paddle2onnx编译依赖protobuf,需要先在本地编译安装
paddlepaddle
需要安装paddle最新的日包,满足paddlepaddle>=3.0.0.dev20240923
paddle2onnx
4.2 本地环境验证
得到模型和参数文件
可通过转化resnet50模型进行测试
使用paddle2onnx转化
如果没有错误发生说明本地环境正常
4.3 明确模型中需要支持的算子列表
在当前版本中,保留了对模型Program打印的信息,因此,开始时可以先直接使用paddle2onnx进行转化,当然肯定会有一些问题,但是在输出的日志中可以看到打印的Program信息,可以根据此信息列举该模型使用的所有算子,并完成所有算子的【4.4算子注册】和【4.5单测完善】
4.4 算子注册
REGISTER_PIR_MAPPER
宏进行注册即可确定某算子在Paddle2ONNX中是否已经支持(即存在相应的mapper文件)的方法,以transpose算子为例:
_
结尾的算子xxx_
,其是xxx
算子的inplace版本,直接去查找xxx
算子是否已经支持即可REGISTER_MAPPER(transpose
,发现找不到完全匹配的/paddle/phi/ops/yaml/op_compat.yaml
文件中查找该算子名,如果在能够在其中找到,说明在新旧IR下算子名发生了变化,transpose
即属于这种情况,在op_compat.yaml
中可以看到其在旧IR下的名字是transpose2
REGISTER_MAPPER(transpose2
,找到完全匹配的,说明该transpose
的转化已经支持,不需要再新增对应的mapper,直接在PIR下注册即可4.5 单测完善
tests/
文件夹下,并以test_xxx.py
或者test_auto_scan_xxx.py
的方式命名,这种情况可以在相关的单测文件中加入from onnxbase import _test_with_pir
并在其中的以test
为开始的函数上添加@_test_with_pir
即可tests/test_auto_scan_matmul.py
文件的实现方式,首先创建一个网络结构类Net
并继承BaseNet
,实现其forward
函数,然后创建一个测试类,并继承OPConvertAutoScanTest
,实现sample_convert_config
方法和test
方法。完成后再按照上述添加@_test_with_pir
即可 Note: 在对某算子对应的单测文件进行完善时,可能会遇到一种情况,该单测中不仅仅涉及你要支持的算子,还涉及其它算子,可以在日志中看到[Paddle2ONNX] There are some ops not supported yet, including xxx
,此时需要一并支持其它未支持的算子。4.6 开发示例
可以参考以下PR提供的开发示例进行开发,在该PR中完成了算子xxx的注册,并对相关单测进行了完善。新旧IR下算子的输入、输出、属性等信息可能发生改变,需要适当修改算子的mapper文件
开发示例 PR#1403
算子注册
在头文件中重载PIR下的构造函数
可以看到上面注释了获取属性
axis
,sections
和num
,是因为在PIR下paddle.split
在模型结构中会以两种算子存在,一种是pd_op.split
,另一种是pd_op.split_with_num
,在pd_op.split 中
axis和
sections成为输入,
num属性不存在,在
pd_op.split_with_num中
axis是输入,
num是属性,而
sections`不存在在源文件中完成注册
检查源文件中的转化逻辑,主要根据PIR下算子的输入、输出、属性的变化来调整 主要包括检查
GetMinOpsetVersion
方法和Opset7
方法等,如果PIR下算子的输入、输出、属性有变化,需要进行修改。需要注意的是,如果不是新增的算子,GetInput
、GetOutput
、GetAttr
等方法中传入的变量或属性名使用旧IR下的即可,目前已经完成了自动映射的机制paddle2onnx/mapper/tensor/split.cc
中的变化单测完善
paddle2onnx/tests/
目录下找到算子对应的单测文件,一般命名为test_xxx.py
和test_auto_scan_xxx.py
,例如split算子的单测文件为tests/test_split.py
和tests/test_auto_scan_split.py
_test_with_pir
进行测试4.7 结果验证
保证算子的单测已完善并通过本地测试,以算子conv2d为例:
4.8 PR提交格式要求
【P2O-PIR】
开头,并写明适配的算子名称