Repository navigation
Sync with Microsoft ONNX Runtime - 31102026 - #1376
Open
ai-fw-intg wants to merge 18 commits into
Open
ai-fw-intg wants to merge 18 commits into
ai-fw-intg wants to merge 18 commits into
Conversation
…e and 4-lane warp-shuffle decode epilogue (microsoft#33738) ## Description Optimizes `HyperConnectionLowRankMix` for both multi-row prefill and small-M decode on CUDA: 1. **Prefill (`FusedPreMixInjectPostGateB4H2560Kernel<T>`)**: Fuses the pre-mix projection (`Norm(streams) * sigmoid_gate * (2 * alpha_pre)`), the `alpha_inj * streams + y` injection, and the `2 * sigmoid(post_logits) * post_scale` post-gate into a single 320-thread register-only kernel for the 4-branch, `hidden = 2560` shape (`num_rows >= 8, rank == 320`), eliminating two intermediate `(num_rows, 4, 2560)` global-memory round-trips and reducing prefill HyperConnection mix latency by **25%** (`41.7 -> 31.4 us/launch` at `num_rows = 8192` on H200). 2. **Decode (`HcDownKernel` and `HcUpPreKernel<T, 2, 4, 320>`)**: Adds a 4-lane warp-shuffle epilogue (`kFastEp4x320`) that eliminates the `sg` shared-memory staging and third CTA barrier in `HcUpPreKernel`, prefetches `norm_w` / `streams` before `griddepcontrol.wait`, caches `w_reg8` / `w_reg9` in `HcDownKernel`, and unrolls `p.splits == 8`, reducing combined `HcDown + HcUpPre` critical-path time in Qwen3.8-Flash-Next decode by **94 us/cycle**. ## Summary of Changes | File | Change | |------|--------| | `onnxruntime/contrib_ops/cuda/bert/hyper_connection_low_rank_mix_impl.cu` | Add `FusedPreMixInjectPostGateB4H2560Kernel<T>` for prefill and `kFastEp4x320` 4-lane warp-shuffle epilogue + weight/stream prefetching in `HcDownKernel` and `HcUpPreKernel<T, 2, 4, 320>` for decode | | `onnxruntime/test/contrib_ops/hyper_connection_low_rank_mix_op_test.cc` | Add `(num_rows=11, num_branches=4, hidden=2560, rank=320)` FP16/BF16 coverage to `UnfusedManyRows` | ## Testing - `onnxruntime_provider_test --gtest_filter='*HyperConnection*'`: **30 / 30 passed** (including new `(11, 4, 2560, 320)` prefill test cases and `FusedDecodeShapeRank320`). - End-to-end `engine_behaviours.py` on Qwen3.8-Flash-Next RC5 (`all_int4`, `top16`, `top08`): **27 / 27 PASS** on each package. ## Checklist - [x] Tests added/updated - [x] No breaking changes - [x] `lintrunner` clean --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…soft#33404) ### Description <!-- Describe your changes. --> Refines the extensible runtime fusion design around EP-registered, ordered patterns and the existing capability path: - EPs own pattern registration and priority; ORT selects compatible candidates in that order, subject to semantic, ownership, kernel, and eventual memory-feasibility checks. - Reuse `GetCapability`, `ComputeCapability`, `nodes_to_optimize`, and `optimization_func` through validated adapters. Distinguish existing application hooks from the additional recipe-description, ordering, capability-update, and external-registration support still needed. - Separate candidate description, selection, application, and reconciliation. Baseline ordered selection comes first; target memory estimation can connect to the same recipes before final budgeted selection, without requiring the general placement planner. - Replace the parallel post-partition hook and proposed `OrtRF*` function table with logical recipe/lifetime contracts. Preserve optional independent package delivery; defer exact public ABI additions until the capability integration is established. - Treat gramalingam#16 as an optional matcher implementation to evaluate with small Qwen-derived fixtures and the model demo, not a system-design prerequisite. - Update the qualification plan, approval ledger, and milestones consistently; retain CUDA mapping, state, numerical, and resource requirements. Design-only; no runtime implementation, build, GPU allocation, or model qualification is included. Public interfaces and implementation contracts remain subject to maintainer approval. Validation: `git diff --check` passed. Documentation fences and stale hook/API references were checked; no runtime tests were run. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Keep canonical ONNX artifacts unchanged while allowing optional matcher/adapter updates to reuse existing kernels. Align fusion with capability-based EP ownership and the recipe/planning direction in microsoft#33372 instead of introducing a separate selection pipeline. Qwen3.8-27B remains the model-independent mechanism's pilot, not its API. Fixes microsoft#33403. --------- Signed-off-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: titaiwangms <18010845+titaiwangms@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38c05fba-777a-447c-af24-f930f13e4021
## Description Adds a `com.microsoft` `SwiGLU` contrib operator with a CUDA kernel, plus a CUDA graph fusion that rewrites the decomposed SiLU-gated activation that exporters emit today into the new operator. `SwiGLU` exposes the clamped SwiGLU activation that `MoE`/`QMoE` already apply internally, for dense feed-forward and shared-expert paths that do not run through a grouped expert GEMM. > This PR previously also added `MoERouter`. That operator is now in its own PR: microsoft#32935. ## Summary of Changes ### `SwiGLU` operator | File | Change | |------|--------| | `onnxruntime/core/graph/contrib_ops/contrib_defs.cc`, `ms_opset.h` | Schema, shape inference and registration. | | `onnxruntime/contrib_ops/cuda/math/swiglu.{h,cc}` | CUDA `OpKernel`: validates shapes and handles the packed single-input form. | | `onnxruntime/contrib_ops/cuda/math/swiglu_impl.{h,cu}` | Fused clamp + gate kernel. | | `onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc` | Registration for float, float16 and bfloat16. | ``` G = clamp(gate, max=limit) L = clamp(up, min=-limit, max=limit) output = G * Sigmoid(activation_alpha * G) * (L + activation_beta) ``` - Arithmetic is done in float regardless of `T`. A `limit` of zero or less disables both clamps. - The result is rounded to `T` once, after the multiply. The optional INT attribute `round_activation` (default 0) additionally rounds `G * Sigmoid(activation_alpha * G)` to `T` before the multiply by `(L + activation_beta)`, as a `QuickGelu` followed by a `Mul` in `T` would. - Uses the same `limit` / `activation_alpha` / `activation_beta` contract as `MoE`/`QMoE`. - `up` is optional. When omitted, `gate` holds both halves of one `[.., 2 * inter]` projection (gate first, then up), so a fused sibling GEMM needs no `Split`. - With `up` supplied and default `limit`/`activation_beta`, it matches ONNX `SwiGLU` (opset 28) with `alpha = activation_alpha`. ### `SwiGluFusion` (CUDA EP, level 2) | File | Change | |------|--------| | `onnxruntime/core/optimizer/swiglu_fusion.{h,cc}` | Rewrites `QuickGelu(gate, alpha) * up` to `SwiGLU(gate, up, activation_alpha=alpha, round_activation=1)`. | | `onnxruntime/core/optimizer/graph_transformer_utils.cc` | Registers it for CUDA right after `QuickGeluFusion`. | `QuickGeluFusion` already turns `gate * Sigmoid(gate)` into `QuickGelu`, so existing models with a decomposed SiLU-gated MLP now run the fused kernel without being re-exported. The fusion only fires when `QuickGelu` has a single consumer, the element type is float, float16 or bfloat16, and `gate` and `up` provably share one shape (`Mul` broadcasts but `SwiGLU` does not). `round_activation=1` keeps `QuickGelu`'s rounding to `T` before the multiply, so the fused graph is bit-identical to the unfused `QuickGelu` + `Mul` for float, float16 and bfloat16, including the negative tail where the activation underflows in `T`. ### Shared helper - `_Sigmoid(float)` added to `onnxruntime/core/providers/cuda/cu_inc/common.cuh` next to `_Exp`/`_Log`. It uses the same numerically stable form as `OP_Sigmoid`. ## Testing - `onnxruntime/test/python/transformers/test_swiglu.py`: PyTorch reference over float32/float16/bfloat16, with and without `up`, with and without the clamp, non-default `activation_alpha`/`activation_beta`, packed vs. split parity, and shape validation errors. Fusion-on vs. fusion-off outputs must be exactly equal for float32/float16/bfloat16 on negative-tail and bulk inputs, and both `round_activation` modes are pinned. - `onnxruntime/test/optimizer/swiglu_fusion_test.cc`: fusion fires in either `Mul` operand order and carries `alpha` and `round_activation=1`. It is skipped for broadcast `Mul`, a shared `QuickGelu` output and CPU-assigned nodes. End-to-end CUDA parity (Level1 vs. Level2) is exact (tolerance 0) for float, float16 and bfloat16, including negative-tail inputs. ``` python -m pytest onnxruntime/test/python/transformers/test_swiglu.py # 12 passed onnxruntime_test_all --gtest_filter='*SwiGlu*:*SwiGLU*:*QuickGelu*' # 27 passed, 2 skipped (WebGPU) onnxruntime_test_all --gtest_filter='GraphTransformationTests*:*Fusion*:*SwiGlu*:*SwiGLU*:*QuickGelu*' # 505 passed, 17 skipped (WebGPU) # Two MobileClip CUDA attention-fusion tests need libcudnn on the library path; they pass when it is visible. ``` ## Checklist - [x] Tests added - [x] No breaking changes - [x] Documentation updated --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
) ### Description <!-- Describe your changes. --> Adds a subgroup-matrix Conv path for the WebGPU EP that computes the convolution as an implicit GEMM. Covers F16, channels-last, `group == 1` convs on devices reporting an 8x16x16 subgroup-matrix config, and falls back to the existing Conv paths otherwise. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Conv dominates runtime in vision models, but the existing WebGPU Conv paths do not use the subgroup-matrix units that the MatMul path already exploits on Intel Xe2/Xe3. This brings the same acceleration to Conv.
…mers/models/stable_diffusion/requirements/cuda12 (microsoft#33734) Bumps [onnx](https://github.com/onnx/onnx) from 1.21.0 to 1.22.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/onnx/onnx/releases">onnx's releases</a>.</em></p> <blockquote> <h2>v1.22.0</h2> <p>ONNX v1.22.0 is now available with exciting new features! We would like to thank everyone who contributed to this release! Please visit <a href="https://onnx.ai/">onnx.ai</a> to learn more about ONNX and associated projects.</p> <h2>What's Changed</h2> <h3>Breaking Changes and Deprecations</h3> <ul> <li>Swap qk_matmul_output_mode 1 & 2 to match computation order by <a href="https://github.com/titaiwangms"><code>@titaiwangms</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7913">onnx/onnx#7913</a></li> </ul> <h3>Spec and Operator</h3> <p>Two new operators <code>LinearAttention-27</code> and <code>CausalConvWithState-27</code> were introduced.</p> <ul> <li>Fix number of pad modes in doc_strings.cc by <a href="https://github.com/assafpr"><code>@assafpr</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7803">onnx/onnx#7803</a></li> <li>Add FlexAttention Op to ai.onnx.preview opset by <a href="https://github.com/mshr-h"><code>@mshr-h</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7534">onnx/onnx#7534</a></li> <li>Fix Attention op softcap ordering: apply before mask/bias by <a href="https://github.com/titaiwangms"><code>@titaiwangms</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7867">onnx/onnx#7867</a></li> <li>Add LinearAttention and CausalConvWithState operators (Opset 27) by <a href="https://github.com/tadani3"><code>@tadani3</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7950">onnx/onnx#7950</a></li> <li>feat(generator): extend Range operator with float16 and bfloat16 support (opset 27) by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7923">onnx/onnx#7923</a></li> </ul> <h3>Reference Implementation</h3> <ul> <li>Fix missing 'mul' reduction in ScatterElements reference implementation by <a href="https://github.com/zdryan"><code>@zdryan</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7842">onnx/onnx#7842</a></li> <li>Fix QLinearMatMul output saturation by <a href="https://github.com/karimbaidar"><code>@karimbaidar</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7868">onnx/onnx#7868</a></li> <li>Fixed more bugs in the Scan reference op by <a href="https://github.com/tadani3"><code>@tadani3</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7964">onnx/onnx#7964</a></li> </ul> <h3>Utilities and Tools</h3> <ul> <li>Fix Slice shape inference crashes with SIGABRT on empty dimensions by <a href="https://github.com/titaiwangms"><code>@titaiwangms</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7738">onnx/onnx#7738</a></li> <li>Rename misleading input_rank param to input_dim_value in processSlice… by <a href="https://github.com/titaiwangms"><code>@titaiwangms</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7739">onnx/onnx#7739</a></li> <li>fix: Conv/Pool strides validation by <a href="https://github.com/edgchen1"><code>@edgchen1</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7764">onnx/onnx#7764</a></li> <li>fix: add input/output bounds checks in version converter adapter by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7813">onnx/onnx#7813</a></li> <li>Harden version conversion against malformed inputs by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7872">onnx/onnx#7872</a></li> <li>fix: add input rank checks in Gemm version converter adapters by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7880">onnx/onnx#7880</a></li> <li>Fix raw_data handling in version converter adapters by <a href="https://github.com/cyyever"><code>@cyyever</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7910">onnx/onnx#7910</a></li> <li>Fix checker to use len() instead of sys.getsizeof() for protobuf size check by <a href="https://github.com/OmarAzizi"><code>@OmarAzizi</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7760">onnx/onnx#7760</a></li> <li>Add version macros by <a href="https://github.com/cbourjau"><code>@cbourjau</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7918">onnx/onnx#7918</a></li> <li>Remove internal spec_to_yaml tool by <a href="https://github.com/cbourjau"><code>@cbourjau</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7985">onnx/onnx#7985</a></li> <li>Address shape inference shortcomings by <a href="https://github.com/yuslepukhin"><code>@yuslepukhin</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7997">onnx/onnx#7997</a></li> <li>Add unifyInputShape / unifyInputShapePrefix shape inference utilities by <a href="https://github.com/gramalingam"><code>@gramalingam</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7999">onnx/onnx#7999</a></li> <li>Add operator+ and operator- for Dim by <a href="https://github.com/gramalingam"><code>@gramalingam</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/8000">onnx/onnx#8000</a></li> <li>Fix KeepAspectRatioHelper precision for scaled output dimensions by <a href="https://github.com/elwhyjay"><code>@elwhyjay</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/8007">onnx/onnx#8007</a></li> <li>Fix heap buffer over-read in Conv/Pool shape inference for weight rank mismatch by <a href="https://github.com/Copilot"><code>@Copilot</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/8037">onnx/onnx#8037</a></li> </ul> <h3>Build, CI and Tests</h3> <ul> <li>Add update into main.yml by <a href="https://github.com/titaiwangms"><code>@titaiwangms</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7687">onnx/onnx#7687</a></li> <li>Update check_urls.yml by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7716">onnx/onnx#7716</a></li> <li>Update add_msvc_runtime_flag to work with MSVC_RUNTIME_LIBRARY by <a href="https://github.com/Shadows-of-Fire"><code>@Shadows-of-Fire</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7660">onnx/onnx#7660</a></li> <li>Try to fix renovate by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7742">onnx/onnx#7742</a></li> <li>fix upload; Update release_win.yml by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7728">onnx/onnx#7728</a></li> <li>Allow release CIs to run when a labeled PR receives new commits by <a href="https://github.com/Copilot"><code>@Copilot</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7741">onnx/onnx#7741</a></li> <li>Update pixi.{toml,lock} by <a href="https://github.com/cbourjau"><code>@cbourjau</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7746">onnx/onnx#7746</a></li> <li>hash for googletest by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7765">onnx/onnx#7765</a></li> <li>Update RELEASE-MANAGEMENT.md by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7773">onnx/onnx#7773</a></li> <li>Update doc CIPipeline by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7782">onnx/onnx#7782</a></li> <li>use reviewdog to fix the pr_checks workflow by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7780">onnx/onnx#7780</a></li> <li>Update copilot-setup-steps.yml; persist-credentials: false by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7768">onnx/onnx#7768</a></li> <li>Update release_linux.yml; replace tag by hash by <a href="https://github.com/andife"><code>@andife</code></a> in <a href="https://redirect.github.com/onnx/onnx/pull/7769">onnx/onnx#7769</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/onnx/onnx/commit/2bb50465112feca9003e1ed654d77f01ff1415ca"><code>2bb5046</code></a> Fix windows workflows on rel-1.22.0 branch (<a href="https://redirect.github.com/onnx/onnx/issues/8087">#8087</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/eda03851c322d0132a937f983cef83fb33c0dd9b"><code>eda0385</code></a> Update version number to 1.22.0 (<a href="https://redirect.github.com/onnx/onnx/issues/8086">#8086</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/b124e0188a8bc47c9de8157e3296df6c77fdc06b"><code>b124e01</code></a> Bump version number to 1.22.0rc2 (<a href="https://redirect.github.com/onnx/onnx/issues/8071">#8071</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/8de2cf6aa47928e6515ac6d9e1a8b4758886a7df"><code>8de2cf6</code></a> Cherrypicks for 1.22.0rc2 (<a href="https://redirect.github.com/onnx/onnx/issues/8066">#8066</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/53d61200c0b966f39027ea46ea4e3078363a0308"><code>53d6120</code></a> Cherry-pick: Address shape inference issues in Conv (<a href="https://redirect.github.com/onnx/onnx/issues/8051">#8051</a>) to rel-1.22.0 (<a href="https://redirect.github.com/onnx/onnx/issues/8">#8</a>...</li> <li><a href="https://github.com/onnx/onnx/commit/bc3be77bec2f628788796dff60819186bacf49df"><code>bc3be77</code></a> Set version number to 1.22.0rc1 (<a href="https://redirect.github.com/onnx/onnx/issues/8024">#8024</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/e945daf7e12eaeb624ce1edd39ccdbb97879626d"><code>e945daf</code></a> feat(generator): extend Range operator with float16 and bfloat16 support (ops...</li> <li><a href="https://github.com/onnx/onnx/commit/293ad621a244fb501a5ed9660c01e666ba5e3e86"><code>293ad62</code></a> Run lints also on Windows (<a href="https://redirect.github.com/onnx/onnx/issues/8014">#8014</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/8847da48ff3bcf9314cdebb1a44114f723a8de4d"><code>8847da4</code></a> Follow up for scikit-build-core migration (<a href="https://redirect.github.com/onnx/onnx/issues/8017">#8017</a>)</li> <li><a href="https://github.com/onnx/onnx/commit/882a5ef11bf987462e0fbaf9d95d5e640a7b82c7"><code>882a5ef</code></a> Fix/sdist missing SBOM cdx json (<a href="https://redirect.github.com/onnx/onnx/issues/8010">#8010</a>)</li> <li>Additional commits viewable in <a href="https://github.com/onnx/onnx/compare/v1.21.0...v1.22.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/microsoft/onnxruntime/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…soft#33663) ### Description `QDQSelectorActionTransformer` rewrites `DQ -> op -> Q` node groups in two ways: it replaces them with a `QLinear*`/`QGemm` op, or it drops the Q/DQ nodes around ops such as `MaxPool`, `Resize` and `Slice`. Neither rewrite is valid for float8/float4 quantized types: - The `QLinear*`/`QGemm` replacement ops only accept int8/uint8. The schema of `QLinearConv`, `QLinearAdd`, `QLinearConcat`, `QGemm` and the other ops rejects float8. `QLinearMatMul`-21 allows float8 in its schema, but the CPU EP only registers int8/uint8 kernels for it. - After the Q/DQ nodes are dropped, the target op receives the float8 tensor directly. Most of these ops (for example `MaxPool`, `Resize` and `Slice`) either do not accept float8 in their schema or have no float8 kernel on the CPU EP. So for a float8 QDQ model, session creation fails at `ORT_ENABLE_EXTENDED` and `ORT_ENABLE_ALL`, while `ORT_DISABLE_ALL` and `ORT_ENABLE_BASIC` run fine, because the CPU EP has float8 `QuantizeLinear`/`DequantizeLinear` kernels. This PR makes `BaseSelector::Select` leave a node group unchanged when any of its DQ inputs or Q outputs has a float8 or float4 type. The check sits in `BaseSelector`, which only `QDQSelectorActionTransformer` uses. It does not affect the `NodeGroupSelector` classes that EPs reuse for QDQ node unit grouping. One trade-off: for opset >= 21, `Transpose` and `Reshape` do support float8, so dropping their Q/DQ nodes would still have been valid. Their Q/DQ nodes are now kept for float8 as well. That costs only the lossless drop-QDQ optimization for those two ops, and avoids encoding a per-op, per-opset allow list in the selector. ### Motivation and Context Fixes microsoft#33761. Minimal repro (opset 21, CPU EP): ```python import numpy as np import onnxruntime as ort from onnx import TensorProto, helper F8 = TensorProto.FLOAT8E4M3FN inits = [ helper.make_tensor("s", TensorProto.FLOAT, [], [0.125]), helper.make_tensor("zp", F8, [], [0]), helper.make_tensor("w", F8, [4, 4, 3, 3], [0.25] * 144), helper.make_tensor("ws", TensorProto.FLOAT, [], [0.0625]), ] nodes = [ helper.make_node("QuantizeLinear", ["x", "s", "zp"], ["xq"]), helper.make_node("DequantizeLinear", ["xq", "s", "zp"], ["xdq"]), helper.make_node("DequantizeLinear", ["w", "ws", "zp"], ["wdq"]), helper.make_node("Conv", ["xdq", "wdq"], ["y"]), helper.make_node("QuantizeLinear", ["y", "s", "zp"], ["yq"]), helper.make_node("DequantizeLinear", ["yq", "s", "zp"], ["out"]), ] graph = helper.make_graph( nodes, "fp8_qdq_conv", [helper.make_tensor_value_info("x", TensorProto.FLOAT, [1, 4, 8, 8])], [helper.make_tensor_value_info("out", TensorProto.FLOAT, None)], inits) model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 21)], ir_version=10) x = np.random.uniform(-2, 2, (1, 4, 8, 8)).astype(np.float32) for level in [ort.GraphOptimizationLevel.ORT_DISABLE_ALL, ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED]: so = ort.SessionOptions() so.graph_optimization_level = level sess = ort.InferenceSession(model.SerializeToString(), so, providers=["CPUExecutionProvider"]) sess.run(None, {"x": x}) ``` With `ORT_ENABLE_EXTENDED`, this fails with: ``` INVALID_GRAPH : This is an invalid model. Type Error: Type 'tensor(float8e4m3fn)' of input parameter (xq) of operator (QLinearConv) in node () is invalid. ``` The same failure happens for float8 QDQ `Add`, `Mul`, `Concat`, `AveragePool`, `GlobalAveragePool`, `Sigmoid`, `LeakyRelu`, `Softmax`, `Gemm`, `MaxPool`, `Resize`, `Slice`, `Gather`, `Expand`, `Tile`, `DepthToSpace` and `Squeeze`/`Unsqueeze`/`Flatten`. `MatMul` fails with `NOT_IMPLEMENTED` for `QLinearMatMul(21)` instead. The current workaround is to disable `QDQSelectorActionTransformer` through `disabled_optimizers`, which also disables all int8 QDQ fusions in the session. ### Testing - Added `QDQTransformerTests.Float8QDQNodeGroupsAreNotFused`. It builds float8 QDQ graphs for `Conv`, `MatMul`, `Add`, `Mul`, `AveragePool`, `Softmax`, `Concat`, `MaxPool`, `Resize` and `Slice`, runs them at Level1 and Level2, checks that the outputs match and that no `QLinear*`/`QGemm` op is created. Without the selector change, all 10 cases fail with the errors above. - Extended `GetZeroPointBytes` in the test graph builder to support `FLOAT8E4M3FN` zero points. - Ran locally on Linux x64 (Release, CPU EP), all passing: `*QDQ*:*Qdq*:*Quant*:*NodeUnit*:*TransposeOpt*:GraphRuntimeOptimizationTest.*` (409 tests) and `*Transform*:*Optimiz*:*Fusion*:*Selector*` (1044 tests, of which 25 are skipped). Co-authored-by: Cursor <cursoragent@cursor.com>
…oft#33745) ### Description <!-- Describe your changes. --> Guard the three disk-backed constant tests with `!defined(__wasm__)`, matching existing optimizer external-data test coverage. Preserve all native tests and WASM in-memory constant tests. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Fix Web CI build failure. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
### Description Adds a WebGPU `QuantizeLinear` kernel and int8 support in `Cast`, and fixes byte-lane packing in the segmented (>`maxStorageBufferBindingSize`) output setters. All gaps were found by the W3C WebNN conformance (WPT) suite running on the WebGPU EP with CPU fallback disabled. Commits: 1. **Add WebNN regression test for 1-D blocked uint8 DequantizeLinear.** Adds the WebNN vector "dequantizeLinear uint8 1D tensor with 1D scale, implicit block_size = 2" (microsoft#32730) for f32 and f16 scales, with `block_size` both explicit and inferred. microsoft#32734 fixed this path but only tested int8 with block_size 4. 2. **Add QuantizeLinear kernel.** - f32/f16 input, int8/uint8 output. Registered for opsets 10-12, 13-18, 19-20, 21-22 and 23-24. From opset 23, x / y_scale is computed in the `precision` type (default: the y_scale type). The kernel divides in f32, so opset 23/24 is registered for f32 `y_scale` only. Both GetCapability paths (in-tree `webgpu_execution_provider.cc` and plugin `ep/ep.cc`) leave nodes with an explicit non-f32 `precision` to another EP. - Each invocation writes one packed u32 word (4 outputs), so output bytes are never shared between invocations. - DequantizeLinear's per-tensor/per-axis/blocked classification and shape validation (including block_size inference and the element-wise axis 0, block_size 1 form) is factored into a helper used by both kernels. - Adds an `Int8x4` case to `ShaderVariableHelper::SetByOffset` that packs the low byte of each lane. - WGSL f32 division is only accurate to 2.5 ULP, which flips results near .5 (e.g. `QuantizeLinearOpTest.Int8`: -5 / 0.039215686 = -127.4999...). The shader recomputes the quotient with integer long division when 0.25 <= |q| < 1024, so round-half-to-even matches the CPU kernel bit-exactly. 3. **Support int8 in Cast.** Adds int8 to T1/T2. Input is unpacked with `unpack4xI8` (sign-extending) on both the generic and to-int64 paths; output uses the new Int8x4 packing, which keeps each lane's low byte like a narrowing conversion. 4. **Pack byte lanes in segmented output setters.** Outputs larger than `maxStorageBufferBindingSize` are written through a generated per-segment setter that stored the packed u32 value unchanged. Uint8x4/Int8x4 writers (Cast, Expand, Gather, QuantizeLinear) pass one value per lane, so those shaders failed to compile. The setter now takes `vec4<u32>`/`vec4<i32>` lanes and packs them like the unsegmented `SetByOffset`. This also fixes a latent uint8 bug on main for Cast/Expand/Gather. Tests (WebGPU-pinned, CPU EP fallback disabled) are in `onnxruntime/test/providers/webgpu/tensor/{quantize_linear_test,cast_op_test}.cc`. They cover the WebNN conformance vectors, ties, saturation, per-axis, blocked (first/last axis, partial block), all opsets, `precision` routing, near-tie quotients against the CPU reference, Q -> DQ round trip, int8 casts to/from f32/f16/int32/int64/uint8/bool, and outputs spanning buffer segments. Validation (Windows ARM64, NVIDIA RTX Spark N1X / D3D12, Release): - `build.py --use_webgpu ... --target onnxruntime_provider_test`, then `onnxruntime_provider_test --gtest_filter="*WebGpu*:CastOpTest.*:*QuantizeLinear*:*DequantizeLinear*:ExpandOpTest.*:GatherOpTest.*"`: 1159 tests, 1147 passed, 0 failed, 12 skipped. The skips existed before this change and are unrelated: `QuantizeLinearOpTest.*_DML*` (DML only) and hardware/build-feature skips in `WebGpuMatMulAlgorithmTest`, `WebGpuMatMulNBitsTest.DP4A*` and `WebGpuContextTest.AdapterIndexRejectsUnsupportedBuild`. - New tests that ran and passed: `WebGpuQuantizeLinearTest.*` (including `OpsetVersions` 10-24, `Opset23PrecisionOtherThanFloat`, `Opset23ExplicitFloatPrecision`, `SegmentedOutput`), `CastOpTest.Int8ToOtherTypes_WebGpu`, `CastOpTest.OtherTypesToInt8_WebGpu`, `CastOpTest.ByteOutputsAcrossBufferSegments_WebGpu` and `WebGpuDequantizeLinearTest.*`. - The existing CPU `QuantizeLinearOpTest.*` suite also runs on WebGPU and passes, including `Int8`, which depends on the exact-quotient rounding. - Plugin EP build: `build.py --use_webgpu shared_lib --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF --target onnxruntime_providers_webgpu` succeeds. This compiles the `ep/ep.cc` GetCapability change. - Sensitivity check: without the fixes, `Opset23PrecisionOtherThanFloat` returned 5 and 3 (expected 4 and 2), and `SegmentedOutput` and `CastOpTest.ByteOutputsAcrossBufferSegments_WebGpu` failed. Related work: this overlaps with @edgchen1's branch [`edgchen1/webgpu_quantizelinear`](https://github.com/microsoft/onnxruntime/tree/edgchen1/webgpu_quantizelinear) (last updated 2026-04-10, no PR yet). That branch also adds int4/uint4 QuantizeLinear output, which this PR does not cover; int4/uint4 is planned as a follow-up PR. ### Motivation and Context WebNN's `quantizeLinear`, qdq subgraphs and int8 `cast` lower to ONNX `QuantizeLinear`/`Cast`, which had no WebGPU kernel (or no int8 type), so graph build failed with CPU fallback disabled. WPT results (webgfx/webnn-test full suite, Edge Canary 158 arm64, NVIDIA RTX Spark N1X (D3D12), ORT 1.28.3 runtime, WebGPU plugin EP). Before = plugin built from main at 8120434; after = plugin with this change and four companion WebGPU PRs applied, attributed by op. This PR's ops fix 67 subtests (57 required): | WPT test | Before | After | Notes | |---|---|---|---| | quantizeLinear | 4/29 | 15/29 | remaining 14 are optional int4/uint4/int32 outputs | | qdq_subgraph | 1/43 | 43/43 | | | dequantizeLinear | 25/33 | 27/33 | "quantizeLinear then dequantizeLinear" cases | | cast | 38/51 | 50/51 | all int8 casts; remaining failure is a separate f32->f16 rounding issue | For context, with this PR and its four companions applied, failing WPT subtests drop from 343 to 68 (required failures 275 -> 11). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
### Description <!-- Describe your changes. --> Two WebGPU EP gaps found by running the W3C WebNN conformance (WPT) suite on the WebGPU EP. **[WebGPU] Support channels-last bilinear Resize** - A 4-D linear `Resize` can scale dims 1 and 2 with channels last (scales `[1, h, w, 1]`). Scale validation accepts this, and WebNN emits it for `resample2d` with `axes = [1, 2]`. The WebGPU EP keeps Resize NCHW-only, so this layout reaches the NCHW bilinear kernel, which always interpolated the last two dims. - `ResizeBilinearProgram` now takes explicit `height_axis` / `width_axis`. For a rank-4 input with `scales[1] != 1` it interpolates dims 1 and 2; otherwise it keeps interpolating the last two dims. The layout is part of the program cache key. - New `onnxruntime/test/providers/webgpu/tensor/resize_op_test.cc`: f32 and f16 channels-last linear upsample (WebNN conformance vector), pinned to WebGPU with CPU EP fallback disabled. **[WebGPU] Add LpPool and GlobalLpPool kernels** - Adds an Lp mode to the shared WebGPU pool program. It accumulates `sum(|x|^p)` in f32 so float16 windows don't overflow, then applies `^(1/p)`. Padding contributes 0. `p = 1` (abs-sum) and `p = 2` (`sqrt` of the sum of squares) are specialized, and other `p` use `pow`. Parallel reduction for large kernels uses an f32 shared buffer in Lp mode. - `PoolProgram` now takes a `PoolType` and `p` instead of an `is_max_pool` flag. Average-pool-only paths (`count_include_pad`, count tracking) are now gated on `kAveragePool`. - Registered in both the ONNX domain and the internal NHWC domain: `LpPool` 11–17, 18–21 and 22+, and `GlobalLpPool` 2–21 and 22+. The internal NHWC domain only defines LpPool 11/18 and GlobalLpPool 2, so LpPool before opset 11 stays on the CPU EP. - New tests in `onnxruntime/test/providers/webgpu/nn/pool_op_test.cc` cover p=1/2/3, strides/pads/dilations, opsets 11/18/22, GlobalLpPool, a large kernel (parallel reduction) and a float16 no-overflow case. Each runs NCHW and NHWC against a double-precision reference, pinned to WebGPU with CPU EP fallback disabled. #### Testing Unit tests: Windows ARM64, NVIDIA RTX Spark N1X (D3D12), Release, built with `build.py --use_webgpu ... --target onnxruntime_provider_test` on this branch (main + these two commits). - `onnxruntime_provider_test --gtest_filter="*WebGpu*:PoolTest.*:ResizeOpTest.*:UpsampleOpTest.*"`: 912 tests, **899 passed, 0 failed**, 13 skipped. - Skipped tests target other EPs (`PoolTest.*_Dml`, `ResizeOpTest.*_CudaRegression*`) or need hardware/build features this machine lacks (`WebGpuMatMulAlgorithmTest.ForcedSubgroupMatrix*` / `ForcedPackedSplitK*`, `WebGpuMatMulNBitsTest.DP4A*`, `WebGpuContextTest.AdapterIndexRejectsUnsupportedBuild`). None are related to this change. - The existing shared LpPool tests (`PoolTest.LpPool*`, `GlobalLpPool`, `LpPool_*` failure cases) now also run on WebGPU and pass. WebNN conformance (webgfx/webnn-test, full WPT suite), Edge Canary 158 arm64, NVIDIA RTX Spark N1X (D3D12), ORT 1.28.3 runtime, private WebGPU plugin EP. Before = plugin built from main; after = plugin built with this PR plus the four related WebGPU PRs (subtest fixes attributed by op). This PR fixes 29 subtests, all of them required: | WebNN op | Before | After | Cause | |---|---|---|---| | `l2Pool2d` | 2/30 | 30/30 | lowers to `LpPool`, which had no WebGPU kernel | | `resample2d` | 13/14 | 14/14 | linear upsample with `axes = [1, 2]` (channels last) | ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> WebNN `l2Pool2d` and channels-last `resample2d` either fell back to the CPU EP or gave wrong results on the WebGPU EP. This is one of five PRs from the WebNN conformance sweep of the WebGPU EP; the others cover elementwise kernels, precision fixes, quantization and f16 GRU/LSTM. With all five applied, failing WPT subtests drop from 343 to 68 and required failures from 275 to 11, compared with main. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…icrosoft#33652) ### Description <!-- Describe your changes. --> Draft pilot for EP-owned pattern rewriting through the existing capability optimization callback. **Prerequisite integrated:** microsoft#33631 merged as `9d3dc81268ab91a925b103d8bc4cee9807799148`. This branch is rebased onto `main` at `f809e08b988cc7613f2ed4ea40cdbc5c4c98aea4`; the aggregate diff no longer includes the Rama prerequisite. Review the two pilot commits: - `9aa06ce4d2` — internal region-scoped rewriting and test-only EP capability handoff. - `13d14f0f6e` — function-expansion lifecycle documentation and integration coverage. The rebase preserves upstream constant-loading tests and semantics; it does not revert the final merged Rama implementation. - Add an internal region-scoped `PatternRewriter::Run` overload. Only fully contained matches are eligible; existing rule ordering, provider checks and iterative behavior remain intact. - Track removed and newly emitted node IDs in the mutable region. Preserve boundary values and document nontransactional failure behavior. - Add a test-only CPU EP that owns ordered Transpose-composition patterns, discovers a region without changing the graph, and attaches an optimization callback to its capability. After ORT accepts the capability, the callback rewrites the selected region, updates its node list, and uses existing CPU kernels. - Verify mixed graphs, unselected overlapping capabilities, priority/fallback, outside consumers, scoped iteration and replacement DAG tracking, invalid/deleted IDs, missing ONNX domain imports, match-only mode and failures. - Add function-expansion lifecycle coverage using a fixed model-local function and a test-only CPU adapter. With AOT inlining enabled and disabled, verify that discovery does not apply rewrites, a claimed function survives until accepted application, and an unclaimed function expands before fresh body-pattern discovery. This addition changes no production code or expansion/partitioning policy. #### Rebased-head validation Qualified the pilot-only source at `13d14f0f6e05f342a4f42c99f70bddcc981d64cb`, independently of the CUDA fusion commits, in the existing Linux Release CUDA-enabled build. The capability adapters under test use the CPU EP. With the existing virtual environment, CUDA/cuDNN paths and build flags retained: ```sh timeout --signal=TERM --kill-after=30s 900s /usr/local/bin/cmake -S /home/titaiwang/workspace/ort-runtime-fusion-h200/cmake -B /mnt/data/titaiwang/runtime-fusion/build-cuda/Release -DFETCHCONTENT_FULLY_DISCONNECTED=ON -DFETCHCONTENT_UPDATES_DISCONNECTED=ON -DPython_EXECUTABLE=/mnt/data/titaiwang/runtime-fusion/venv/bin/python timeout --signal=TERM --kill-after=30s 7200s /usr/local/bin/cmake --build /mnt/data/titaiwang/runtime-fusion/build-cuda/Release --config Release --parallel 8 --target onnxruntime_test_all onnxruntime_providers_cuda -- -v ``` Results: both commands passed. The build completed 1,460 Ninja actions, compiling core/CUDA sources and linking the CUDA implementation provider; this was not a cached-object/link-only qualification. From `/mnt/data/titaiwang/runtime-fusion/build-cuda/Release`: ```sh timeout --signal=TERM --kill-after=30s 900s ./onnxruntime_test_all '--gtest_filter=FunctionTest.*:CheckAndBindComponentTests.*:MatchComponentTests.*:PatternCapabilityTests.*:PatternComponentTests.*:PatternRewriterTests.*:ReplacementComponentTests.*' --gtest_output=xml:/mnt/data/titaiwang/runtime-fusion/rama-rebase-pilot-engine.xml ``` Result: **283/283 passed**, zero failures/errors/disabled/skips, with no exclusions. This includes both tests previously excluded in the older CPU-only environment. XML counts and log/XML hashes were independently checked. `git diff --check f809e08..integration/ep-pattern-capability-rebase` also passed. Exact commands, build provenance, configuration and artifact hashes are retained locally in `rama-rebase-qualification-report.json`. #### Historical review and validation The original pilot commit `826601e64f14cee31ec35d72faca2e09fc1601a0` completed readability, implementation, critical, deep/spec and integration reviews. No Critical/Major findings were reported. Minor documentation/diagnostic clarification findings were resolved; the missing-domain capability fallback was reproduced with a failing regression test and fixed. The function-lifecycle addition and rebase integration received direct review, not another five-reviewer round. Before this rebase, the CPU-only build and scoped lint passed: ```sh cmake --build build/cpu-capability/Release --target onnxruntime_test_all --parallel 24 lintrunner --take CLANGFORMAT onnxruntime/core/optimizer/pattern_rewriter.h onnxruntime/core/optimizer/pattern_rewriter.cc onnxruntime/test/optimizer/pattern_rewriter_components_test.cc git diff --check ``` Results: all three commands passed on the old pilot revision. From that build directory: ```sh ./onnxruntime_test_all --gtest_filter='PatternCapabilityTests.*:PatternComponentTests.*:PatternRewriterTests.*:FunctionTest.*-PatternRewriterTests.GroupSignaturesAreIndependentOfGlobalLocale:FunctionTest.TestInlinedLocalFunctionNotRemoved' ``` Result: **248/248 passed**. This was an older Linux CPU Release `-O1 -DNDEBUG` build with contrib/ML ops disabled and local-only GCC warning exceptions; it is historical evidence, not qualification of the rebased head. Two tests were explicitly excluded: the locale-signature test segfaulted on both the pilot and a diagnostic executable with the unchanged prerequisite engine; the retained-local-function test failed on both the function-lifecycle addition and its unchanged prior component-test source. Those outcomes are not counted as passes. The new qualification above uses an unexcluded selector. **Limits:** the generic scoped rewriter tracks multi-node replacement results, but the capability adapters are test-only and deliberately handle N-to-1 Transpose chains and one fixed model-local function definition. Recognizing a function name alone is not production function-equivalence checking. No production EP registration, general N-to-M placement, resource accounting/memory estimation, external registration ABI or Qwen qualification is included. The function probe does not compare whole-function versus expanded-body placement alternatives or change cross-EP priority. Full CI and non-Linux platforms have not been validated locally. **Open question (integration review, non-blocking):** production integration must define rewrite policy during ORT-format `kAssignOnly` export. The current optimization callback does not receive the partitioner mode; this pilot does not establish or validate export behavior. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Pilot implementation toward microsoft#33403 and the EP-capability direction in microsoft#33404. An EP should be able to supply ordered patterns while ORT retains placement decisions. The existing `nodes_to_optimize` / `optimization_func` hook provides the acceptance-to-application seam; the missing local primitive was restricting iterative rewriting to the accepted region and returning its updated node membership. This pilot reuses the merged microsoft#33631 matcher and mutation engine rather than introducing a second rewrite pipeline or requiring ORT to select every individual match. It is intended to collect feedback on the region-scoped interface and capability handoff before adding production patterns or memory planning. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38c05fba-777a-447c-af24-f930f13e4021
…microsoft#33736) ### Description Skip the cuDNN include dir when it is one of the compiler's implicit include directories; the compiler searches it anyway. ### Motivation and Context When cuDNN is installed under the system prefix (e.g. --cudnn_home=/usr), CUDA_PLUGIN_CUDNN_INCLUDE_DIR is /usr/include. CMake drops that implicit directory from the plugin target's own compile lines, but onnxruntime_unittests.cmake copies the target's INCLUDE_DIRECTORIES onto moe_gemm_int2_test.cc as a source property, which is not filtered. The file was then compiled with -isystem /usr/include ahead of the libstdc++ headers, and <cstdlib>'s #include_next <stdlib.h> failed with "stdlib.h: No such file or directory".
### Description <!-- Describe your changes. --> Add standard ONNX `BitShift` to the CUDA EP using the existing elementwise broadcasting dispatcher: - Unsigned 8/16/32/64-bit integers for opsets 11–27; all eight signed/unsigned integer types from opset 28. - Both directions, arithmetic right shifts for signed inputs, and wrapping left shifts implemented with unsigned intermediates and a bit-preserving conversion. - Counts are checked before shifting: negative or oversized counts produce `-1` only for right shifts of negative signed inputs, otherwise `0`, matching the current ONNX schema and CPU implementation. Negative counts do **not** reverse direction. - CUDA-only tests disable CPU fallback and cover integer extrema/high 64-bit patterns, zero/width-boundary/negative counts, scalar and multidirectional broadcasts, per-channel paths, initializer counts, empty tensors, and 2,051-element tails. - Update only the CUDA `BitShift` rows in `OperatorKernels.md`. This change is independent of the other bitwise kernel PRs. **Validation:** Passed on an H200 (`sm90`), Linux, CUDA 13.3, cuDNN 9.10.2, Python 3.12, ORT 1.32.0 Release/QUICK_BUILD. The standalone validation source was base `812043410eebd29c4bdd46b906447e2e5b77f7b2` plus this branch through `a94f033211605b6352f75a371790e803cb648cb8`; no XOR/AND/OR/NOT changes were present. All five compiled C++/CUDA source files match the committed content after CRLF normalization. Build/wheel command, run from the validation source directory — **passed**, including nvcc compilation and device `memcpy`: ```bash ../.venv/bin/python tools/ci_build/build.py --config Release --build_dir /tmp/ort-cuda-bitwise-xor-8d05709c/build --update --build --build_wheel --skip_tests --skip_submodule_sync --use_cuda --cuda_home /usr/local/cuda --cudnn_home /usr/lib/python3.12/site-packages/nvidia/cudnn --cmake_generator Ninja --parallel 16 --disable_contrib_ops --disable_ml_ops --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=90 FETCHCONTENT_FULLY_DISCONNECTED=ON onnxruntime_QUICK_BUILD=ON onnxruntime_USE_FLASH_ATTENTION=OFF onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION=OFF onnxruntime_USE_TRT_FUSED_ATTENTION=OFF onnxruntime_USE_XQA=OFF --targets onnxruntime_provider_test onnxruntime_pybind11_state ``` From the build's `Release` directory — **42/42 passed, no skips**: 18 new CUDA tests and 24 existing `BitShiftOpTest` tests: ```bash CUDA_VISIBLE_DEVICES=4 LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/python3.12/site-packages/nvidia/cudnn/lib ./onnxruntime_provider_test '--gtest_filter=*CudaBitShiftTest*:*BitShiftOpTest*' ``` Additional ad hoc numerical/profile probes, from `validated-shift` with the same environment — **230/230 models passed**, CPU fallback disabled, exact integer results, and all 230 profiled `BitShift` executions assigned to `CUDAExecutionProvider`: ```bash CUDA_VISIBLE_DEVICES=4 LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/python3.12/site-packages/nvidia/cudnn/lib ../.venv/bin/python ../probe-remaining-bitwise.py --group shift ``` The probes include six exhaustive 8-bit pair models (all 256×256 value/count pairs for signed opset 28 and unsigned opsets 11/28, both directions: 393,216 scalar results). The ad hoc probe script is validation infrastructure, not an added repository test. The initial 224-model baseline also matched CPU before applying this patch. Operator documentation generation, from the validation task root — **passed**; generated `BitShift` rows match the committed rows: ```bash PYTHONPATH=/tmp/ort-cuda-bitwise-xor-8d05709c/validated-shift/wheel-runtime LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/python3.12/site-packages/nvidia/cudnn/lib .venv/bin/python src/tools/python/gen_opkernel_doc.py --providers cuda --output_path validated-shift/OperatorKernels.generated.md ``` Validation is limited to this configuration; the full suite, other GPU architectures, and performance benchmarks were not run. The archive build does not embed a Git revision; provenance was checked using explicit source hashes. Validated wheel SHA256: `791fbb2278876c4dba5df7cb78d43d795209a67edf4629a23cf2de22fb22f132`. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> CUDA currently lacks a standard ONNX `BitShift` kernel. Native integer operations avoid CPU fallback and preserve exact wide-integer results without floating-point emulation or hardware-modulo shift-count behavior. --------- Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
### Description <!-- Describe your changes. --> Remove `continue-on-error: true` / `continueOnError: true` from browser WebGPU EP tests in GitHub Actions and Azure Pipelines, and from C# delegate validation in the Windows WebGPU workflow. Update the migration release-gate documentation. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Make test failures errors. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
### Description <!-- Describe your changes. --> Schedule `Python - CUDA13 - Combined WHLs` (Lotus definition 2353) daily at **09:00 UTC** from `main`. Set `always: true` so wheels are built even when the source has not changed. Push and PR triggers remain disabled, and the build continues to publish pipeline artifacts only. The existing Package pipeline health automation has also been updated separately to monitor definition 2353 explicitly. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Generate combined CUDA 13 wheels every morning for downstream publishing. The companion [release-pipelines PR 56020](https://aiinfra.visualstudio.com/Lotus/_git/release-pipelines/pullrequest/56020) repoints the existing 1ES publisher to this pipeline's unified wheel artifacts, preserving its feed options and `main`/`rel-*` completion triggers. Validation: YAML parsing and assertions passed for the exact cron, main-only branch filter, and `always: true`; comparison against the original YAML confirmed all other pipeline configuration is unchanged. `git diff --check` passed. No build or publishing pipeline was queued. The schedule takes effect after merge to `main`; the publishing pipeline's new source resource still requires authorization. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft#28019) ### Description Add CACHE when unsetting `CMAKE_CUDA_ARCHITECTURES` to ensure it's empty. ### Motivation and Context Recently, when building passing `CMAKE_CUDA_ARCHITECTURES=all` configuring fails because `CMAKE_CUDA_ARCHITECTURES` is not being correctly unsetted and then set to the curated list of architectures. Error message: ``` -- Setting CMAKE_CUDA_ARCHITECTURES to all enables a list of architectures OnnxRuntime optimized for, not all architectures CUDA compiler supports. CMake Error at external/cuda_configuration.cmake:154 (message): Unrecognized CUDA architecture: all Call Stack (most recent call first): CMakeLists.txt:715 (setup_cuda_architectures) -- Configuring incomplete, errors occurred! ``` I got this error both on Alma 9 and Ubuntu 24.04 and after this change the build starts to compile. --------- Co-authored-by: Juan Miguel Carceller <jmcarcell@users.noreply.github.com>
…nce (microsoft#33680) ### Description <!-- Describe your changes. --> Adds WebGPU EP kernels and integer type support for ops that the W3C WebNN conformance (WPT) suite lowers to ONNX. Without them, graph build fails when CPU EP fallback is disabled. Each commit includes WebGPU-pinned unit tests with CPU fallback disabled. | Commit | Change | |---|---| | [WebGPU] Add Or and Xor kernels | Registers `Or`/`Xor` (opset 7+, bool) next to `And`. WGSL defines `\|` on `vec4<bool>` but not `^`, so Xor uses `!=`. Tests cover scalar, element-wise (partial vec4), non-vectorized broadcast (including 4-D to 5-D) and both vectorized broadcast paths. | | [WebGPU] Add IsNaN and IsInf kernels | Registers `IsNaN` (9-12, 13-19, 20) and `IsInf` (10-19 f32, 20 f32/f16). Values are classified on raw IEEE-754 bits because WGSL lets implementations assume floats are finite, so `x != x` checks can be folded away. f16 lanes are split out of the raw words instead of being widened to f32. IsInf honors `detect_positive`/`detect_negative`. | | [WebGPU] Register Slice for int32 and uint32 | The Slice shader is type-agnostic, so `T` widens from float types to f32/f16/i32/u32. | | [WebGPU] Add Round, Sign and Softsign kernels | `Round` (11-21, 22; f32/f16): WGSL `round()` rounds half to even. `Sign` (9-12, 13; f32/f16/i32): WGSL `sign()` has no u32 overload. `Softsign` (1-21, 22; f32/f16) is evaluated in f32 and returns ±1 once \|x\| >= 2^24. Dividing directly returned 0 for ±FLT_MAX because GPUs flush the subnormal reciprocal of the divisor. | | [WebGPU] Accept an int64 exponent in Pow | Allows int64 for Pow's `T1` (exponent) constraint when int64 is enabled. The shader already converts the exponent to f32. An int64 base remains unsupported (existing TODO). | | [WebGPU] Support int32 in Abs and Neg | `Abs` accepts all supported number types (u32 is the identity). `Neg` accepts f32/f16/i32. INT_MIN wraps as in two's complement. | #### Testing Built on Windows ARM64 (Release, `build.py --use_webgpu ... --target onnxruntime_provider_test`) and run on an NVIDIA RTX Spark N1X GPU (D3D12): ``` onnxruntime_provider_test --gtest_filter="*WebGpu*:MathOpTest.*:ActivationOpTest.*:SliceTest.*:IsNaNOpTest.*:IsInfTest.*:RoundTest.*:SignTest.*:SoftsignTest.*:AbsTest.*:NegTest.*" ``` Result: 1214 tests, 1200 passed, 0 failed, 14 skipped. All 14 skips already exist on main and are unrelated to this change: - `MathOpTest.MatMulInt32Type`/`MatMulUint32Type`/`MatMulZeroK*`/`MatMulFloat16SharedInitializerWithKernelOwnedPrepack`: known WebGPU MatMul limitations. - `SliceTest.Slice1D_WithNegativeSteps_EndOutOfBounds_2`: an unconditional WebGPU skip on a float test. - `WebGpuMatMulAlgorithmTest.ForcedSubgroupMatrix*`/`ForcedPackedSplitK*`, `WebGpuMatMulNBitsTest.DP4A*`, `WebGpuContextTest.AdapterIndexRejectsUnsupportedBuild`: skipped because the hardware or build doesn't support the feature. `lintrunner` (clang-format, ruff) reports no issues on the changed files. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> The W3C WebNN conformance suite found these ops failing on the WebGPU EP. WebNN `logicalOr`/`logicalXor`, `isNaN`/`isInfinite`, `roundEven`, `sign`, `softsign`, `abs`/`neg` (int32) and `slice` (int32) lower to the ONNX ops above. Chromium lowers `reduceSumSquare` over no axes, or over a 0-D input, to `Pow(x, int64 2)`. WPT results (webgfx/webnn-test full suite, Edge Canary 158 arm64, NVIDIA RTX Spark N1X (D3D12), ORT 1.28.3 runtime, WebGPU plugin EP). "Before" is the plugin built from main at 8120434. "After" is the plugin built with this PR plus four related WebGPU WebNN-conformance PRs; results are attributed by op. This PR fixes 106 subtests (105 required): | WebNN op | Before | After | Notes | |---|---|---|---| | logical_or | 2/17 | 17/17 | | | logical_xor | 2/17 | 17/17 | | | is_nan | 1/15 | 15/15 | | | is_infinite | 1/18 | 18/18 | | | round_even | 1/11 | 11/11 | | | sign | 2/8 | 6/8 | remaining 2 are optional int8/int64 | | softsign | 2/19 | 19/19 | | | subgraph | 49/52 | 52/52 | conv2d/convTranspose2d/batchNormalization + softsign | | abs | 18/21 | 19/21 | int32; remaining are optional int8/int64 | | neg | 17/20 | 18/20 | int32; remaining are optional int8/int64 | | slice | 20/21 | 21/21 | | | reduce_sum_square | 37/45 | 45/45 | via Pow(x, int64 2) | With all five PRs applied, failing subtests drop from 343 to 68 compared with main, and required failures from 275 to 11. --------- Co-authored-by: Aditya Rastogi <adityar@ntdev.microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
### Description <!-- Describe your changes. --> Add CUDA execution for standard ONNX `BitwiseXor` (opset 18+) for `int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, and `uint64`. Reuse the existing binary elementwise implementation for multidirectional broadcasting and empty tensors. Boolean `Xor` is unchanged; this does not add other bitwise operators. Add CUDA-only regressions with CPU fallback explicitly disabled, covering all eight integer types at opsets 18 and 24, signed/unsigned boundaries, scalar operands, multidirectional broadcasting in both operand orders, empty outputs, and the INT64 `state XOR (state / 2048)` RNG pattern. Update the CUDA operator support table. Validation on Azure Linux 3 / NVIDIA H200 (physical GPU4), CUDA 13.3, cuDNN 9.10.2, Python 3.12, Release/sm90; source based on main `997d2d1b26` plus this patch: - `python tools/ci_build/build.py --config Release --build_dir /tmp/ort-cuda-bitwise-xor-8d05709c/build --build --build_wheel --skip_tests --skip_submodule_sync --use_cuda --cuda_home /usr/local/cuda --cudnn_home /usr/lib/python3.12/site-packages/nvidia/cudnn --parallel 16 --disable_contrib_ops --disable_ml_ops --targets onnxruntime_provider_test onnxruntime_pybind11_state` — **passed**, producing an ORT 1.32.0 GPU wheel. The build was configured with Ninja, `CMAKE_CUDA_ARCHITECTURES=90`, `onnxruntime_QUICK_BUILD=ON`, and Flash/MEA/TRT-fused-attention/XQA disabled. - From the build output directory: `CUDA_VISIBLE_DEVICES=4 LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/python3.12/site-packages/nvidia/cudnn/lib ./onnxruntime_provider_test --gtest_filter=*Xor*` — **45 tests passed**, no skips, including existing boolean XOR tests. - Additional ad hoc wheel probe: **146/146** models produced bit-identical NumPy results, and **146/146** profiled `BitwiseXor` executions used `CUDAExecutionProvider`, with CPU fallback disabled. This covers all integer types, opsets 18/24, full-width random values (including upper 64-bit lanes), scalar/multidirectional/empty cases, and integrated `Div → BitwiseXor` graphs over 4,103 INT64 RNG states. Before installing the patched wheel, the same probes on ORT 1.28.0 (`0368187f84`) produced 146 CPU XOR executions; GPU-only initialization failed as expected. - `clang-format --dry-run --Werror` on all six changed C++/CUDA files — **passed**; `git diff --check` — **passed**. The initial untargeted contrib-disabled build encountered a pre-existing `-Werror=unused-function` in `onnxruntime/test/optimizer/nhwc_transformer_test.cc:71`; the relevant provider-test and wheel targets above built successfully without changing unrelated code. Full-suite, non-sm90, full-model fidelity, and performance validation were not performed. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Current main has CPU and DirectML `BitwiseXor` kernels but no CUDA registration. Integer RNG hashing therefore falls back to CPU, even for INT32/UINT32, introducing repeated device transfers in GPU inference. This was observed while adding fishaudio/drama-3 support in onnxruntime/mobius#793 (2,862 CPU XOR executions in one sampled profile). Supporting the standard operator preserves the model's RNG algorithm and exact integer outputs without a custom operator or graph rewrite. Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
ai-fw-intg
requested review from
Jaswanth51,
ankitm3k,
jatinwadhwa921 and
vthaniel
October 30, 2026 20:39
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated daily backmerge from ORT main to ovep-develop. No conflicts detected. Do NOT squash or rebase - use merge commit only.