Add scheduler for batched requests - #22035
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22035
Note: Links to docs will display an error until the docs builds have been completed. ✅ You can merge normally! (1 Unrelated Failure)As of commit ae14128 with merge base 5c11944 ( BROKEN TRUNK - The following job failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@claude review this code |
This PR needs a
|
|
Claude finished @metascroy's task in 2m 16s —— View job Code review:
|
| std::int32_t max_batch_size() const { | ||
| return 2 * max_prefill_chunk_size_ + max_decode_sequences_; | ||
| } |
There was a problem hiding this comment.
not sure I follow this
There was a problem hiding this comment.
max_batch_size is the batch size forwarded to the model per step.
This scheduler admits enough work for max_decode_sequences_ and 2 prefill chunks per step. Decode work is always preferred to prefill work.
| using PendingPtr = std::shared_ptr<PendingRequest>; | ||
| using PendingQueue = std::deque<PendingPtr>; | ||
|
|
||
| class Scheduler { |
There was a problem hiding this comment.
ok for now, but going forward I would like to separate scheduler mechanism and scheduler policy. I.e. Mechanism: how the scheduler interface looks like, Policy: how one can use those APIs to achieve a certain behavior, and we may impl more than one policy on the same mechanism. You can imagine on a phone we have a different policy vs. a beefy desktop.
There was a problem hiding this comment.
Absolutely! Focus on the public API (submit/has_work/get_work) for what the interface looks like (and even this I'm planning on modifying a bit as I'm sketching a model runner with concurrent sessions). We can promote to an interface, with this being just one (policy) implementation of that interface. A policy basically is 1-1 with the implementation of the get_work function, and the implementation of get_work here is just an example of a policy.
There was a problem hiding this comment.
To make this clearer, I split out scheduler.h into an interface, with decode_first_scheduler.h a specific implementation / policy.
|
@claude review this code |
|
Claude finished @metascroy's task in 4m 53s —— View job Code review:
|
This PR adds extension/llm/batching/, the scheduling seam for batched LLM serving. It is three headers. types.h holds the vocabulary shared by the runner, scheduler, and executor: an Input is one slice of work for one session, either a prompt chunk or a decode token, and a Task adds the identity used to order and cancel it. scheduler.h is the abstract interface (submit, has_work, get_work, cancel, clear), which is bookkeeping only: it never calls an executor or runs a callback, and it hands tasks back for the caller to complete. decode_first_scheduler.h is the first policy. It fills a batch with queued decodes first, at most one per session, then spends the leftover token budget on prefill, rotating one chunk per session so a long prompt cannot crowd out a decode. Everything is header-only and free of ExecuTorch runtime types, so the CMake target is an INTERFACE library that becomes a real one when the runner lands with a .cpp. Nothing consumes this yet; the runner is the next PR. Tested by 50 gtest cases in scheduler_test.cpp.