mstar.engine.engine#
Functions
|
Name the weights a cached page was produced under, without reading them. |
Classes
|
|
|
|
|
Stop-gap solution: the dynamic loop iters in CurrentForwardPassInfo may be used in two places at once: in _postprocess_batch (for batch N), and in the forward pass for batch N+1, which require different iterations. |
|
- class mstar.engine.engine.Engine(graph_runtime, autocast_dtype=torch.bfloat16, enable_nvtx=False, enable_profile=False)[source]#
Bases:
object- add_request(request_id, overrides=None)[source]#
- Parameters:
request_id (str)
overrides (Mapping[str, ResourceReqConfig] | None)
- Return type:
None
- apply_resident_delta(node_name, delta)[source]#
Match the leader’s resident set on this node. Mutates OffloadDelta by popping off the steps that have already landed. False means not all has landed and the caller must retry before trying the next step.
- Parameters:
node_name (str)
delta (OffloadDelta)
- Return type:
- can_pre_plan(node_name)[source]#
Whether pre-planning this node could stage anything at all.
A node with no pre-planning resource has nothing to stage: its step declaration is empty, so pre_plan_for_batch is guaranteed to bail. Asked BEFORE the plan thread waits on the previous batch’s commit, so a stateless node does not pay that wait to reach a foregone conclusion.
- capture_group(node_name, graph_walk, request_id, request_info)[source]#
The capture bucket this one request would replay, by
cg_key_info; None when the walk has no capture or the submodule does not split by it.A batch spanning two groups matches no capture and runs eager, so the scheduler batches each group on its own when the submodule opts in (
split_batches_by_capture_key).- Parameters:
node_name (str)
graph_walk (str)
request_id (int)
request_info (CurrentForwardPassInfo)
- Return type:
Any | None
- check_ready(node_name, request_id, request_info, allow_reload=True)[source]#
Whether this node can run the request now.
An offloaded request is brought back first; it stays not-ready until that fits, which is the scheduler’s cue to run something else (and, on OOM, to evict). Then each resource takes in whatever the request published elsewhere — a KV transfer from a prefill worker, say — and reports whether that has landed.
The outcome, not a bool: a resource can report the request unservable (
AdmitRuntimeError), and the caller has to fail it rather than scan it again forever.- Parameters:
node_name (str)
request_id (str)
request_info (CurrentForwardPassInfo)
allow_reload (bool)
- Return type:
- check_stop_for_batch(batch, outputs, host_rows=None)[source]#
Each rid’s
submodule.check_stop, as rid -> loops that should stop.Reads tensor values, so it belongs on the caller’s slow-postprocess path rather than in
exec, where the.item()/.cpu()would block the GPU thread. Per-rid like the other stages: a raise fails that request onto the batch, because letting it escape would abandon the check for the rest of the batch and leave their loops running past their stop condition.With
host_rows,check_stop_batchedchecks the batch in one call; if it raises, the per-request path runs so a failure lands on its own request.
- exec(batch)[source]#
Run one step: declare → admit → plan → forward → commit.
Captured replay and the eager forward are the same path. Under a lease the batch is padded to the slot’s shape, preprocess output is staged into the static buffers, and the launch is a replay; everything above the launch is identical.
- Parameters:
batch (ExecutingBatch)
- Return type:
- exec_and_postprocess(batch)[source]#
The forward and its per-rid tail, which belong to the same step: a walk that captured only its forward finishes in
postprocess.prepare_inputsand the stop check stay outside — the worker has to place those itself.- Parameters:
batch (ExecutingBatch)
- Return type:
- extend_prefix_chains(batch, outputs)[source]#
Key what this step generated, from the stop check’s host copy.
- finalize_batch(batch, publish_request_ids=None)[source]#
- Parameters:
batch (ExecutingBatch)
- Return type:
dict[str, dict[str, PublishedInfo]]
- finalize_stopped_requests(batch, request_ids)[source]#
Publish state that must include the last iteration of a stopped loop.
- Parameters:
batch (ExecutingBatch)
- Return type:
None
- get_max_batch_size(node_name, graph_walk)[source]#
Most requests this node will take in one step, or None for no cap.
Two sources: what the submodule says it can batch, and the largest batch this walk captured a graph for — going past that would drop the step to eager, so the scheduler splits instead. Splitting is the scheduler’s job, not the engine’s: the pieces then pipeline like any other batch instead of running back to back.
- load_model(submodules, specs, parallel_groups, device, transfer_engine_info, kv_cache_type=None, model=None)[source]#
- Parameters:
submodules (dict[str, NodeSubmodule])
specs (list[NodeResourceSpec])
parallel_groups (WorkerParallelGroups)
device (device)
transfer_engine_info (TransferEngineInfo)
model (Model | None)
- offload_priority(node_name, request_id, resource_label)[source]#
How much one named resource wants this request gone.
Only the PRIORITY eviction policy asks; it names the resource to consult, since “most worth reclaiming” means something different per resource.
- offload_request(node_name, request_id)[source]#
Move the request off-device across this node’s resources.
Returns what was reclaimed, in whatever each resource counts (pages, today); 0 means nothing moved and the caller should pick another victim.
- postprocess_batch(batch, outputs)[source]#
Per-rid
submodule.postprocess, e.g. the non-capturable tail of a walk whose graph covered only the forward.Per-rid like
prepare_inputs: a raise fails that request and leaves the rest of the batch to route normally.- Parameters:
batch (ExecutingBatch)
outputs (BatchedModelOutput)
- Return type:
None
- pre_plan_for_batch(batch)[source]#
Admit and plan the pre-planning resources a step ahead.
Worth doing only under a lease: the reserved slot is not the one the in-flight replay reads, so this can write its plan buffers on the plan stream while that replay runs.
execthen re-drives the full sweep, where each pre-planned resource promotes what was staged here, and the replay waits on the event recorded here.An unprepared batch declares its step over the capture config’s inputs for the leased bucket, which is why the lease had to come from a batched capture. That step is not cached:
execre-declares it over the real inputs.TODO: pre-planning a packed capture (and chunked prefill) needs the real token counts here, i.e.
prepare_inputsrun ahead of the forward. That needs every submodule’sprepare_inputsto be async-safe — no.item()on a tensor the in-flight step is still producing — which some are not (e.g. qwen3_tts).ExecutingBatch.outputs_readyis the hook for it.Returns False when nothing was planned ahead, in which case
execplans inline.- Parameters:
batch (ExecutingBatch)
- Return type:
- prepare_inputs(batch)[source]#
Per-rid
submodule.prepare_inputs, ontobatch.inputs.Per-rid, so a raise is attributable to one request: record it and take that rid out rather than losing the batch. A rid the submodule declines (returns None) leaves the same way, without being an error.
- Parameters:
batch (ExecutingBatch)
- Return type:
None
- preplan_is_stale(batch)[source]#
Whether the staged plan no longer describes this batch.
- Parameters:
batch (ExecutingBatch)
- Return type:
- reclaimable(node_name, request_id, affected_resources=None)[source]#
What this node’s resources could reclaim from the request. 0 means offloading it would free nothing, so it is not a candidate.
- reload_request(node_name, request_id)[source]#
Bring it back. False when any resource can’t fit it yet, in which case the request stays offloaded and the caller retries later.
- reserve_replay_slot(batch)[source]#
Lease the slot this batch will replay on, before it is dispatched.
Reserving up front is what puts pre-plan(N+1) and replay(N) on different slots. No captured graph for the batch’s shape leaves the lease unset, i.e. the step runs eager.
A batch that hasn’t been through
prepare_inputshas no token count yet, so only a batched capture can serve it — seeCudaGraphRunner.select_batched_bucket.- Parameters:
batch (ExecutingBatch)
- Return type:
SlotLease | None
- reset_pre_plan_for_batch(batch=None)[source]#
Drop planned-ahead state, e.g. when its batch never dispatched.
The resources hold the plan itself. The batch keeps whatever
prepare_inputsproduced — only the plan is redone — but the leased slot’s padding rows are returned so their pages aren’t left attributed to a step that never ran.- Parameters:
batch (ExecutingBatch | None)
- Return type:
None
- take_resident_delta(node_name)[source]#
The moves on this node since the last call, ready for the wire.
Verbatim. Every move in it is one this rank executed, so a rank in the same state can always apply it — which is what makes a refused replay mean the states differ, and nothing else.
- Parameters:
node_name (str)
- Return type:
- class mstar.engine.engine.ExecutingBatch(node_name: str, per_request_info: Mapping[int, mstar.conductor.request_info.CurrentForwardPassInfo], step_context: mstar.engine.resources.step.StepContext, running_batched: bool = False, slot: int | None = None, cg_key_info: typing.Any | None = None, preplan_event: torch.cuda.streams.Event | None = None, preplanned_rids: tuple[int, ...] | None = None, step: mstar.engine.resources.step.SubmoduleStep | None = None, per_request_input_tensors: Mapping[str, dict[str, list[torch.Tensor]]] = <factory>, final_stream_rids: set[str] = <factory>, per_request_input_metadata: Mapping[str, mstar.model.submodule_base.InputMetadata] = <factory>, stream_partition_done_rids: set[str] = <factory>, inputs: list[mstar.model.submodule_base.NodeInputs] | None = None, skipped_rids: set[str] = <factory>, failed_requests: dict[str, str] = <factory>, admit_error: mstar.engine.resources.step.AdmitFailedReason | None = None, failed_resource: str | None = None, outputs: mstar.model.submodule_base.BatchedModelOutput = <factory>, resource_publish_info: dict[str, dict[str, mstar.engine.resources.base.PublishedInfo]] = <factory>, outputs_ready: threading.Event = <factory>, commit_done: threading.Event = <factory>, completion_event: torch.cuda.streams.Event | None = None, launch_started_event: threading.Event | None = None, exec_timings: mstar.profile.worker.ExecTimings = <factory>)[source]#
Bases:
object- Parameters:
node_name (str)
per_request_info (Mapping[int, CurrentForwardPassInfo])
step_context (StepContext)
running_batched (bool)
slot (int | None)
cg_key_info (Any | None)
preplan_event (Event | None)
step (SubmoduleStep | None)
per_request_input_tensors (Mapping[str, dict[str, list[Tensor]]])
per_request_input_metadata (Mapping[str, InputMetadata])
inputs (list[NodeInputs] | None)
admit_error (AdmitFailedReason | None)
failed_resource (str | None)
outputs (BatchedModelOutput)
resource_publish_info (dict[str, dict[str, PublishedInfo]])
outputs_ready (Event)
commit_done (Event)
completion_event (Event | None)
launch_started_event (Event | None)
exec_timings (ExecTimings)
- admit_error: AdmitFailedReason | None = None#
- exec_timings: ExecTimings#
- inputs: list[NodeInputs] | None = None#
- outputs: BatchedModelOutput#
- per_request_info: Mapping[int, CurrentForwardPassInfo]#
- per_request_input_metadata: Mapping[str, InputMetadata]#
- register_admit_error(reason, failed_resource=None)[source]#
- Parameters:
reason (AdmitFailedReason)
failed_resource (str | None)
- register_prepare_batch(inputs)[source]#
- Parameters:
inputs (list[NodeInputs])
- release_waiters()[source]#
Let anything waiting on this step proceed.
Called on every exit from
exec, so a step that raised before publishing outputs or committing doesn’t strand the thread preparing the next one.
- property request_ids#
- step: SubmoduleStep | None = None#
- step_context: StepContext#
- class mstar.engine.engine.ForwardPassInfoWrapper(info, metadata)[source]#
Bases:
objectStop-gap solution: the dynamic loop iters in CurrentForwardPassInfo may be used in two places at once: in _postprocess_batch (for batch N), and in the forward pass for batch N+1, which require different iterations. The InputMetadata is built per executing batch, so its value is guaranteed to be up-to-date.
TODO: the long-term solution is to maybe move the dynamic loop iters off of CurrentForwardPassInfo entirely.
- Parameters:
info (CurrentForwardPassInfo)
metadata (InputMetadata)
- info: CurrentForwardPassInfo#
- metadata: InputMetadata#
- class mstar.engine.engine.SubmoduleManagement(submodule: mstar.model.submodule_base.NodeSubmodule, forward: Callable, forward_batched: Callable, joint_comm_group: mstar.distributed.communication.JointGroups, resources: dict[str, mstar.engine.resources.base.Resource], cuda_graph_runner: mstar.engine.cuda_graph_runner.CudaGraphRunner | None = None, piecewise_runners: dict[str, mstar.engine.cuda_graph_runner.PiecewiseCudaGraphRunner] = <factory>)[source]#
Bases:
object- Parameters:
submodule (NodeSubmodule)
forward (Callable)
forward_batched (Callable)
joint_comm_group (JointGroups)
cuda_graph_runner (CudaGraphRunner | None)
piecewise_runners (dict[str, PiecewiseCudaGraphRunner])
- cuda_graph_runner: CudaGraphRunner | None = None#
- joint_comm_group: JointGroups#
- property needs_slot_fence: bool#
Whether reusing a slot has to wait out the GPU work that last held it — true exactly when a resource stages into a reused host buffer.
- property next_slot: int#
an int read is atomic under the GIL, and the only other leaser is the plan thread, which is gated on the previous batch’s
commit_done.- Type:
The slot the next lease hands out. Read unlocked
- piecewise_runners: dict[str, PiecewiseCudaGraphRunner]#
- set_piecewise_slot(slot)[source]#
Point the region runners at this batch’s slot, on the GPU thread just before its forward. Set here rather than at lease time: leasing runs ahead of the forward (pre-plan reserves N+1’s slot while N is in flight), so a lease-time write would race the replay reading
_current_slot.- Parameters:
slot (int)
- Return type:
None
- submodule: NodeSubmodule#