Skip to content

[Relax][ONNX] Add GridSample ONNX frontend integration#18932

Merged
tlopex merged 2 commits into
apache:mainfrom
OmarAzizi:onnx-frontend-gridsample
Mar 26, 2026
Merged

[Relax][ONNX] Add GridSample ONNX frontend integration#18932
tlopex merged 2 commits into
apache:mainfrom
OmarAzizi:onnx-frontend-gridsample

Conversation

@OmarAzizi

@OmarAzizi OmarAzizi commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Implements ONNX GridSample frontend integration for Relax, which was previously commented out in the converter map.
  • Adds GridSample converter class that handles ONNX→TVM grid shape transpose ([N, H_out, W_out, 2][N, 2, H_out, W_out]) and mode/padding attribute mapping.
  • Reuses the existing grid_sample Relax op (relax.op.image.grid_sample), which already exists, keeping the change minimal and focused on the frontend layer.
  • Adds tests covering all supported mode/padding_mode/align_corners combinations.

Closes part of #18928

Notes for Maintainers

The ONNX spec defines the default mode as "linear", but onnxruntime only accepts "bilinear". I've set the converter default to "bilinear" — happy to add a "linear""bilinear" translation if needed for spec compliance. (Edit: This was addressed)

Test Plan

python3 -m pytest -q tests/python/relax/test_frontend_onnx.py -k 'grid_sample'

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces full support for the ONNX GridSample operator in Relax. It provides the necessary conversion logic to translate ONNX GridSample nodes into Relax expressions, correctly handling attribute mapping and grid tensor shape transformations. The integration reuses an existing Relax operator and is thoroughly tested across various configurations, significantly expanding Relax's ONNX compatibility for image processing tasks.

Highlights

  • ONNX GridSample Integration: Implemented the frontend integration for the ONNX GridSample operator within Relax, enabling its conversion to equivalent Relax expressions.
  • GridSample Converter Class: Added a dedicated GridSample converter class responsible for handling ONNX to TVM grid shape transpositions (from [N, H_out, W_out, 2] to [N, 2, H_out, W_out]) and mapping mode and padding_mode attributes.
  • Existing Relax Op Reuse: Leveraged the pre-existing relax.op.image.grid_sample operator, ensuring minimal changes focused on the frontend conversion layer.
  • Comprehensive Testing: Included new tests covering all supported combinations of mode, padding_mode, and align_corners for the GridSample operator, along with a test for default attribute handling.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces the GridSample ONNX operator conversion to Relax, supporting various modes, padding, and alignment options. It also includes new parameterized tests to ensure correctness. The review suggests enhancing ONNX spec compliance by explicitly handling the "linear" mode for GridSample and adding a corresponding test case. Additionally, a redundant test for default attributes was identified and recommended for removal.

Comment on lines +3906 to +3908
method = attr.get("mode", b"bilinear")
if isinstance(method, bytes):
method = method.decode("ascii")

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.

medium

The ONNX GridSample spec defines "linear" as a valid mode, which is equivalent to "bilinear" for 4-D inputs. The current implementation does not handle this case and would pass "linear" to relax.op.image.grid_sample, which does not support it.

To improve ONNX spec compliance, I suggest adding a translation from "linear" to "bilinear". This will make the converter more robust for models that use mode="linear".

You've correctly noted the discrepancy between the ONNX spec and onnxruntime's behavior regarding the default mode. Keeping "bilinear" as the default in attr.get is a reasonable pragmatic choice, but handling explicit "linear" is important for broader model support.

Suggested change
method = attr.get("mode", b"bilinear")
if isinstance(method, bytes):
method = method.decode("ascii")
method = attr.get("mode", b"bilinear")
if isinstance(method, bytes):
method = method.decode("ascii")
if method == "linear":
method = "bilinear"

tvm_selected[:min_rows], ort_selected[:min_rows], rtol=1e-5, atol=1e-5
)

@pytest.mark.parametrize("mode", ["bilinear", "nearest"])

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.

medium

To test the recommended handling of mode="linear", please add it to the parameterization for this test. This will ensure the frontend correctly maps "linear" to "bilinear" as per the ONNX spec for 4D inputs.

Suggested change
@pytest.mark.parametrize("mode", ["bilinear", "nearest"])
@pytest.mark.parametrize("mode", ["bilinear", "nearest", "linear"])

Comment on lines +4024 to +4063
def test_grid_sample_defaults():
"""Test GridSample with explicit default attributes to verify correct handling:
mode defaults to 'bilinear', padding_mode defaults to 'zeros',
align_corners defaults to 0.
"""
# Only testing 2D (NCHW) as that's what TVM currently supports
x_shape = [1, 3, 4, 4]
grid_shape = [1, 2, 2, 2]
out_shape = [x_shape[0], x_shape[1], grid_shape[1], grid_shape[2]]

node = helper.make_node(
"GridSample",
inputs=["X", "grid"],
outputs=["Y"],
mode="bilinear",
padding_mode="zeros",
align_corners=0,
)

graph = helper.make_graph(
[node],
"grid_sample_defaults_test",
inputs=[
helper.make_tensor_value_info("X", TensorProto.FLOAT, x_shape),
helper.make_tensor_value_info("grid", TensorProto.FLOAT, grid_shape),
],
outputs=[
helper.make_tensor_value_info("Y", TensorProto.FLOAT, out_shape),
],
)

grid_data = np.random.uniform(-1, 1, grid_shape).astype("float32")
x_data = np.random.uniform(-1, 1, x_shape).astype("float32")

model = helper.make_model(graph, producer_name="grid_sample_defaults_test")
check_correctness(
model,
inputs={"grid": grid_data, "X": x_data},
opset=16,
)

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.

medium

This test case for default attributes is redundant. The parameter combination it tests (mode='bilinear', padding_mode='zeros', align_corners=0) is already covered by the parameterized test_grid_sample.

To avoid test duplication and improve test suite conciseness, I recommend removing this test function.

Signed-off-by: OmarAzizi <oalazizi75@gmail.com>
@OmarAzizi

Copy link
Copy Markdown
Contributor Author
  • "linear""bilinear" translation added. Also added "cubic""bicubic" translation for completeness since the ONNX spec defines both. Added dedicated IR-inspection tests (test_grid_sample_linear_mode_translation, test_grid_sample_cubic_mode_translation) since onnxruntime rejects both "linear" and "cubic" as mode strings, making check_correctness unusable for these cases. Also added "bicubic" to the main parametrized test since onnxruntime accepts it.

  • Remove test_grid_sample_defaults

@tlopex tlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM! Thank you! @OmarAzizi

@tlopex tlopex merged commit 59c14f6 into apache:main Mar 26, 2026
6 checks passed
@OmarAzizi OmarAzizi deleted the onnx-frontend-gridsample branch April 8, 2026 11:11
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.

2 participants