Skip to content

[Train] Sort Local Train Workers by GPU id#40953

Merged
matthewdeng merged 12 commits intoray-project:masterfrom
woshiyyya:train/sort_worker_by_device_id
Nov 17, 2023
Merged

[Train] Sort Local Train Workers by GPU id#40953
matthewdeng merged 12 commits intoray-project:masterfrom
woshiyyya:train/sort_worker_by_device_id

Conversation

@woshiyyya
Copy link
Member

@woshiyyya woshiyyya commented Nov 5, 2023

Why are these changes needed?

Sort the local Ray Train workers according to the GPU device id. This ensures that the allocated GPU == "cuda:{local_rank}". More details in #40803

Related issue number

Close #40803

Checks

  • I've signed off every commit(by using the -s flag, i.e., git commit -s) in this PR.
  • I've run scripts/format.sh to lint the changes in this PR.
  • I've included any doc changes needed for https://docs.ray.io/en/master/.
    • I've added any new APIs to the API Reference. For example, if I added a
      method in Tune, I've added it in doc/source/tune/api/ under the
      corresponding .rst file.
  • I've made sure the tests are passing. Note that there might be a few flaky tests, see the recent failures at https://flakey-tests.ray.io/
  • Testing Strategy
    • Unit tests
    • Release tests
    • This PR is not tested :(

Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
@woshiyyya woshiyyya marked this pull request as ready for review November 6, 2023 19:03
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
# More details: https://github.com/ray-project/ray/issues/40803
def get_lowest_gpu_id(worker) -> int:
gpu_ids = worker.metadata.resource_ids.get("GPU", [])
return min(map(int, gpu_ids), default=0)
Copy link
Contributor

Choose a reason for hiding this comment

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

Converting to int won't work in the future if we support UUIDs (e.g for MIG). Maybe we can first try to convert to int and then fallback to string?

Copy link
Member Author

@woshiyyya woshiyyya Nov 15, 2023

Choose a reason for hiding this comment

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

Got it. Make sense. I've made take str ID as a backup.

Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering if we should update the name of this method now that it's no longer grouping but also sorting. At the very least we should update the docstring.

In the future we may want to start generalizing this more (e.g. have it be a generic sort function that takes in a comparator) and define the comparison logic upstream in the caller, since this IP/GPU sorting logic doesn't actually belong to the "worker group", but the "backend" layer on top of it.

Copy link
Member Author

@woshiyyya woshiyyya Nov 15, 2023

Choose a reason for hiding this comment

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

I agree. This is a temporary solution for now. We should actually put the ranking allocation logic into backend executor (e.g. here:

def _create_rank_world_size_mappings(self) -> List[Dict]:
) and support different allocation strategies in the future. I'll update the name and docstring. What about naming it as sort_workers_by_ip_and_gpu_id?

"pids": [0, 1, 2, 3, 4, 5, 6, 7],
"ips": ["2", "2", "1", "1", "2", "1", "1", "2"],
"gpu_ids": [None] * 8,
"expected_local_ranks": None, # No expected ranks for CPU workers
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should still test default sorting behavior when there are no GPU IDs?

Copy link
Member Author

@woshiyyya woshiyyya Nov 15, 2023

Choose a reason for hiding this comment

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

When using cpu actors, GPU ids should be empty, then the sorted order will be non-deterministic since all the worker has the same key 0.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I think sort will retain the ordering when the entries have the same sort value. But to your point I don't know if this is guaranteed or just based on the implementation.

entries = [5, 4, 3, 2, 1]
print(entries)

entries.sort(key = lambda x: 0)
print(entries)

entries.sort(key = lambda x: x)
print(entries)
[5, 4, 3, 2, 1]
[5, 4, 3, 2, 1]
[1, 2, 3, 4, 5]

Copy link
Member Author

@woshiyyya woshiyyya Nov 16, 2023

Choose a reason for hiding this comment

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

Ah I got you. Seems that the python's sort will maintain the order if multiple entries have identical keys: https://docs.python.org/3.7/howto/sorting.html#sort-stability-and-complex-sorts

I'll add a test for it.

woshiyyya and others added 4 commits November 14, 2023 21:46
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
@matthewdeng matthewdeng merged commit 0e7a481 into ray-project:master Nov 17, 2023
ujjawal-khare pushed a commit to ujjawal-khare-27/ray that referenced this pull request Nov 29, 2023
Signed-off-by: woshiyyya <xiaoyunxuan1998@gmail.com>
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.

[Train] Mismatched device error with HF Accelerate when local rank != device id

2 participants