Skip to content

[ONNX] Support Mod opset 28 - #32369

Open
Justin Chu (justinchuby) wants to merge 2 commits into
justinchuby-onnx-1-23-opset-28-basefrom
justinchuby-mod-opset-28
Open

Justin Chu (justinchuby) wants to merge 2 commits into
justinchuby-onnx-1-23-opset-28-basefrom
justinchuby-mod-opset-28

Conversation

@justinchuby

Copy link
Copy Markdown
Contributor

Summary

  • split CPU and CUDA Mod registrations into opsets 13-27 and 28
  • implement ONNX Mod-28 floating floor-mod semantics, including signed zero, infinities, NaNs, and mixed-sign operands
  • register DirectML's Python-compatible floor modulus for opset 28
  • cap QNN, CANN, MIGraphX, and OpenVINO Mod support at opset 27 so opset 28 falls back instead of advertising unverified semantics
  • preserve legacy behavior and harden signed integer min % -1

Stacked on #32359 / justinchuby-onnx-1-23-opset-28-base at checkpoint 92853202d4cb2bd7b9c20f1ba3abf1427980cf31.

Validation

  • Windows RelWithDebInfo CMake configuration completed against ONNX 1.23.0
  • focused floor-mod edge/reference formula validation passed
  • git diff --check passed
  • independent code review found no significant issues

A first-time local onnxruntime_test_all build was stopped after spending about an hour compiling unrelated dependencies; a provider-only compile was also gated on unfinished protobuf-generated headers. No changed-file compiler error was observed. CUDA and provider-specific builds remain for CI.

Add native CPU and CUDA floor-mod behavior, register DirectML support, and cap uncertified EPs at opset 27 fallback. Cover mixed signs, signed zero, infinities, NaNs, zero divisors, and signed overflow.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

CUDA’s integer fmod=1 path still performs undefined INT_MIN % -1 despite the new overflow hardening.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds ONNX Mod opset 28 semantics while preserving prior behavior and restricting unverified execution providers.

Changes:

  • Adds CPU/CUDA floating floor-mod implementations and edge-case tests.
  • Splits registrations at opset 28 and updates DirectML support.
  • Prevents unsupported providers from claiming Mod-28 nodes.
File summaries
File Description
onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc Adds Mod-28 semantic and overflow tests.
onnxruntime/core/providers/qnn/builder/opbuilder/mod_op_builder.cc Rejects Mod-28 partitioning.
onnxruntime/core/providers/openvino/ov_versions/data_ops.cc Excludes Mod-28 nodes.
onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc Excludes Mod-28 nodes.
onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorVersions.h Defines the Mod-28 version.
onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp Registers DirectML Mod-28.
onnxruntime/core/providers/cuda/math/binary_elementwise_ops.h Tracks Mod-28 floor-mod support.
onnxruntime/core/providers/cuda/math/binary_elementwise_ops.cc Splits registrations and dispatches floating floor-mod.
onnxruntime/core/providers/cuda/math/binary_elementwise_ops_impl.cu Instantiates floating Mod kernels.
onnxruntime/core/providers/cuda/cuda_execution_provider.cc Registers versioned CUDA kernels.
onnxruntime/core/providers/cuda/cu_inc/common.cuh Implements CUDA floor-mod and integer overflow handling.
onnxruntime/core/providers/cpu/math/element_wise_ops.cc Implements CPU Mod-28 semantics.
onnxruntime/core/providers/cpu/cpu_execution_provider.cc Registers versioned CPU kernels.
onnxruntime/core/providers/cann/cann_graph.cc Excludes Mod-28 nodes.
docs/OperatorKernels.md Documents updated registrations.
Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread onnxruntime/core/providers/cuda/cu_inc/common.cuh
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Om-singhaI

Copy link
Copy Markdown

Opset 28 is the first Mod spec whose text defines fmod=1 for integer types, and I think that makes an existing CPU precision bug newly relevant here.

BroadCastFMod computes each element as static_cast<T>(std::fmod(x, y)). For integral T both arguments promote to double, so int64 and uint64 stop being exact past 2^53. With divisor 10:

9007199254740991 -> 1   correct
9007199254740992 -> 2   correct
9007199254740993 -> 2   should be 3

uint64 18446744073709551613 % 10 gives 6 instead of 3. The same values at fmod=0 are exact, since Modulus uses x % y. CUDA _Fmod is also a % b for integers, so after this PR the CPU and CUDA paths disagree on int64 fmod=1, across two functions it touches.

Signed_integer_overflow_case_fmod covers that exact combination but only at int32, where the trip through double is lossless, so it passes either way. Routing integral T through x % y, with the same signed min guard you're adding to Modulus, would fix it, and an int64 dividend above 2^53 in that test would catch it.

To be clear about what I ran: I read the source at head and reproduced the numbers on the 1.23.2 wheel on CPU, where BroadCastFMod is byte identical to head. I haven't built this branch and haven't run anything on CUDA.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants