-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Honor --include/--exclude in the SLURM launcher #8304
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -358,7 +358,9 @@ def name(self): | |
| def get_cmd(self, environment, active_resources): | ||
| assert not getattr(self.args, 'detect_nvlink_pairs', | ||
| False), "slurm backend does not support remapping visible devices" | ||
| total_process_count = sum(self.resource_pool.values()) | ||
| # --include/--exclude are already resolved into active_resources, so counting the | ||
| # whole pool here would ask srun for slots the user filtered out. | ||
| total_process_count = sum(len(slots) for slots in active_resources.values()) | ||
| srun_cmd = [ | ||
| 'srun', | ||
| '-n', | ||
|
|
@@ -368,12 +370,19 @@ def get_cmd(self, environment, active_resources): | |
| if getattr(self.args, 'slurm_comment', ''): | ||
| srun_cmd += ['--comment', self.args.slurm_comment] | ||
|
|
||
| if self.args.include != "": | ||
| srun_cmd.append('--include') | ||
| srun_cmd.append(f'{self.args.include}') | ||
| if self.args.exclude != "": | ||
| srun_cmd.append('--exclude') | ||
| srun_cmd.append(f'{self.args.exclude}') | ||
| if self.args.include != "" or self.args.exclude != "": | ||
| # srun has no --include, and the NAME[:SLOT,...] syntax DeepSpeed accepts is not | ||
| # a slurm hostlist, so name the hosts that survived the filter instead. | ||
| active_hosts = ",".join(active_resources.keys()) | ||
| srun_cmd.append('--nodelist') | ||
| srun_cmd.append(active_hosts) | ||
|
Comment on lines
+377
to
+378
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a filter leaves multiple active hosts but reduces the task count, such as the new Useful? React with 👍 / 👎. |
||
| # --nodelist alone is only an upper bound: srun documents that a lower task count | ||
| # "may only require a subset of the supplied node list", so it could pack every | ||
| # rank onto one host and silently drop a host the filter kept. --nodes pins the | ||
| # count, and runner.py forbids --num_nodes alongside a resource filter, so the | ||
| # branch below cannot also set it. | ||
| srun_cmd.append('--nodes') | ||
| srun_cmd.append(f'{len(active_resources)}') | ||
| if self.args.num_nodes > 0: | ||
| srun_cmd.append('--nodes') | ||
| srun_cmd.append(f'{self.args.num_nodes}') | ||
|
|
||
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 ran this against 8fa2478 in a clean container. The
--includepath does what the description says. One thing the description does not name: this line is unconditional, so it also changes-nfor--num_gpusand--num_nodes.runner.pytrimsactive_resourcesfor those two flags as well (--num_nodesat runner.py:521,--num_gpusat runner.py:529), andget_cmdnow sizes the job fromactive_resourcesinstead ofself.resource_pool. Building the srun command at this SHA and at the merge base aa3914d, on the same two-node four-slot pool the launcher tests use:The bottom two look correct to me rather than wrong:
world_info_base64is encoded from the same trimmedactive_resourcesat runner.py:543, so-n 8against a 4 rank world info was already inconsistent. My point is only that they are unpinned.test_slurm_runner_resource_filterparametrizes include and exclude, andtest_slurm_runnerasserts the unfiltered 8, so nothing covers the two flags that now also move.Two more cases in that parametrize would cover it, though they need main()'s trim replicated the way
parse_inclusion_exclusionalready is, since it happens after it. Naming the wider scope in the description would work too.How I got the numbers: I called
parse_inclusion_exclusionand then replicated runner.py:521-533 in a probe, then calledSlurmRunner.get_cmd. I did not runmain(), and I have no slurm cluster here, so the--nodelistand--nodessemantics in your description are the only part I did not check.