Skip to content

Fix meshgrid converter to handle non-1D inputs#2665

Merged
TobyRoseman merged 1 commit intoapple:mainfrom
cdeil:fix-meshgrid-non-1d-inputs
Mar 30, 2026
Merged

Fix meshgrid converter to handle non-1D inputs#2665
TobyRoseman merged 1 commit intoapple:mainfrom
cdeil:fix-meshgrid-non-1d-inputs

Conversation

@cdeil
Copy link
Copy Markdown
Contributor

@cdeil cdeil commented Mar 27, 2026

I am trying to use https://github.com/roboflow/rf-detr and convert the model to CoreML for use on iPad computer vision app. I'm using some of the fixes from https://github.com/landchenxuan/rf-detr-to-coreml and after upgrading to latest PyTorch 2.11 am getting good performance! :-)

There's one issue with torch.meshgrid that needs a small fix. For now I have a helper function to monkey-patch coremltools with this fix as workaround.

See description and code/test in this PR - done by coding agent.

Would be great if you could include it.


Summary

The meshgrid op converter raises ValueError("meshgrid received non-1d tensor.") when
inputs have rank > 1. This happens in practice when converting models that use
torch.linspace(...) / scalar before torch.meshgrid(), because the MIL real_div op
can broadcast the 1D linspace result with a 0D scalar divisor to produce a higher-rank
tensor.

This pattern is common in deformable attention modules (DINO, Deformable-DETR, RF-DETR)
where coordinate grids are created:

grid_y = torch.linspace(0.5, h - 0.5, steps=h) / h
grid_x = torch.linspace(0.5, w - 0.5, steps=w) / w
grid_y, grid_x = torch.meshgrid(grid_y, grid_x, indexing="ij")

The PyTorch JIT trace shows 1D tensors flowing into meshgrid, but during MIL conversion
the division by a 0D shape-derived scalar produces a result with rank > 1 in the MIL IR,
causing the meshgrid converter to reject it.

Changes

coremltools/converters/mil/frontend/torch/ops.py

  • Removed the hard rejection of non-1D inputs (raise ValueError("meshgrid received non-1d tensor."))
  • Added _flatten_inputs() helper that reshapes any non-1D inputs to 1D via mb.reshape(shape=[-1]) before meshgrid processing
  • This is safe because meshgrid semantically requires 1D-like inputs, and the flatten simply recovers the intended shape

coremltools/converters/mil/frontend/torch/test/test_torch_ops.py

  • Added test_meshgrid_non_1d_inputs to TestMeshgrid class
  • Tests the deformable attention pattern (linspace / scalar → meshgrid) with both ij and xy indexing modes
  • Parametrized across compute units and backends, consistent with existing test style

Testing

Red/green verified:

  • RED: Without the fix, the new test fails with ValueError: meshgrid received non-1d tensor.
  • GREEN: With the fix, all meshgrid tests pass (both existing and new)
4 passed (2 existing + 2 new) — no regressions

Related Issues

The meshgrid op converter raises ValueError when inputs have rank > 1.
This happens when converting models that use torch.linspace(...) / scalar
before torch.meshgrid(), because the MIL real_div op can broadcast the
1D linspace result with a 0D scalar divisor to produce a higher-rank tensor.

This pattern is common in deformable attention modules (DINO,
Deformable-DETR, RF-DETR) where coordinate grids are created via:
  grid_y = torch.linspace(0.5, h - 0.5, steps=h) / h
  grid_x = torch.linspace(0.5, w - 0.5, steps=w) / w
  grid_y, grid_x = torch.meshgrid(grid_y, grid_x, indexing='ij')

Instead of rejecting non-1D inputs, flatten them to 1D with
mb.reshape(shape=[-1]) before meshgrid processing.
@TobyRoseman
Copy link
Copy Markdown
Collaborator

Code changes look good.

CI: https://gitlab.com/coremltools1/coremltools/-/pipelines/2418650256

@TobyRoseman TobyRoseman merged commit 896bb1c into apple:main Mar 30, 2026
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