-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extend buffer donation aliasing APIs #8721
base: master
Are you sure you want to change the base?
Conversation
0dc6476
to
03e26ac
Compare
019f145
to
5cb4a6c
Compare
I had
but that was failing |
5cb4a6c
to
ed28bcd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, LGTM. I do think it would be better to leave non-trivial refactorings for another PR. It would make reviewing easier.
That said, I'm not entirely familiar with this buffer donor system. Maybe @tengyifei @lsy323 @vanbasten23 @bhavya01 could help review.
ed28bcd
to
6016023
Compare
3dac1fd
to
b6a9371
Compare
As suggested by @ysiraichi, so we don't block on this needed PR, deferring:
In addition to separating the following as separate PRs (I'll do so shortly after closing this one):
|
b6a9371
to
3904c2c
Compare
Just so we are clear: are you closing this one? Or do you mean after this gets merged? |
I will do these as separate PRs after this one is merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one comment. Looks good otherwise.
Could you also change the PR description so we know exactly what changes this PR is introducing?
std::vector<size_t> user_config_buffer_donor_indices; | ||
if (GetAliasWithBufferDonorConfig()) { | ||
user_config_buffer_donor_indices = | ||
GetBufferDonorIndexFromUserConfig(parameters_data); | ||
} | ||
|
||
// Both LTC and user config buffer donation indices vector are originally | ||
// sorted. In order to ensure that we get deterministic hash across runs, in | ||
// cases where there is an alternating aliasing among auto LTC and user | ||
// specified buffer donor indices, we ensure we retain the sorting and remove | ||
// any duplicates when merging the two indices vector. | ||
std::vector<size_t> buffer_donor_indices; | ||
buffer_donor_indices.reserve( | ||
std::max(ltc_buffer_donor_indices.size(), | ||
user_config_buffer_donor_indices.size())); | ||
std::set_union(ltc_buffer_donor_indices.cbegin(), | ||
ltc_buffer_donor_indices.cend(), | ||
user_config_buffer_donor_indices.cbegin(), | ||
user_config_buffer_donor_indices.cend(), | ||
std::back_inserter(buffer_donor_indices)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this supposed to be a refactoring PR? Reason I'm asking is because these lines are changing the old behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is the actual PR that resolves the PFR. We're extending the buffer donation to simultaneously include user config buffer donations with LTC aliasing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay. I'll be frank I don't understand the internal details that well. In fact nobody on the team does. So I've asked some questions on the PR.
t1 += 2 | ||
xm.mark_step() | ||
|
||
self.assertEqual(met.metric_data("InputOutputAliasCount")[1], 2.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to test that t0 can no longer be used?
self.assertEqual(met.metric_data("InputOutputAliasCount")[1], 2.0) | ||
|
||
def test_user_config_donation_with_ltc_donation_overlap(self): | ||
with alias_with_buffer_donor_config_context(True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this config context do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It enables the general behavior of buffer donation. In other words, this (_xla_set_enable_alias_with_buffer_donor_config
) needs to be set, so that the tensors (with the associated XLA device data backend) that were explicitly marked to be donated (_set_buffer_donation
) can be donated in the next execution (i.e. mark step) [1]. It's effectively a general opt-in for the entire donation behavior (arguably we wouldn't need it since _set_buffer_donation
is already assuming that the user does intend to explicitly donate it, but I just kept it as is).
#8711 describes the problem and use case, but Jack introduced this in the context of dynamo execution (#6587). Since it's an opt-in, we want to give users the flexibility to explicitly annotate the donation (precisely when they don't need the tensor after mark step). This is particularly helpful with the gradient accumulation (and scan), since we can't do in-place mutations of the fn parameters (aliasing is uncaptured by LTC), so this allows us to mitigate / close that gap. The main change in this PR, to resolve the PFR, is that we enable LTC and buffer donation to coexist (and alleviate the former constrained fallback behavior: if no LTC aliasings + user config is enabled -> donate the buffers). It doesn't alter the original intended behavior, since this heuristic is still directly maintained - but we widen the applications.
[1] XLA HLO donation ref: https://github.com/openxla/xla/blob/1c7d5f62e3b4c90a4b3484429c5042c69ceb5c5b/xla/service/hlo.proto#L479
self.assertIn('XlaSetBufferDonation', met.counter_names()) | ||
self.assertEqual(met.counter_value('XlaSetBufferDonation'), 1) | ||
t1 = t0 + 1 | ||
torch_xla._XLAC._xla_sync_multi([t0, t1], [str(xla_device)], True, False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does sync_multi do? Is it the same as mark_step?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly, but more flexible. It allows me to specify sync_xla_data=False
, so that I can ensure that the aliasing is due to the user config (explicit buffer donation), and not auto LTC aliasings. So sync_ltc_data
in SyncTensorsConfig
will be false, so it won't include the default LTC aliasing.
I'll add a comment, since that's the motivation behind using it over mark_step.
@@ -95,8 +95,7 @@ class XLAGraphExecutor : public torch::lazy::LazyGraphExecutor { | |||
torch::lazy::BackendDataPtr GetBaseSeedData( | |||
const torch::lazy::BackendDevice& device); | |||
|
|||
void SetAliasWithBufferDonorConfig(bool should_alias); | |||
|
|||
void SetAliasWithBufferDonorConfig(bool enable_alias); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you've renamed "should" to "enable". Does this imply some feature change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I understand using "should" for donating buffers (_set_buffer_donation
), because it may not necessarily donate it, since it depends whether this config is enabled (_xla_set_enable_alias_with_buffer_donor_config
). I renamed the parameters for _xla_set_enable_alias_with_buffer_donor_config
/SetAliasWithBufferDonorConfig
, since we are enabling/allowing explicitly marked tensors (_set_buffer_donation
) to be donated, so I figured that renaming it to "enable" is more suitable.
No worries. Thanks for taking a look - let me know if I was able to answer these. I'll revise with the test change asap. |
Enables #8711. In particular, it alleviates the fallback aliasing logic for user config. Previously, it would only be applied if auto LTC did not infer any needed aliasing which is a semantically suboptimal surface area. In this PR, we modify this behavior to always accommodate explicitly donated buffers, working simultaneously with LTC, IF enabled.
In this PR, it is out of scope to address the per-device concerns associated with having global (DeviceArenaContext) metadata for all the devices with respect to aliasing and other dynamo execution -specific logic.