Skip to content

ONNX gelu float16 标量常量导致 pass_level3 崩溃 (std::map::at) #6817

Description

@dawnwtc

error log

error_log.md

context | 编译/运行环境 |

  • PNNX 版本:20260526(pip install pnnx)
  • 系统:Ubuntu 22.04
  • PyTorch:2.13.0

how to reproduce | 复现步骤

单个 GELU 算子导出 ONNX,float16 精度即可复现:

import torch, torch.nn as nn
m = nn.GELU().to(torch.float16).eval()
x = torch.randn(1, 16, 16, 16, dtype=torch.float16)
torch.onnx.export(m, x, 'gelu_f16.onnx',
    input_names=['a'], output_names=['b'],
    opset_version=18, dynamo=True)
pnnx gelu_f16.onnx optlevel=2

而 float32 的同样模型正常:

# 把上面脚本里 float16 改成 float32,重新导出
pnnx gelu_f32.onnx optlevel=2  # ✅ 正常通过

根因定位

第 1 步:加载 ONNX 标量常量时,pass_onnx.cpp 约第 1010–1026 行:

// INT32、INT64、FLOAT、BOOL 都有对应的分支,会设置 params["value"]
else if (tensor.data_type() == onnx::TensorProto::BOOL)
{
    op_const->params["value"] = ...;  //
}
else
{
    // FLOAT16 落到了这里
    fprintf(stderr, "unknown constant scalar type %d\n", ...);
    // 只打了个 warning,params["value"] 没有被设置!
}

此时 prim::Constant 节点已经创建,但缺少 "value" 参数。GELU 公式中的 0.5、1.0、√2 等标量全部变成了这种「空壳」Constant。

第 2 步pass_level3/eliminate_noop_math.cpp 第 15 行:

static bool constant_is_all_constant(const Operator* op_constant, ...)
{
    const Parameter& param = op_constant->params.at("value");  // ← 崩溃!
    // "value" 这个 key 不存在 → std::map::at 抛 std::out_of_range

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