Skip to content

feat: meet min_instances and batch_size independently, start gang tasks together - #637

Closed
k82cn wants to merge 2 commits into
xflops:mainfrom
k82cn:feat/independent-warmup
Closed

k82cn wants to merge 2 commits into
xflops:mainfrom
k82cn:feat/independent-warmup

Conversation

@k82cn

@k82cn k82cn commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

min_instances is a warm-up and batch_size is a gang, and the design (RFE591, 4.5 and 4.6) says they are met independently. Dispatch did not do that: a session with pending tasks bound everything through one Statement, and when the gang could not be formed it discarded the whole statement, warm-up executors included. Whether the warm-up held its executors then depended on whether a task happened to be pending when the scheduler ran. That is what made TestGangScheduling::test_single_instance_sessions_are_not_held_back fail intermittently (the gang session was warmed up one executor at a time in the gap between create_session and create_task, then could not get a seventh; see #636 for the test side).

Change

MinMax::is_underused no longer counts the gang size: it compares the executors a session holds with task_demand, min_demand and max_demand (new, with the same bounds as before). compute_demand is renamed session_demand; it adds the gang size while a task is pending and is unchanged for is_ready, is_overused and DRF. A gang is formed all at once by is_satisfied, not one executor at a time.

DispatchAction (scheduler/actions/dispatch.rs) first dispatches the warm-up: for a session with min_instances above 0, while is_underused holds (the executors it has are below what its tasks and min_instances call for, within the instance limits), it binds eligible Idle executors, in a Statement of its own that is always committed. It stops at the task demand and not at min_instances, so with min_instances above 0 a gang whose tasks exceed the cluster can hold a partial set; whether the cluster has the resources is up to the user. With min_instances 0 the gang stays all-or-nothing. Then the existing gang Statement runs; the executors just bound count toward the gang, and when the gang cannot be formed only its own binds are discarded. No new plugin hook and no executor counting in Dispatch.

Behavior change

Executors are created (Allocate) for the session's tasks and min_instances only, so a gang needs one pending task per member: a gang of 4 with one pending task is no longer given four executors. The examples and the e2e tests submit batch_size tasks; RFE591 4.2 and docs/api/types.md say so.

A session that sets min_instances and batch_size to the same number no longer gets an all-or-nothing group: the warm-up holds what it can, and a bound executor takes a pending task whether or not the gang is complete. The scheduler does not hold a gang's tasks back for it; the service has to make sure of that. For an all-or-nothing group, set batch_size alone. In the repository, examples/rl/search-r1 already does this (trainer.py uses batch_size, rollout.py uses warmup); the RFE584 text still said the trainer used warmup=N, so it is corrected. docs/api/types.md, sdk/python/docs/API.md and RFE591 (new 4.3.1, the Dispatch steps, the edge cases and the test plan) describe the behavior.

Tests

  • plugins/minmax.rs: is_underused counts the tasks and the warm-up but not the gang.
  • scheduler/mod.rs, with real controller storage and a cycle loop, both priority+das and drf+das: a gang of 7 with min_instances 7 on 6 slots holds 6, and with min_instances 0 holds none; a gang of 4 with min_instances 2 and one task holds 2 on 3 slots, and with four tasks 4 on 4; min_instances 3 without tasks binds exactly 3. The first two fail on main's dispatch.rs (they get 0 executors).
  • test_competing_gangs_never_hold_a_partial_set now creates its gangs without min_instances: with min_instances equal to the gang size, one gang holds 4 and the other 2 by design.
  • cargo test -p flame-session-manager (300 passed with --test-threads=6; at the default parallelism some tests hit the per-process file limit on my machine), clippy -D warnings, rustfmt.
  • testing/e2e/tests/test_session.py has the same change as fix: a gang's min_instances is 0 or batch_size and a kept-warm gang binds together #636 (gangs created with batch_size only and one long task per executor, because min_instances equal to the gang size would now hold executors by design). fix: a gang's min_instances is 0 or batch_size and a kept-warm gang binds together #636's CI showed that change needs another fix (a session with running tasks cannot be closed), which this pull request does not have yet.
  • Not run: the e2e tests (they need a cluster) and the Python/Rust SDK suites.

@k82cn
k82cn force-pushed the feat/independent-warmup branch from d7844b0 to 2ad855f Compare October 27, 2026 06:24
@k82cn
k82cn force-pushed the feat/independent-warmup branch from a29ca43 to e3b5b75 Compare October 27, 2026 07:00
@k82cn

k82cn commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #636: the independent warm-up design was dropped in favor of tying a gang's min_instances and max_instances to its batch_size.

@k82cn k82cn closed this Oct 27, 2026
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.

1 participant