-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Description
【快乐开源】Paddle2Torch API 转换功能开发
一、任务背景
PaddleAPITest 项目致力于确保 PaddlePaddle API 的正确性,这对 PaddlePaddle 框架的训练、推理和可靠性至关重要。该项目主要解决三个方面的正确性问题:API 精度、大张量计算和零尺寸张量支持。目前已经采集到 732 个 API 的 300 余万条配置,并进行了广泛的测试与适配,项目已初步建成,但仍有 100 多个 API 尚未支持精度对比测试。
Paddle2Torch 模块作为 PaddleAPITest 的关键组件,能够自动将 PaddlePaddle API 调用转换为对应的 PyTorch 实现,用于精度对比测试。
Paddle2Torch 模块是一个轻量级、解耦的工具,包含三个核心组件:
converter.py
:转换引擎,响应 Paddle API 调用并生成 PyTorch 代码mapping.json
:转换配置文件,定义 Paddle 到 PyTorch 的 API 映射关系rules.py
:转换规则文件,用于处理复杂的 API 转换
本任务的目标是修复未支持精度对比测试的 API,通过开发和扩展 API 转换能力来增强 Paddle2Torch 模块,以支持更广泛的 PaddlePaddle API 精度对比测试,确保语义一致性、实现强大的跨框架验证。现已释放 76+11+25 个 API 的转换功能开发任务!
这是开源贡献者们参与深度学习关键工具开发的绝佳机会,可促进学习模型迁移、跨框架验证和混合编程!!过程中参与者将会对 PaddlePaddle、PyTorch 的 API 更加熟悉!
二、任务清单
序号 | API 名称 | 认领人/状态/PR号 | 难度 |
---|---|---|---|
1 | paddle.assign |
@Cutelemon6 @HangFu7 |
⭐ |
2 | paddle.autograd.hessian |
@cangtianhuang |
⭐⭐⭐⭐ |
3 | paddle.autograd.jacobian |
@cangtianhuang |
⭐⭐⭐⭐ |
4 | paddle.binomial |
@Cutelemon6 |
⭐⭐⭐ |
5 | paddle.cartesian_prod |
@yuwu46 |
⭐⭐⭐ |
6 | paddle.geometric.segment_mean |
@yuwu46 |
⭐⭐⭐ |
7 | paddle.geometric.segment_min |
@yuwu46 |
⭐⭐⭐ |
8 | paddle.geometric.segment_sum |
@yuwu46 |
⭐⭐ |
9 | paddle.geometric.send_u_recv |
@cszdrg |
⭐⭐⭐⭐⭐ |
10 | paddle.geometric.send_ue_recv |
@cszdrg |
⭐⭐⭐⭐⭐ |
11 | paddle.geometric.send_uv |
@yuwu46 |
⭐⭐⭐⭐⭐ |
12 | paddle.histogram_bin_edges |
@cszdrg |
⭐⭐⭐ |
13 | paddle.incubate.nn.functional.blha_get_max_len |
@yuwu46 |
⭐⭐⭐⭐⭐⭐ |
14 | paddle.incubate.nn.functional.block_multihead_attention |
@cangtianhuang @Cutelemon6 |
⭐⭐⭐⭐⭐ |
15 | paddle.incubate.nn.functional.fused_bias_act |
@cangtianhuang |
⭐⭐⭐⭐⭐ |
16 | paddle.incubate.nn.functional.fused_bias_dropout_residual_layer_norm |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
17 | paddle.incubate.nn.functional.fused_dropout_add |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
18 | paddle.incubate.nn.functional.fused_feedforward |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
19 | paddle.incubate.nn.functional.fused_layer_norm |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
20 | paddle.incubate.nn.functional.fused_linear |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
21 | paddle.incubate.nn.functional.fused_linear_activation |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
22 | paddle.incubate.nn.functional.fused_matmul_bias |
@cangtianhuang |
⭐⭐⭐⭐⭐ |
23 | paddle.incubate.nn.functional.fused_multi_head_attention |
@cangtianhuang |
⭐⭐⭐⭐⭐ |
24 | paddle.incubate.nn.functional.fused_rms_norm |
@cangtianhuang |
⭐⭐⭐⭐⭐ |
25 | paddle.incubate.nn.functional.fused_rotary_position_embedding |
@cangtianhuang |
⭐⭐⭐⭐⭐ |
26 | paddle.incubate.nn.functional.masked_multihead_attention |
@cangtianhuang |
⭐⭐⭐⭐⭐ |
27 | paddle.incubate.nn.functional.swiglu |
@Cutelemon6 |
⭐⭐⭐⭐⭐ |
28 | paddle.incubate.nn.functional.variable_length_memory_efficient_attention |
@cangtianhuang |
⭐⭐⭐⭐⭐⭐ |
29 | paddle.incubate.segment_max |
@cangtianhuang |
⭐⭐⭐ |
30 | paddle.incubate.segment_mean |
@cangtianhuang |
⭐⭐⭐ |
31 | paddle.incubate.segment_min |
@cangtianhuang |
⭐⭐⭐ |
32 | paddle.incubate.segment_sum |
@cangtianhuang |
⭐⭐⭐ |
33 | paddle.incubate.softmax_mask_fuse |
@cangtianhuang |
⭐⭐⭐⭐ |
34 | paddle.incubate.softmax_mask_fuse_upper_triangle |
@cangtianhuang |
⭐⭐⭐⭐ |
35 | paddle.index_add |
@mzj104 |
⭐⭐ |
36 | paddle.index_put |
@mzj104 |
⭐⭐⭐ |
37 | paddle.index_sample |
@mzj104 |
⭐⭐ |
38 | paddle.log_normal |
@mzj104 |
⭐⭐ |
39 | paddle.masked_scatter |
@mzj104 |
⭐⭐⭐ |
40 | paddle.matmul |
@ccsuzzh |
⭐ |
41 | paddle.multinomial |
@ccsuzzh |
⭐ |
42 | paddle.nn.functional.adaptive_avg_pool2d |
@cangtianhuang |
⭐⭐ |
43 | paddle.nn.functional.adaptive_avg_pool3d |
@cangtianhuang |
⭐⭐ |
44 | paddle.nn.functional.pixel_shuffle |
@yuwu46 |
⭐⭐⭐ |
45 | paddle.nn.functional.pixel_unshuffle |
@yuwu46 |
⭐⭐⭐ |
46 | paddle.nn.functional.prelu |
@yuwu46 |
⭐ |
47 | paddle.nn.functional.selu |
@yuwu46 |
⭐ |
48 | paddle.nn.quant.weight_only_linear |
@cszdrg |
⭐⭐⭐⭐ |
49 | paddle.nn.quant.weight_quantize |
@cszdrg |
⭐⭐⭐⭐ |
50 | paddle.signal.stft |
@yuwu46 |
⭐⭐ |
51 | paddle.slice_scatter |
@mzj104 |
⭐⭐⭐ |
52 | paddle.standard_gamma |
@mzj104 |
⭐⭐ |
53 | paddle.standard_normal |
@mzj104 |
⭐⭐ |
54 | paddle.stanh |
@mzj104 |
⭐⭐ |
55 | paddle.strided_slice |
@mzj104 |
⭐⭐ |
56 | paddle.subtract |
@mzj104 |
⭐ |
57 | paddle.take |
@mzj104 |
⭐⭐ |
58 | paddle.Tensor.__len__ |
@HangFu7 |
⭐ |
59 | paddle.Tensor.__lshift__ |
@Cutelemon6 |
⭐⭐ |
60 | paddle.Tensor.__neg__ |
@Cutelemon6 |
⭐ |
61 | paddle.Tensor.__nonzero__ |
@Cutelemon6 |
⭐ |
62 | paddle.Tensor.__or__ |
@Cutelemon6 |
⭐ |
63 | paddle.Tensor.__rlshift__ |
@mzj104 |
⭐⭐ |
64 | paddle.Tensor.__ror__ |
@mzj104 |
⭐ |
65 | paddle.Tensor.__rrshift__ |
@mzj104 |
⭐⭐ |
66 | paddle.Tensor.__rxor__ |
@mzj104 |
⭐ |
67 | paddle.Tensor.__xor__ |
@mzj104 |
⭐ |
68 | paddle.Tensor.bernoulli_ |
@yuwu46 |
⭐ |
69 | paddle.Tensor.cast |
@yuwu46 |
⭐ |
70 | paddle.Tensor.cauchy_ |
@yuwu46 |
⭐⭐ |
71 | paddle.Tensor.fill_diagonal_tensor |
@yuwu46 |
⭐⭐ |
72 | paddle.Tensor.slice_scatter |
@yuwu46 |
⭐⭐⭐ |
73 | paddle.unstack |
@yuwu46 |
⭐ |
74 | paddle.vander |
@yuwu46 |
⭐⭐ |
75 | paddle.vecdot |
@yuwu46 |
⭐⭐ |
76 | paddle.view_as |
@yuwu46 |
⭐ |
77 | paddle.Tensor.argmax |
@inaomIIsfarell @Cutelemon6 |
⭐ |
78 | paddle.argmax |
@inaomIIsfarell @Cutelemon6 |
⭐ |
79 | paddle.full |
@Cutelemon6 |
⭐ |
80 | paddle.full_like |
@Cutelemon6 |
⭐ |
81 | paddle.linspace |
@Cutelemon6 |
⭐ |
82 | paddle.logcumsumexp |
@Cutelemon6 |
⭐⭐ |
83 | paddle.logspace |
@Cutelemon6 |
⭐ |
84 | paddle.nn.functional.sequence_mask |
@cszdrg |
⭐⭐⭐ |
85 | paddle.ones_like |
@yuwu46 |
⭐ |
86 | paddle.sum |
@cangtianhuang |
⭐ |
87 | paddle.zeros_like |
@yuwu46 |
⭐ |
88 | paddle.argmin |
@mzj104 |
⭐ |
89 | paddle.chunk |
@mzj104 |
⭐ |
90 | paddle.clip |
@cszdrg |
⭐ |
91 | paddle.cumsum |
@mzj104 |
⭐ |
92 | paddle.diag |
@mzj104 |
⭐ |
93 | paddle.eye |
@mzj104 |
⭐ |
94 | paddle.linalg.cov |
@yuwu46 @superdonkey007 |
⭐⭐⭐ |
95 | paddle.linalg.lstsq |
@superdonkey007 |
⭐⭐ |
96 | paddle.linalg.norm |
@superdonkey007 |
⭐ |
97 | paddle.mm |
@mzj104 |
⭐ |
98 | paddle.nn.functional.affine_grid |
@yuwu46 |
⭐ |
99 | paddle.nn.functional.grid_sample |
@yuwu46 |
⭐ |
100 | paddle.outer |
@mzj104 |
⭐ |
101 | paddle.quantile |
@mzj104 |
⭐⭐ |
102 | paddle.reshape |
@cszdrg |
⭐ |
103 | paddle.roll |
@yuwu46 |
⭐ |
104 | paddle.sign |
@yuwu46 |
⭐ |
105 | paddle.squeeze |
@yuwu46 |
⭐ |
106 | paddle.take_along_axis |
@yuwu46 |
⭐ |
107 | paddle.Tensor.clip |
@cszdrg |
⭐ |
108 | paddle.Tensor.matmul |
@mzj104 |
⭐ |
109 | paddle.tensordot |
@mzj104 |
⭐ |
110 | paddle.tile |
@yuwu46 |
⭐ |
111 | paddle.unflatten |
@cszdrg |
⭐⭐ |
112 | paddle.unsqueeze |
@yuwu46 |
⭐ |
【腾讯文档】Paddle2Torch API 转换功能开发(此处为总统计表,已有多位同学完成 API 转换功能开发,上次更新:6/8)
同学们可查看该文档中的已贡献 PR,学习了解本活动~
三、任务详情
Paddle2Torch 模块通过解析 PaddlePaddle API 调用,使用预定义的转换规则与动态代码生成,实现从 PaddlePaddle 到 PyTorch 的自动转换,转换过程需确保代码的语义一致性。
Paddle2Torch 模块的工作原理是:
- 读取 mapping.json 配置,加载 rules.py 中所有 Rule 类,形成 API 与 Rule 的映射字典(默认为 GenericRule 类)
- 根据输入的 API 信息执行相应 Rule 的 apply 方法,获取转换结果和需要执行的代码行列表(字符串形式的代码)
- 传入测试配置的具体参数,使用 exec() 执行对应代码,返回最终结果
经过归纳总结,PaddlePaddle 到 PyTorch 的 API 转换情况可分为 8 类:
- 第1类为
API 可直接映射
,最简单的情况,包括:无参数、参数完全一致、仅参数名不一致 - 第2类为
参数默认值不一致
,一般可直接映射,但需注意设置 torch 参数默认值 - 第3类为
仅 torch 参数更多
,如果使用 torch 的部分参数可以完整表达,就直接映射,但需注意设置 torch 参数默认值 - 第4类为
仅 paddle 参数更多
,一般无法直接映射(会丢失信息) - 第5类为
torch 和 paddle 都支持更多参数
,情形与仅 paddle 参数更多
类似(不考虑 torch 多的参数) - 第6类为
参数用法不一致
,无法直接映射,如:参数类型不一致、参数含义不一致、返回参数类型不同 - 第7类为
没有对应 API
,无法直接映射,但可通过 组合替代实现(通过多个 API 组合实现)、自定义规则(撰写 torch 代码)方法解决 - 第8类为
功能缺失
,完全无法或很难使用 torch 表达当前 API 的功能,不进行转换
需要说明的是,我们仅关心能否使用 Torch API 完整地模拟出 Paddle API 的表现,在非常功利的视角下,我们仅需关注 Torch 的执行结果!
Paddle2Torch 模块的内核机制提供以下的转换方案:
- 读取 mapping.json,直接进行 API 映射,解决第1类与部分第2、3类 API
- 读取 mapping.json,直接进行 API 映射的同时,手动设置 torch 的部分 args 与 kwargs,解决部分第2-7类问题
- 读取 mapping.json 的 Rule 注册,加载 rules.py 中相应的 Rule 规则,将 API 分配给指定的 Rule 类执行,解决剩余的第2-7类问题
在任务开发过程中,需要完成以下步骤。更详细的开发指南请参考 Paddle2Torch README#贡献指南。
1. 在 mapping.json 中编写转换配置
如果 PaddlePaddle API 有直接对应的 PyTorch API,可采用 直接映射 的方法。需在 mapping.json 的相应条目(去掉 paddle. 后的字典序)下编写转换配置,编写规则为:
"<api_name>": {
"torch_api": "torch api 名称",
"set_defaults":{
"_description1": "默认值设置字典,键为参数名,值为默认值",
"_description2": "建议参考官方文档设置默认值,不会覆盖已有参数值,功能等效于 var = locals().get('var', value)"
},
"paddle_torch_args_map": {
"_description": "参数名映射字典,键对应 paddle,值对应 torch",
},
"torch_args": [
"torch api 位置参数列表, 变量名可使用 {} 环绕,字符串的引号请使用 \\ 转义,可以直接设为常值"
],
"torch_kwargs": {
"_description": "torch api 关键字参数字典,与 torch_args 类似"
}
}
如果 PaddlePaddle API 没有直接对应的 PyTorch API,或者无法直接映射(Paddle 参数更多、参数用法不同等),应采用 规则映射 的方法,编写转换规则。既需要在 mapping.json 中注册,也需要在 rules.py 中定义类。注册规则为:
"<api_name>": {
"Rule": "自定义 Rule 类的类名"
}
此外,也可以添加更多的常规配置,以减少 Rule 类代码的编写量(需要在 Rule 类中主动调用 apply_generic() 方法,返回 defaults_code 与 map_code ):
"<api_name>": {
"Rule": "自定义 Rule 类的类名",
"torch_api": "torch api 名称",
"set_defaults":{
"_description1": "默认值设置字典,键为参数名,值为默认值",
"_description2": "建议参考官方文档设置默认值,不会覆盖已有参数值,功能等效于 var = locals().get('var', value)"
},
"paddle_torch_args_map": {
"_description": "参数名映射字典,键对应 paddle,值对应 torch"
}
}
以 paddle.nn.functional.conv1d 的转换配置为例:
"paddle.nn.functional.conv1d": {
"Rule": "Conv1dRule",
"torch_api": "torch.nn.functional.conv1d",
"set_defaults": {
"bias": "None",
"stride": 1,
"padding": 0,
"dilation": 1,
"groups": 1,
"data_format": "'NCL'"
},
"paddle_torch_args_map": {
"x": "input",
"weight": "weight",
"bias": "bias",
"stride": "stride",
"padding": "padding",
"dilation": "dilation",
"groups": "groups"
}
},
2. 在 rules.py 中编写转换规则代码
Rule 类的定义需要继承自抽象基类 BaseRule,并实现 apply() 方法,否则无法执行转换。基类定义为:
class BaseRule(ABC):
"""转换规则的抽象基类"""
@abstractmethod
def apply(self, paddle_api: str) -> ConvertResult:
pass
以 paddle.nn.functional.conv1d 的转换规则为例:
class Conv1dRule(BaseRule):
def apply(self, paddle_api: str) -> ConvertResult:
defaults_code, map_code = self.apply_generic()
pre = """
if data_format == "NLC":
x = x.permute(0, 2, 1)
stride = tuple(stride) if isinstance(stride, list) else stride
dilation = tuple(dilation) if isinstance(dilation, list) else dilation
if isinstance(padding, str):
if padding.lower() == "same":
padding = "same"
elif padding.lower() == "valid":
padding = "valid"
elif isinstance(padding, list):
if len(padding) == 2:
pad_left, pad_right = padding
x = torch.nn.functional.pad(x, (pad_left, pad_right))
padding = 0
else:
padding = tuple(padding)
"""
core = f"result = {self.torch_api}(**_kwargs)"
post = """
if data_format == "NLC":
result = result.permute(0, 2, 1)
"""
code = Code(
preprocess=defaults_code + pre.splitlines() + map_code,
core=[core],
postprocess=post.splitlines(),
)
return ConvertResult.success(paddle_api, code)
更详细的 Rule 编写指南可参考 Paddle2Torch README#高级Rule指南。
3. 测试转换结果
在 PaddleAPITest 项目 tester/api_config
路径下搜索 API 名称,将所有 api_config_merged_*.txt
文件内的相关测试配置移至临时文件中,然后运行 accuracy 测试命令:
python engineV2.py --accuracy=True --api_config_file="tester/api_config/temp.txt" >> "tester/api_config/test_log/log.log" 2>&1
测试结果将位于 tester/api_config/test_log
文件夹中。若全部 pass,请将配置合并至通过 accuracy 测试的 tester/api_config/api_config_support2torch_*.txt
中(递增认领一个文件);如果有 torch_error、paddle_error 或 accuracy_error,请进一步定位是否是转换出错,亦或是 PaddleAPITest 引擎问题、PaddlePaddle 问题 或 PyTorch 问题,前者请尝试仔细阅读文档,或寻求项目开发者帮助。
如果确认是引擎问题,请 @cangtianhuang 进行反馈;其他情况请在 report/fresh_report/accuracy
中记录错误配置、报错信息,并将配置合并至未通过精度测试的 tester/api_config/api_config_accuracy_error_*.txt
中(递增认领一个文件)
四、如何开始
1. 克隆仓库
访问 https://github.com/PFCCLab/PaddleAPITest ,点击右上角的 “Fork” 按钮,将仓库 fork 到你自己的 GitHub 账号下,进行本地分支开发
git clone https://github.com/YOUR_USERNAME/PaddleAPITest.git
cd PaddleAPITest
git remote add upstream https://github.com/PFCCLab/PaddleAPITest.git
git checkout -b develop main
2. 配置环境
建议在虚拟环境或 docker 中开发(需先安装 paddlepaddle-gpu 再安装 torch,否则会报错,重新安装请添加 --force-reinstall )
pip install --pre paddlepaddle-gpu -i https://www.paddlepaddle.org.cn/packages/nightly/cu118/
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install func_timeout pebble pynvml
3. 任务认领
Important
请务必严格按照格式填写,否则快乐开源小助手无法自动更新信息
请大家在 issue 下以 comment 的形式认领任务,否则不会正确报名,格式如下:
【报名】: 1、2、3-5
多个任务之间使用中文顿号分隔,多个连续任务可用横线表示
4. 提交 PR
// ------- PR 标题 --------
[P2T support No.xxx]+API名称
// ------- PR 内容 --------
## 转换能力补齐
### [API 名称]
[描述转换所属情况,具体转换方案]
## 测试结果
[描述配置测试结果,处理与截图]
- https://github.com/PaddlePaddle/Paddle/issues/72643
@cangtianhuang 和 @wanghuancoder
五、参考文档 和 PR 示例
请务必查阅 API 文档:
README:
百度同学可查阅:
PR 示例:
- 【BIT】转换能力补齐+引擎修复:increment、scale、Tensor.scale、searchsorted、shape、meshgrid PFCCLab/PaddleAPITest#115
- 【BIT】转换能力补齐:paddle.nn.functional.max_pool[1 2 3]d PFCCLab/PaddleAPITest#108
- 【BIT】转换能力补齐:paddle.nn.functional.conv[1 2 3]d PFCCLab/PaddleAPITest#103
看板信息
任务方向 | 任务数量 | 提交作品 / 任务认领 | 提交率 | 完成 | 完成率 |
---|---|---|---|---|---|
转换功能开发 | 112 | 112 / 112 | 100.0% | 112 | 100.0% |
统计信息
排名不分先后 @Cutelemon6 (20) @cangtianhuang (19) @yuwu46 (31) @cszdrg (10) @mzj104 (27) @ccsuzzh (2) @HangFu7 (1) @superdonkey007 (2)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status