Skip to content

[PIR] linear_v2 / group_norm / layer_norm 算子导出失败 — PIR 位置索引无命名映射 #1644

Description

@PlumBlossomMaid

Describe the bug

PIR 格式下三个基础算子 linear_v2 / group_norm / layer_norm 无法正常导出 ONNX。

Bug A: nn.Linearlinear_v2 无 mapper

PIR 3.x 格式将 nn.Linear 融合为单一算子 pd_op.linear_v2,但 paddle2onnx 源码中没有任何 linear* 的 mapper 文件(旧格式下 Linear 被分解为 mul + elementwise_add 两个旧算子,因此不需要独立 mapper)。

使用 paddle2onnx 2.1.0(PyPI)或源码 commit 1877292 均无法导出含 nn.Linear 的模型。

Bug B: nn.GroupNorm → PIR 模式不兼容

已有 REGISTER_PIR_MAPPER(group_norm, GroupNormMapper),但两个问题:

  1. GetInput("X") / GetInput("Scale") / GetInput("Bias") 在 PIR 模式下无 OpNameNormalizer 映射,返回空
  2. PIR 格式输入为 3D [N, C, L],ONNX InstanceNormalization 要求 4D [N, C, H, W]

Bug C: nn.LayerNorm → PIR 模式下 Scale/Bias 被忽略

HasInput("Scale")HasInput("Bias") 在 PIR 模式下返回 false(同样因为无命名映射),导致 LayerNorm 实际的 weight/bias 参数被忽略,使用全 1/全 0 常量替代,推理结果完全错误。

Root Cause

所有三个 bug 的共同根因:PIR 格式算子的输入是位置索引I[0], I[1], I[2]),而非命名映射("X", "Weight", "Scale")。GetInput("X") 内部调用 GetOpInputOutputName2Idx 通过 OpYamlInfoInterface 解析算子参数名,但这三个算子在 OpNameNormalizer 中没有对应的 PIR 参数名映射,返回 -1 导致空结果。

Reproduction

import paddle
import paddle.nn as nn
from paddle.static import InputSpec

# Bug A: nn.Linear
model = nn.Linear(64, 128).eval()
sm = paddle.jit.to_static(model,
    input_spec=[InputSpec([1, 64], 'float32', 'x')],
    full_graph=True)
paddle.jit.save(sm, '/tmp/linear_model')

然后用 paddle2onnx 导出:

paddle2onnx --model_dir /tmp/linear_model ...

→ SIGABRT / unsupported operators

# Bug B: nn.GroupNorm
model = nn.GroupNorm(4, 64).eval()

→ "There are unsupported features"

# Bug C: nn.LayerNorm
class M(nn.Layer):
    def __init__(self):
        super().__init__()
        self.w = self.create_parameter([64, 128])
        self.b = self.create_parameter([128])
        self.ln = nn.LayerNorm(128)
    def forward(self, x):
        return self.ln(paddle.matmul(x, self.w) + self.b)

→ ONNX output is all-zero because Scale/Bias are ignored

Fix (PR prepared)

  • 新增 paddle2onnx/mapper/nn/linear_v2.hlinear_v2.cc:将 linear_v2 分解为 MatMul + Add,PIR 模式下使用位置索引 GetInput(0)/GetInput(1)/GetInput(2)
  • 修改 paddle2onnx/mapper/nn/group_norm.cc:PIR 位置索引 + 3D→4D Unsqueeze→InstanceNormalization→Squeeze
  • 修改 paddle2onnx/mapper/nn/layer_norm.cc:PIR 位置索引读取 Scale/Bias
  • 修改 paddle2onnx/mappers_registry.h.in:注册 linear_v2

Informations (please complete the following information):

  • Inference engine for deployment: ONNX Runtime (CPU/CUDA)
  • Why convert to onnx: Model deployment
  • Paddle2ONNX Version: 2.1.0 (PyPI) & source commit 1877292
  • PaddlePaddle Version: 3.5.0.dev20260614
  • OS: Ubuntu 22.04

Screenshots

N/A

Additional context

N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions