Heuristic:Onnx Onnx Opset Version Selection
| Knowledge Sources | |
|---|---|
| Domains | Model_Building, Compatibility |
| Last Updated | 2026-02-10 02:00 GMT |
Overview
Use an operator's `since_version` (minimum opset) for maximum runtime compatibility rather than the latest opset version.
Description
Every ONNX operator has a `since_version` field that records the earliest opset version in which it was introduced. When building models, you must choose which opset version to target. Using the latest opset version gives access to the newest operators and features, but limits compatibility with older ONNX runtimes. Using the minimum `since_version` for the operators in your graph maximizes backward compatibility. The ONNX version converter can convert models between opset versions, but not all conversions are lossless or possible, so choosing the right opset upfront avoids issues.
Usage
Use this heuristic when:
- Choosing an opset version for `onnx.helper.make_opsetid()` during model creation
- Exporting models for deployment on runtimes with older ONNX support
- Testing backend compliance where stable, reproducible test models are needed
- Converting between opset versions to understand what the minimum viable version is
The Insight (Rule of Thumb)
- Action: Use `onnx.helper.make_opsetid("", <target_version>)` with the lowest opset version that supports all operators in your model. Check `onnx.defs.get_schema(op_type).since_version` for each operator.
- Value: The VERSION_TABLE in `onnx/helper.py` maps ONNX release versions to IR versions and opset versions. Use this as a reference.
- Trade-off: Lower opset versions have broader runtime support but lack newer operators and optimizations. Higher opset versions have newer features but may not be supported by all runtimes.
Reasoning
The ONNX backend test suite itself follows this principle. When generating test models, it uses each operator's `since_version` by default rather than the latest opset. This ensures that test models remain stable and comparable across ONNX releases. The `use_max_opset_version` flag exists as an explicit opt-in for latest-version testing.
The version converter can adapt models between opset versions, but it relies on per-operator adapters. Not all operator changes have adapters, so some conversions may fail. It is safer to target the correct opset version during model creation than to rely on post-hoc conversion.
Code evidence from `onnx/backend/test/case/node/__init__.py:250-253`:
# Instead of creating model with latest version, it now generates
# models for since_version by default. Thus it can make every model
# uses the same opset version after every opset change. Besides, user
# can specify 'use_max_opset_version' to generate models for the
# latest opset version...
Version table from `onnx/helper.py:46-78`:
VERSION_TABLE: dict[int, tuple[int, int, int]] = {
# (ONNX release version): (IR version, ai.onnx version, ai.onnx.ml version)
# ...
}