Skip to content

Elide redundant same-device copies in PropagateDevicePass (#20914)#20914

Merged
meta-codesync[bot] merged 1 commit into
pytorch:mainfrom
Conarnar:export-D111992997
Jul 15, 2026
Merged

Elide redundant same-device copies in PropagateDevicePass (#20914)#20914
meta-codesync[bot] merged 1 commit into
pytorch:mainfrom
Conarnar:export-D111992997

Conversation

@Conarnar

@Conarnar Conarnar commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the same
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
_h2d_copy(_d2h_copy(x)) when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Reviewed By: Gasoonjia

Differential Revision: D111992997

Copilot AI review requested due to automatic review settings July 14, 2026 21:05
@pytorch-bot

pytorch-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/20914

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit 44fea49 with merge base e500fee (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jul 14, 2026
@meta-codesync

meta-codesync Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@Conarnar has exported this pull request. If you are a Meta employee, you can view the originating Diff in D111992997.

@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

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.

Pull request overview

This PR improves PropagateDevicePass by removing redundant host/device transfer pairs that occur when two delegated regions execute back-to-back on the same device, avoiding an unnecessary device→host→device round-trip while preserving true cross-device transfers.

Changes:

  • Add a third phase to PropagateDevicePass that detects and elides _h2d_copy(_d2h_copy(x)) when x is already on the same target device.
  • Add targeted tests that construct two consecutive delegates with per-op target devices and verify redundant same-device copies are removed while cross-device copies remain.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
exir/passes/propagate_device_pass.py Adds an optimization pass phase to remove redundant same-device D2H→H2D copy chains after per-boundary copy insertion.
exir/tests/test_propagate_device_pass.py Adds a custom partitioner to force per-add delegation and two tests validating same-device elision and cross-device preservation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@meta-codesync meta-codesync Bot changed the title Elide redundant same-device copies in PropagateDevicePass Elide redundant same-device copies in PropagateDevicePass (#20914) Jul 14, 2026
Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 14, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Differential Revision: D111992997
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 9e4ab31 to ce30c8b Compare July 14, 2026 21:15
Copilot AI review requested due to automatic review settings July 14, 2026 21:15

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 14, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Differential Revision: D111992997
@Conarnar
Conarnar force-pushed the export-D111992997 branch from ce30c8b to 7c91a10 Compare July 14, 2026 21:25
@meta-codesync meta-codesync Bot changed the title Elide redundant same-device copies in PropagateDevicePass (#20914) Elide redundant same-device copies in PropagateDevicePass Jul 14, 2026
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 7c91a10 to b2d7712 Compare July 14, 2026 23:14
Copilot AI review requested due to automatic review settings July 14, 2026 23:14

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread exir/tests/test_propagate_device_pass.py
Copilot AI review requested due to automatic review settings July 14, 2026 23:20
@Conarnar
Conarnar force-pushed the export-D111992997 branch from b2d7712 to 596c42e Compare July 14, 2026 23:20

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Conarnar
Conarnar force-pushed the export-D111992997 branch from 596c42e to e07e470 Compare July 14, 2026 23:26
Copilot AI review requested due to automatic review settings July 14, 2026 23:26

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@meta-codesync meta-codesync Bot changed the title Elide redundant same-device copies in PropagateDevicePass Elide redundant same-device copies in PropagateDevicePass (#20914) Jul 14, 2026
Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 14, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Differential Revision: D111992997
@Conarnar
Conarnar force-pushed the export-D111992997 branch from e07e470 to 0ae723a Compare July 14, 2026 23:31
Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 15, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Differential Revision: D111992997
Copilot AI review requested due to automatic review settings July 15, 2026 01:11
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 0ae723a to ec7ba46 Compare July 15, 2026 01:11

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 15, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Differential Revision: D111992997
@Conarnar
Conarnar force-pushed the export-D111992997 branch from ec7ba46 to 4d2005a Compare July 15, 2026 01:12
Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 15, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Reviewed By: Gasoonjia

Differential Revision: D111992997
Copilot AI review requested due to automatic review settings July 15, 2026 17:07
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 4d2005a to 27d4f20 Compare July 15, 2026 17:07

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 15, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Reviewed By: Gasoonjia

Differential Revision: D111992997
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 27d4f20 to 6510082 Compare July 15, 2026 17:07
Conarnar added a commit to Conarnar/executorch that referenced this pull request Jul 15, 2026
)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Reviewed By: Gasoonjia

Differential Revision: D111992997
Copilot AI review requested due to automatic review settings July 15, 2026 17:43
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 6510082 to 8422b8e Compare July 15, 2026 17:43

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

)

Summary:

PropagateDevicePass inserts H2D/D2H copies per delegate boundary
independently (an H2D before every device delegate input, a D2H after every
device delegate output). When two delegates run consecutively on the *same*
device, this leaves a redundant device -> host -> device round-trip between
them: the first delegate's output is copied to host and immediately copied
back to the same device for the second delegate.

This adds a third phase to PropagateDevicePass that elides
`_h2d_copy(_d2h_copy(x))` when the tensor before the D2H already lives on the
device the H2D copies back to. The device comparison is the correctness guard:
a genuine cross-device move (e.g. cuda:0 -> host -> cuda:1) has differing
devices and is preserved. A D2H that still feeds other (host) consumers keeps
those users and is removed only once it becomes dead. The phase runs only when
enable_non_cpu_memory_planning is set (i.e. when copies were actually
inserted).

This closes the "redundant copies between back-to-back delegates on the same
device" limitation from the device-aware export work.

Reviewed By: Gasoonjia

Differential Revision: D111992997
@Conarnar
Conarnar force-pushed the export-D111992997 branch from 8422b8e to 44fea49 Compare July 15, 2026 17:44
@meta-codesync
meta-codesync Bot merged commit 8daa7f8 into pytorch:main Jul 15, 2026
185 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants