Partial rotary fusion sets `rotary_embedding_dim` without `num_heads`, which ONNX Runtime requires
维护者通常 2 天内回复
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 25/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 停滞
- 技术栈
- python
调研方向
Read PartialRotaryEmbeddingFusion.rewrite in the rotary embedding fusion implementation and inspect the linked pull request #3186. The repro in this issue shows that fusion creates a RotaryEmbedding with rotary_embedding_dim but no num_heads; use it to check the failure. Done means the fused model runs in ONNX Runtime with the expected head count.
由索引模型根据 Issue 内容生成。
描述
PartialRotaryEmbeddingFusion.rewrite (fuse_partial_rotary_embedding, run by optimize_for_ort) rebuilds ONNX Runtime's RotaryEmbedding over the whole head with rotary_embedding_dim set, but keeps the original node's attributes, which have no num_heads. ONNX Runtime requires num_heads whenever rotary_embedding_dim is set, so a model rotating only part of each head (GPT-NeoX's rotary_pct) runs before the fusion and fails after it. We hit it on GPT-NeoX. Setting num_heads in the rewrite (axis 1 of a 4D input) would fix it.
Repro (onnxscript 0.7.2, onnx-ir 1.1.0, onnxruntime 1.31.1):
"""onnxscript's partial rotary fusion (`fuse_partial_rotary_embedding`, part of `optimize_for_ort`) rebuilds
ONNX Runtime's `RotaryEmbedding` with `rotary_embedding_dim` but without `num_heads`, which ONNX Runtime requires
alongside it: a model rotating part of each head (GPT-NeoX's) runs before the fusion and fails after it."""
import numpy as np
import onnx_ir as ir
import onnxruntime as ort
import onnxscript
from onnx import TensorProto, helper, numpy_helper
from onnxscript.rewriter.ort_fusions.rotary_embedding import fuse_partial_rotary_embedding
B, H, S, D, ROTARY = 2, 4, 5, 16, 4
constants = {
"zero": [0], "rotary": [ROTARY], "end": [np.iinfo(np.int64).max], "axis": [3], "step": [1],
}
initializers = [numpy_helper.from_array(np.array(value, np.int64), name) for name, value in constants.items()]
rng = np.random.default_rng(0)
initializers += [numpy_helper.from_array(rng.standard_normal((S, ROTARY // 2)).astype(np.float32), name) for name in ("cos", "sin")]
graph = helper.make_graph(
[
helper.make_node("Slice", ["x", "zero", "rotary", "axis", "step"], ["rotated_part"]),
helper.make_node("Slice", ["x", "rotary", "end", "axis", "step"], ["passed_part"]),
helper.make_node("RotaryEmbedding", ["rotated_part", "positions", "cos", "sin"], ["rotated"], domain="com.microsoft"),
helper.make_node("Concat", ["rotated", "passed_part"], ["y"], axis=-1),
],
"g",
[helper.make_tensor_value_info("x", TensorProto.FLOAT, [B, H, S, D]), helper.make_tensor_value_info("positions", TensorProto.INT64, [B, S])],
[helper.make_tensor_value_info("y", TensorProto.FLOAT, [B, H, S, D])],
initializers,
)
proto = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 18), helper.make_opsetid("com.microsoft", 1)], ir_version=10)
feeds = {"x": rng.standard_normal((B, H, S, D)).astype(np.float32), "positions": np.tile(np.arange(S), (B, 1))}
def run(model) -> str:
try:
session = ort.InferenceSession(ir.to_proto(model).SerializeToString(), providers=["CPUExecutionProvider"])
return f"runs, y[0, 0, 1, :4] = {session.run(None, feeds)[0][0, 0, 1, :4]}"
except Exception as error:
return f"fails: {str(error).splitlines()[0].split('was false. ')[-1]}"
ort.set_default_logger_severity(3)
print("onnxscript", onnxscript.__version__, "| onnx_ir", ir.__version__, "| onnxruntime", ort.__version__)
model = ir.from_proto(proto)
print("original:", run(model))
print("fuse_partial_rotary_embedding:", fuse_partial_rotary_embedding(model), "fusion(s)")
rotary = next(node for node in model.graph if node.op_type == "RotaryEmbedding")
print("fused attributes:", {name: attribute.value for name, attribute in rotary.attributes.items()})
print("fused:", run(model))
Output:
[m
onnxscript 0.7.2 | onnx_ir 1.1.0 | onnxruntime 1.31.1
original: runs, y[0, 0, 1, :4] = [1.4040405 0.3131538 2.0222473 0.18501948]
fuse_partial_rotary_embedding: 1 fusion(s)
fused attributes: {'rotary_embedding_dim': 4}
fused: fails: num_heads must be provided if rotary_embedding_dim is specified
- 主要语言
- Python
- 星标
- 456
- 派生
- 159
- 平均合并
- 3 天 5 小时
- 30 天内合并 PR
- 23
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
microsoft/onnxscript 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
microsoft/onnxscript#3200 ·
维护者通常 2 天内回复
-
`fuse_skip_rms_normalization` fuses a float16 residual into a norm whose scale is float32, which ONNX Runtime rejects可能已有人在做 @justinchuby 于 8 天前认领。 未关闭module: optimizer
难度 2/5 1-3 小时 新手友好度 76/100
microsoft/onnxscript#3155 · 3 条评论 · 1 个 reaction · 已指派 2 人 ·
维护者通常 2 天内回复
-
Constant folding uses onnx's plain reference ops, never onnx.reference.ops_optimized可能已有人在做 @todkarsant 于 8 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
microsoft/onnxscript#3003 · 3 条评论 ·
维护者通常 2 天内回复
-
CI : Pin github actions to full commit SHA可能已有人在做 @Aniketsy 于 193 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 68/100
microsoft/onnxscript#2903 · 6 条评论 ·
维护者通常 2 天内回复
-
CastCast rewrite changes rounding for DOUBLE inputs by removing the FLOAT intermediate可能已有人在做 @itsrayeedscodespace 于 1 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 35/100
microsoft/onnxscript#3204 ·
维护者通常 2 天内回复
查看 microsoft/onnxscript 的全部 Issue
相似的 Issue
-
fleet size/m
难度 2/5 1-3 小时 新手友好度 78/100
sipyourdrink-ltd/bernstein#7548 ·
维护者通常 1 天内回复
-
good first issue help wanted level 1 wocs
难度 2/5 1-3 小时 新手友好度 82/100
GianlucaBave/murmury#73 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
G-nn-r/lg_heatpump#52 ·
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
category:codebase:gpi category:codebase:handle type:bug
难度 2/5 1-3 小时 新手友好度 74/100
维护者通常 1 天内回复