Environment variables#
Runtime knobs M* reads from the environment. New variables should be documented here as they are introduced.
Communication#
Variable |
Default |
Meaning |
|---|---|---|
|
|
Transport selection for the ZeroMQ control mesh (see
|
|
|
Which graph runtime a worker builds (see
|
|
|
How messages are encoded on every communicator edge (see
|
|
constructor’s protocol |
Overrides the communicator protocol ( |
|
|
Host used to build peer endpoints when the protocol is |
|
|
Base of the deterministic entity-id → TCP port map ( |
|
|
|
|
|
SHM tensor-transport implementation. |
|
random per launch |
Mixed into the namespace of the SHM tensor files and arena segments,
so no two launches share names: not a restart on the same socket
prefix, and not two deployments that share |
|
|
Base directory for host-staged KV snapshots when remote KV transfer uses SHM. Each deployment creates a private child directory here; request cleanup removes snapshots, and startup removes directories left by dead deployments. All workers sharing KV snapshots must see the same filesystem. |
|
|
Size of each arena segment. The arena grows segment by segment;
existing segments never move (registrations stay valid). A
segment’s /dev/shm pages are committed when it is created (pinned
segments always were, by |
|
|
Growth cap PER ENTITY. Every entity (workers + the api-server data
worker) creates its own arena, so node-wide /dev/shm demand can
reach |
|
|
Strict mode only ( |
|
|
Degrade gracefully at the segment cap: stage the tensor through the
per-uuid file protocol instead — slower, never fails, matching the
file transport’s saturation behavior. |
|
|
Optional grace before spilling, for deployments where another thread frees slots concurrently. Default 0: spill immediately (a worker cannot receive ACKs while it waits). |
|
|
|
|
|
Budget for TOTAL pinned host memory PER PROCESS, distinct from the
segment cap (pinned pages come out of the OS’s pageable pool
system-wide). Node-wide pinned demand is approx
|
|
|
TTL backstop for abort-orphaned slots (a request aborted after
staging but before all consumer ACKs defers reclaim forever).
A slot older than the request timeout cannot have a legitimate
reader, so a bound safely above it (recommend >= 2x the request
timeout) cannot race a real consumer. |
|
|
Under |
|
|
NCCL’s own variable. Every worker runs on the conductor’s host, so
the conductor sets |
|
|
PyTorch’s variable for the Gloo groups next to each TP/SP group.
Same rule: the conductor sets |
Models#
Per-model knobs, read when the submodule is built. They are scoped to one model, so they are named for it.
Variable |
Default |
Meaning |
|---|---|---|
|
|
BAGEL: batch several requests through the ViT encoder in one forward.
Off by default because flash-attn’s varlen reductions across packed
images produce small bf16 drift, which at greedy |
|
|
BAGEL: accelerator graph capture of the ViT block loop, over the node’s
ragged attention resource (see Adding a New Model). Requires the
deployment option |
|
|
Comma-separated token-count buckets to capture, when
|
|
|
Comma-separated batch sizes to capture. Read only when
|
|
unset |
Cosmos3: any nonempty value disables denoise, prefill and reasoner
decode capture. The deployment option
|
|
unset |
Cosmos3: any nonempty value disables only the understanding-tower
prefill capture. Denoise and reasoner decode captures remain eligible
when |
|
unset |
OmniVoice: load weights from this local directory instead of the checkpoint the registry names. For serving a fine-tune of the same architecture off a mounted volume, where the registry entry would otherwise pull the public weights from the Hub. |
Serving (Python frontend)#
Read by mstar-serve / mstar.api_server.entrypoint.
Variable |
Default |
Meaning |
|---|---|---|
|
|
Request body limit on every route, as in the Rust frontend: a larger
body gets a 413, refused on its |
|
|
Mount the app under a URL sub-path. Set it when an ingress routes the
deployment at a prefix and does not strip that prefix before the
request reaches the pod (Run:AI serves a workload at
|
|
|
Largest |
|
unset |
API key (read by |
|
unset |
Silero VAD ONNX file ( |
|
unset |
Pipecat Smart Turn v3 ONNX file for |
Serving (Rust frontend)#
Read by the mstar-server binary and its bridge
(mstar-serve --rust-frontend; see Installation).
Variable |
Default |
Meaning |
|---|---|---|
|
unset |
Path to the |
|
unset |
Same rule as the Python server ( |
|
|
Per-request budget in the Rust frontend; on expiry the client gets an error and the request is aborted in the backend. |
|
|
Sample rate stamped on |
|
|
Allow |
|
|
Admission cap on in-flight generation requests; beyond it clients
get an immediate 503 instead of queueing into the request timeout.
|
|
|
Request body limit (multipart uploads included). |
|
|
When a long prompt is encoded as parallel chunks, set
|
|
set by the launcher |
The class name of the model’s adapter in |
|
unset |
Path to a HuggingFace |
Rust frontend limitations#
The Rust frontend carries no audio encoder or media muxer (the Python frontend
uses soundfile / ffmpeg), so two surfaces degrade:
/v1/audio/speechproduces onlywavandpcm. Any otherresponse_format(mp3,opus,flac, …) is rejected with a 400 rather than silently returned as WAV. Run the Python frontend for compressed containers./v1/videos/generations(Cosmos3) returns the video-only mp4. When a request setsgenerate_sound, Cosmos3 generates a separate audio track that mstar muxes into the mp4 as an AAC track; the Rust frontend cannot mux it, so the audio is dropped and a warning is logged. Do not setgenerate_soundon the Rust frontend (it spends compute on a track the client won’t receive), or run the Python frontend for sound video.
Request media#
Read by the model’s media loaders in the data worker’s preprocess thread,
behind either frontend. All four are also checked once when the data worker
starts (mstar.model.media_limits.check_media_limits()), so an invalid
value stops the server instead of failing every media request. The pixel and
audio caps hold for a request’s files together (mstar.model.media_limits.RequestMediaBudget),
so attaching more files does not multiply them.
Variable |
Default |
Meaning |
|---|---|---|
|
|
Pixels a request’s images may decode to, summed over them (see
|
|
|
Pixels a request’s videos may decode to (see
|
|
|
Images, audio clips and videos one request may attach, together (see
|
|
|
Seconds a request’s audio clips may decode to, summed over them (see
|
Worker scheduling#
Variable |
Default |
Meaning |
|---|---|---|
|
config’s |
Async scheduling for lockstep-parallel (TP / SP) nodes; overrides the
deployment config’s |
|
|
Pre-plan the speculative batch’s attention on a dedicated thread
while the previous replay runs. |
|
|
The decode batch sizes a model captures as CUDA graphs (Qwen3.5 reads
it; a model with its own ladder reads it the same way). A decode step
runs at the smallest bucket that holds its rows, so the ladder bounds
both the rows per step and the graph memory; narrow it (for example
|
|
|
Publish resource state (KV pages, positions) only for the requests
whose frame or completion carries it: |
|
|
Cap on back-to-back speculative steps before the leader yields to
other ready work. |
|
|
Milliseconds the speculative submitter holds off the GIL waiting for
the GPU thread to reach the launch before it carries on. A value that
is not a number, is |
|
|
Total tokens of a packed Qwen3.5 text-prefill step that get a captured graph (one per bucket and batch size). A prompt past the top bucket prefills eagerly, which is launch-bound: an eager 8k prefill on 0.8B spends 78 ms of wall time on 36 ms of kernels. The default now reaches 8192; narrow it to save graph memory and capture time, or extend it. |
|
config’s |
How many decode steps of sampled ids the KV manager holds back before
it extends the requests’ prefix chains (the per-page keys the prefix
cache is indexed by), one extend per request per batch of steps instead
of one per step. The per-request Python of that extension was 0.3 to
0.4 ms a step at 128 rows. A page key then appears up to that many
steps late and a later commit indexes it, as the single-request path
already allows; a request that finishes in between may leave its last
page unindexed. The default |
|
config’s |
The KV plan writes FlashInfer’s index arrays (qo_indptr, kv_indptr,
kv_indices, last_page_len) into a ring of page-locked host buffers and
the decode wrapper copies the indices straight into its captured
device buffer from there, so the copies FlashInfer’s |
|
config’s |
The generation-0 garbage-collection threshold a worker sets after
warmup ( |
|
config’s |
The KV manager plans a captured decode step off the previous step’s
plan when the batch is the same rows in the same order and nothing
but that step’s commit touched the streams: every length is one
more, pages change only where a row crossed a page boundary, and the
five FlashInfer index arrays come from numpy instead of a per-row
Python pass. The first version measured a loss at c64/c128 on 0.8B
(batches change every step or two there, and a hit still rebuilt the
views); the reworked path keeps the views lazy and is off by default
until measured. |
|
config’s |
Whether a decode node may keep its loop-back token on the device:
the sampler writes each request’s last token to a slot-addressed
master and the next step reads its input ids from it, so the worker
routes the signal with no tensor (no per-request store, hold or
cleanup per step). Only nodes that declare the read
( |
|
config’s |
A captured decode step builds its rotary tables inside the graph from the position resource’s planned positions instead of staging them. Experiment knob, measured and gated on its own. |
|
config’s |
The captured sampler gathers its RNG offsets from the slot masters
and scatters the advanced offsets and the sampled tokens back inside
the graph, so a replayed decode step issues none of those launches on
the gpu thread afterwards (each one is a GIL release the main thread’s
postprocess wins). Padding rows then address a trash master row and
the masters are allocated once for |
|
unset |
|
|
|
Yield the speculation chain only when another (node, walk) is
actually ready right now; |
|
|
|
|
|
|
Compilation#
Variable |
Default |
Meaning |
|---|---|---|
|
|
Dynamo’s recompile limit, clamped to [8, 256]. Raise it if the logs
show |
|
|
How much a captured forward’s compile tunes; |