-
Notifications
You must be signed in to change notification settings - Fork 6
Add serialize_allocations to chain Slurm allocations #436
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
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
2a4a973
Do not hold an idle job runner for untriggered actions
daniel-thom fa815ab
Ignore id-less actions in the idle-exit check
daniel-thom 7e79dcb
Fix minute-boundary flake in the api-stats endpoint test
daniel-thom d94daef
Adjust interval
daniel-thom 149e409
Merge branch 'main' into feat/chained-allocations
daniel-thom 09e0a0a
Add serialize_allocations to chain Slurm allocations
daniel-thom c60e795
Reject --job-prefix for serialized schedulers
daniel-thom f971e15
Polish chained allocations: jitter, docs, list column, example
daniel-thom 1cc178b
Return stored serialize_allocations from create scheduler
daniel-thom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
6 changes: 3 additions & 3 deletions
6
...ba1d5d9ef4efdd7c33f86a751473267f7bd7.json → ...6cfc175f1d41b19f69905ddee407ebbcf2fc.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # Chained Allocations | ||
|
|
||
| Some workflows need more wall time than any single Slurm allocation provides. A chain of 500 | ||
| sequential jobs at 2-4 hours each is weeks of serial work, but partitions typically cap allocations | ||
| at hours. You need one allocation to run as many jobs as fit, exit, and the next to pick up where it | ||
| left off. | ||
|
|
||
| Set `serialize_allocations` on a Slurm scheduler and torc submits every allocation for that | ||
| scheduler under one shared Slurm job name with `--dependency=singleton`. Slurm then runs them | ||
| strictly one at a time. Submit them all up front and they chain themselves, with no long-running | ||
| process on the login node. | ||
|
|
||
| ## Configuring a Scheduler | ||
|
|
||
| ```yaml | ||
| slurm_schedulers: | ||
| - name: chain | ||
| account: my_account | ||
| walltime: "12:00:00" | ||
| nodes: 1 | ||
| serialize_allocations: true | ||
|
|
||
| resource_requirements: | ||
| - name: serial | ||
| num_cpus: 104 | ||
| memory: "200g" | ||
| runtime: "PT4H" | ||
| ``` | ||
|
|
||
| A complete runnable spec is at `examples/yaml/chained_allocations.yaml`. | ||
|
|
||
| Or on an existing scheduler: | ||
|
|
||
| ```bash | ||
| torc slurm create <workflow_id> -n chain -a my_account -W 12:00:00 --serialize-allocations | ||
| torc slurm update <scheduler_id> --serialize-allocations true | ||
| ``` | ||
|
|
||
| Then submit the whole chain at once: | ||
|
|
||
| ```bash | ||
| torc slurm schedule-nodes <workflow_id> -n 167 | ||
| ``` | ||
|
|
||
| All 167 allocations enter the queue immediately. Slurm starts one, holds the rest, and releases the | ||
| next each time the current one ends. | ||
|
|
||
| ## How Many Allocations to Submit | ||
|
|
||
| Divide the total work by what one allocation can absorb. A worker claims jobs until its remaining | ||
| wall time can no longer fit the next one, so with a 12-hour walltime and a declared `runtime` of | ||
| `PT4H`, each allocation completes at least three jobs: | ||
|
|
||
| ``` | ||
| allocations = ceil(total_jobs / floor(walltime / runtime)) | ||
| = ceil(500 / floor(12 / 4)) = 167 | ||
| ``` | ||
|
|
||
| Round up. Over-submitting is cheap: once the workflow has no runnable jobs left, the finishing | ||
| worker cancels every allocation still queued for the workflow, so the surplus never starts. | ||
|
|
||
| ## Why the Chain Beats Scheduling on Shutdown | ||
|
|
||
| A worker could submit its own replacement as it exits, but that pays Slurm's full | ||
| submit-and-schedule latency at every link — 167 times over — and makes each link's submission depend | ||
| on its predecessor exiting cleanly. A chained allocation is already sitting in the queue when its | ||
| predecessor ends, so it is typically released the moment the slot frees. On clusters that accrue age | ||
| priority for dependency-held jobs (`PriorityFlags=ACCRUE_ALWAYS` in the Slurm config), each link | ||
| also builds priority while its predecessor runs; by default Slurm starts the age clock only when the | ||
| dependency clears. | ||
|
|
||
| ## Wall Time and Job Runtime | ||
|
|
||
| The server only hands a worker jobs whose declared `runtime` fits in the allocation's remaining wall | ||
| time. This is what makes the handoff clean: an allocation stops claiming once the next job no longer | ||
| fits, idles briefly, and exits, releasing the slot early rather than sitting idle until walltime. | ||
|
|
||
| Declare `runtime` at or above the worst case you expect. If a job overruns its declared runtime it | ||
| is terminated when the walltime expires, and jobs downstream of it are left blocked with nothing to | ||
| unblock them — which ends the chain, since the remaining queued allocations have no runnable work. | ||
|
|
||
| ## Scope of the Chain | ||
|
|
||
| The shared job name is derived from the workflow ID and the scheduler ID, so: | ||
|
|
||
| - Two schedulers in one workflow chain independently. | ||
| - The same workflow submitted twice chains independently per scheduler. | ||
| - Allocations added later — by a second `schedule-nodes` call, or by a `schedule_nodes` action | ||
| firing from a compute node — join the existing chain rather than running alongside it. | ||
|
|
||
| Slurm scopes `singleton` to a job name **per user**, so the name is prefixed with `torc-` to keep | ||
| the chain from serializing against your unrelated Slurm jobs. | ||
|
|
||
| Because the chain depends on every allocation sharing one fixed name, | ||
| `torc slurm schedule-nodes --job-prefix` is rejected for a serialized scheduler: a per-invocation | ||
| prefix would change the name and fork the chain. | ||
|
|
||
| ## Interaction with `extra` | ||
|
|
||
| `extra` is emitted after torc's own `#SBATCH` directives, so a `--dependency` set there overrides | ||
| the generated `--dependency=singleton` and breaks the chain. Use `extra` for unrelated flags | ||
| (`--reservation`, `--constraint`) when serializing allocations. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| name: "Chained Allocations" | ||
| description: "Sequential jobs spanning multiple Slurm allocations chained with serialize_allocations" | ||
|
|
||
| # A sequence of jobs whose total runtime exceeds any single allocation's walltime. | ||
| # The scheduler below sets serialize_allocations, so every allocation is submitted | ||
| # under one shared Slurm job name with --dependency=singleton: Slurm runs them one | ||
| # at a time, and each picks up where its predecessor left off. | ||
| # | ||
| # See docs: specialized/hpc/chained-allocations.md | ||
|
|
||
| jobs: | ||
| - name: "step1" | ||
| command: "echo 'Running step 1' && sleep 10" | ||
| resource_requirements: "serial" | ||
|
|
||
| - name: "step2" | ||
| command: "echo 'Running step 2' && sleep 10" | ||
| depends_on: ["step1"] | ||
| resource_requirements: "serial" | ||
|
|
||
| - name: "step3" | ||
| command: "echo 'Running step 3' && sleep 10" | ||
| depends_on: ["step2"] | ||
| resource_requirements: "serial" | ||
|
|
||
| - name: "step4" | ||
| command: "echo 'Running step 4' && sleep 10" | ||
| depends_on: ["step3"] | ||
| resource_requirements: "serial" | ||
|
|
||
| resource_requirements: | ||
| # Declare runtime at or above the worst case: the server only hands a worker a job | ||
| # whose declared runtime fits the allocation's remaining walltime, which is what | ||
| # makes each allocation exit cleanly when the next job no longer fits. | ||
| - name: "serial" | ||
| num_cpus: 4 | ||
| num_nodes: 1 | ||
| memory: "8g" | ||
| runtime: "PT2H" | ||
|
|
||
| slurm_schedulers: | ||
| - name: "chain" | ||
| account: "demo_project" | ||
| nodes: 1 | ||
| walltime: "04:00:00" | ||
| serialize_allocations: true | ||
|
|
||
| actions: | ||
| # Submit the whole chain up front. With a 4-hour walltime and 2-hour job runtime, | ||
| # each allocation completes floor(4 / 2) = 2 jobs, so 4 jobs need | ||
| # ceil(4 / 2) = 2 allocations. Over-submitting is safe: once no runnable jobs | ||
| # remain, the finishing worker cancels the surplus still sitting in the queue. | ||
| - trigger_type: "on_jobs_ready" | ||
| action_type: "schedule_nodes" | ||
| jobs: ["step1"] | ||
| scheduler: "chain" | ||
| scheduler_type: "slurm" | ||
| num_allocations: 2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.