Configuration Reference¶
This page documents all CLI flags, configuration files, and their interactions. For architectural context on what these settings control, see Cluster Architecture and Core Engine.
Configuration Precedence¶
BLIS takes its configuration from four sources. They do not overlap: each setting has exactly one home.
Scenario file (--scenario in --scenarios) — the deployment: model, hardware, fabric, pools,
parallelism, engine settings, coefficient sets
CLI flags — workload, policies, topology, seed/horizon/output
YAML files (policy-config, workload-spec, — CLI flags override these values when explicitly set
kv-offload-config, lora-config, defaults.yaml)
Hardcoded defaults (lowest priority)
CLI flags only override YAML values when explicitly set. BLIS checks whether each flag was provided by the user (not just whether it has a non-default value), so default flag values do not accidentally override YAML configuration. No CLI flag overrides a scenario setting.
Parameter Resolution by Category¶
Deployment and engine settings — from the scenario only. See Scenario and Deployment below for the full list. There is no CLI override and no per-model fallback.
Latency — priced by blis-latency-kernel, the only latency backend. The scenario names the coefficient sets; they are read from the blis-registry clone named by --registry. There are no coefficient flags.
KV cache blocks — computed by the kernel's memory methods from the scenario (model, hardware, parallelism, gpu_memory_utilization, cache_dtype, block_size), per data-parallel rank. There is no flag to set it.
Workload parameters (--rate, --num-requests, --prompt-tokens, etc.):
--workload-specYAML file — when set, all token distribution and arrival parameters come from the YAML; CLI distribution flags are ignored- CLI distribution flags — when
--workload distribution(default) and no--workload-spec - Named preset from the catalog (
<catalog>/workloads/<name>.yaml, #1769) — when--workload <name>(e.g.,chatbot) - Hardcoded CLI flag defaults — (e.g.,
--prompt-tokens 512,--output-tokens 512)
Note
--seed, --horizon, and --num-requests are exceptions — they override the workload-spec YAML values even when --workload-spec is set. --rate does NOT override aggregate_rate in the YAML (see Common Pitfalls).
Scheduling and preemption (--scheduler, --preemption-policy):
- Explicit CLI flags
--policy-configYAML bundle- The scenario's engine settings, then the default
fcfs
Routing, admission and flow control are the embedded llm-d router's, configured by the scenario's router: block and pool labels (Router). See Routing.
Batch formation — max_num_seqs and max_num_batched_tokens come from the scenario's pool engine block. long_prefill_token_threshold comes from the same block, per pool (blis-schemas#75): each P/D pool runs its own. --long-prefill-token-threshold is a run-wide override: it applies to every pool and must agree with every value a pool states, or the run is refused. --preemption-policy remains on the CLI.
Known Unit Gotchas¶
All internal timestamps in the DES (arrival time, schedule time, completion time, clock) use ticks, where 1 tick = 1 microsecond (μs). Output metrics convert to milliseconds for human readability, but several fields and flags use different units:
| Field / Flag | Unit | Notes |
|---|---|---|
ttft_ms, e2e_ms, itl_ms (per-request JSON) |
milliseconds | Converted from ticks by dividing by 1,000 |
scheduling_delay_ms (per-request JSON) |
milliseconds | Converted from ticks by dividing by 1,000. Historically was in ticks (μs) despite the _ms suffix — fixed by BC-14. Old hypothesis scripts (pre-fix) divide by 1,000 again unnecessarily. |
scheduling_delay_p99_ms (aggregate) |
milliseconds | Always was in milliseconds |
--horizon |
ticks (μs) | Simulation time limit. 1,000,000 = 1 second |
--gateway-latency, --epp-scrape-jitter, --kv-event-delay |
ticks (μs) | Gateway hop before the router; scrape phase-offset bound; KV-event delivery delay |
think_time_us (workload YAML) |
microseconds | Inter-round delay in multi-turn sessions. 5,000,000 = 5 seconds |
aggregate_rate, --rate |
requests/second | Not ticks — real-world time unit |
Common Pitfalls¶
Capacity estimate mismatch (issue #390). CLI distribution mode defaults to --prompt-tokens 512, --output-tokens 512. If you estimate per-instance capacity using CLI mode, then run a workload-spec YAML with shorter sequences (e.g., mean 256/128), the YAML workload will achieve ~1.5x higher throughput than the CLI estimate predicted. Always derive capacity estimates from the actual workload you plan to run, not from CLI defaults.
--rate does NOT override workload-spec YAML. The --rate flag only applies in CLI distribution mode. When --workload-spec is set, request rate comes from aggregate_rate in the YAML file — the --rate flag is ignored. To change the rate for a YAML workload, edit the aggregate_rate field in the spec.
aggregate_rate override for inference-perf specs. When converting inference-perf specs via blis convert inference-perf, per-stage rates in the spec override a user-specified aggregate_rate. If the sum of stage rates differs from aggregate_rate, BLIS logs a warning and uses the stage-rate sum. This prevents silent rate scaling errors.
enable_multi_turn_chat semantic mismatch (issue #517). inference-perf's enable_multi_turn_chat creates one persistent session per virtual user. BLIS's closest equivalent is multi_turn.single_session: true in the workload YAML, but the session mechanics differ. When converting inference-perf specs, verify that the converted multi-turn behavior matches your intent.
Deployment Inputs (required)¶
blis run and blis replay both require all four of these. Omitting any is refused.
| Flag | Type | Default | Description |
|---|---|---|---|
--scenario |
string | "" | Required. Scenario file name within --scenarios, e.g. llama-3.1-70b-instruct-h200-fp8-vllm-tp4.yaml. The file is a blis-schemas Scenario + Deployment (two YAML documents) — see Scenario and Deployment. |
--scenarios |
string | "" | Required. Directory holding scenario YAML files. Any directory works. The kernel module's own fixtures are at $(go env GOMODCACHE)/github.com/inference-sim/blis-latency-kernel@v0.3.0/testdata/aisimulate; this repository's testdata/scenarios/ holds a P/D example (glm-5-h200-3p1d-ib.yaml), an MTP example (glm-5-h200-tp8-mtp3.yaml) and a DeepSeek-V4.1-Flash DSpark example (deepseek-v4.1-flash-h100-tp8-dspark5.yaml). |
--registry |
string | "" | Required. blis-registry clone root, holding the fitted coefficient sets the scenario names. Pinned release: v0.2.0. |
--catalog |
string | "" | Path to the blis-catalog clone root (pinned release 0.3.0; see Catalog compatibility) — model graphs, chips, fabrics, storage devices and workload presets. No default and no search path — supply this flag or the BLIS_CATALOG environment variable, or the run is refused naming both (#1731). --catalog wins when both are set, and the override is announced on stderr. A relative value is resolved against the process working directory, an absolute value is used as given. Also registered on convert preset (and the deprecated observe) for the workload presets in the workloads/ namespace. BLIS never fetches or writes a catalog file at run time (NS-6). |
git clone --branch 0.3.0 --depth 1 https://github.com/inference-sim/blis-catalog.git
git clone --branch v0.2.0 --depth 1 https://github.com/inference-sim/blis-registry.git
export BLIS_CATALOG=$PWD/blis-catalog
./blis run --scenario llama-3.1-70b-instruct-h200-fp8-vllm-tp4.yaml \
--scenarios <dir of scenario files> --registry $PWD/blis-registry \
--rate 10 --num-requests 100
Scenario and Deployment¶
A scenario file holds two YAML documents in the blis-schemas format:
- Scenario —
name,engine_version,model(a catalog model),coefficients(the registry coefficient sets that price it), andcluster(hardware,fabric,nodes,gpus_per_node). - Deployment —
pools, each with arole(colocated,prefillordecode),nodes, aparallelblock (tp,pp,dp,enable_expert_parallel) and anengineblock (block_size,max_num_seqs,max_num_batched_tokens,max_model_len,quantization,cache_dtype,cudagraph_mode,gpu_memory_utilization,enable_prefix_caching,speculative: {method, num_spec_tokens}); plus optionaloffloadandpd_transfer.
These settings come from the scenario (and the kernel), and no CLI flag sets them:
| Setting | Source |
|---|---|
| Model | Scenario model |
| Hardware, fabric | Scenario cluster.hardware, cluster.fabric |
| TP / DP / expert parallelism | Pool parallel.tp, parallel.dp, parallel.enable_expert_parallel |
| KV block budget | The kernel's memory methods, per data-parallel rank |
| Block size | Pool engine.block_size |
| Max running requests | Pool engine.max_num_seqs |
| Token budget per step | Pool engine.max_num_batched_tokens |
| Max sequence length | Pool engine.max_model_len — required in the scenario, as a count (auto is refused) |
| Prefix caching | Pool engine.enable_prefix_caching |
| KV-cache dtype | Pool engine.cache_dtype |
| Speculative decoding | Pool engine.speculative.method / num_spec_tokens (acceptance is resolved from the registry's profiles, the workload, the scenario's acceptance pin or the CLI; see Latency Models) |
| Step time, memory, P/D KV transfer, offload tier transfer, host overheads | Priced by blis-latency-kernel with the scenario's registry coefficients |
Data parallelism (MoE only). A pool with dp > 1 becomes one engine per data-parallel rank, each sized as one vLLM EngineCore. The ranks of one instance step in lockstep and the router sees them as one endpoint, balanced across ranks by vLLM's internal DP load balancer; parallel.data_parallel_load_balancing: external (blis-schemas#76, per pool; --dp-load-balancing is a run-wide override that must agree with every mode a pool states; under P/D every rank is already its own endpoint, so a P/D pool's mode is resolved but changes no routing) instead makes every rank its own endpoint, as vLLM's external-LB modes do (Latency Models, #1909). dp > 1 on a dense model is refused.
Node pools. When node_pools are configured in --policy-config, every pool's gpu_type must equal the scenario's cluster.hardware.
Simulation Control¶
Top-level settings that control the simulation run.
| Flag | Type | Default | Description |
|---|---|---|---|
--seed |
int64 | 42 | Random seed for deterministic simulation. Same seed produces byte-identical stdout. |
--horizon |
int64 | MaxInt64 | Simulation time limit in ticks (microseconds). Simulation stops when clock exceeds horizon or all requests complete. |
--log |
string | "warn" | Log verbosity: trace, debug, info, warn, error, fatal, panic. Logs go to stderr. |
--metrics-path |
string | "" | File path to write MetricsOutput JSON (aggregate P50/P95/P99 TTFT, E2E, throughput stats, plus the file-only cache_hit_rate, catalog, measured-window aggregates (#1938), kernel_provenance (#1942) and build-version fields; see the results guide). Accepted on both blis run and blis replay (#1583). Distinct from replay's --results-path, which writes the per-request []SimResult array and is replay-only. Empty = no file output. |
KV Cache Configuration¶
The GPU-tier block budget and block size come from the scenario and the kernel (see Scenario and Deployment). The remaining flags configure CPU / storage offload tiers. Maps to KVCacheConfig.
| Flag | Type | Default | Description |
|---|---|---|---|
--kv-cpu-blocks |
int64 | 0 | Legacy CPU-tier blocks. 0 disables tiered caching. The GPU↔CPU transfer is priced by the kernel from the catalog's cpu_dram storage device. |
--kv-offload-threshold |
float64 | 0.9 | GPU utilization fraction above which blocks are offloaded to CPU on the legacy --kv-cpu-blocks path. Range [0, 1]. |
--kv-offload-config |
string | "" | Path to a YAML file with a top-level kv_offload: block (multi-tier offload). Each tier must name a catalog storage device_class; the kernel prices every tier transfer (its TierTime). An explicit read_bandwidth / write_bandwidth / base_latency on a tier is refused. Under P/D every pool gets its own tier of this size (a MultiConnector of NIXL and the OffloadingConnector). When the scenario states an offload block, that block is the configuration and this flag may only restate it: a file that resolves differently is refused (#1910). See KV Cache Management. |
Batch Formation¶
max_num_seqs and max_num_batched_tokens come from the scenario's pool engine block. Maps to BatchConfig.
| Flag | Type | Default | Description |
|---|---|---|---|
--long-prefill-token-threshold |
int64 | 0 | Prefill length threshold for chunked prefill. 0 = disabled (all prefill in one step). |
--renderer-num-workers |
int | 1 | Render threads per API server (vLLM renderer_num_workers). Each request's admission overhead queues for one, in arrival order (INV-R1). 0 = uncontended per-request delay. |
--api-server-count |
int | 0 | API servers per endpoint (vLLM --api-server-count). 0 = vLLM's default: dp behind an internal or hybrid DP replica, else 1. |
--preemption-policy |
string | "fcfs" | Preemption victim selection: fcfs (tail-of-batch, default) or priority (least-urgent SLO tier evicted first, matching vLLM --scheduling-policy priority). Priority mode uses priority.slo_priorities from the policy bundle when set. |
Latency Model¶
BLIS prices every step with blis-latency-kernel (v0.3.0, adapter sim/kernelmodel). There is no backend selector and no coefficient flag: the scenario names the coefficient sets and --registry locates them. See Latency Models.
| Flag | Type | Default | Description |
|---|---|---|---|
--speculative-acceptance-rate |
float64 | 0.0 | The accepted fraction of drafts, (AL − 1)/K, in [0, 1]. The highest acceptance layer (#1939); not with --speculative-acceptance-length. |
--speculative-acceptance-length |
float64 | 0.0 | The mean acceptance length AL (tokens per verification step, counting the bonus token), in [1, K + 1]. The highest acceptance layer; not with --speculative-acceptance-rate. |
--speculative-thinking |
string | on or off: with --speculative-category, selects the registry's acceptance profile, overriding the workload's selectors. |
|
--speculative-category |
string | The workload category (e.g. coding) that selects the registry's acceptance profile. |
|
--speculative-fallback-category |
string | A category to use, recorded as a fallback, when the workload's has no profile. Without it an unmatched category is refused. A scenario pin's own fallback_category wins over it (blis-schemas acceptance.Resolve). |
Cluster Configuration¶
Every run, --num-instances 1 (the default) included, passes each request through the embedded llm-d router (admission, flow control, endpoint picking) before it reaches a per-instance wait queue. With one instance the router can only pick that instance, and with the default configuration it admits every request on arrival, so a single-instance run reports what a run without a router would (see Routing). See Cluster Architecture for the multi-instance pipeline and Core Engine for single-instance internals.
| Flag | Type | Default | Description |
|---|---|---|---|
--num-instances |
int | 1 | Number of inference instances. 1 = single-instance mode; > 1 = cluster mode behind the llm-d router. Must not exceed the scenario's rank capacity (pool nodes × gpus_per_node / (pp × tp × pcp)); testdata/scenarios/llama-3.1-70b-instruct-h200-tp4-4node.yaml allows up to 8. |
--prefill-instances |
int | 0 | Prefill instances for P/D disaggregation (0 = disabled). Requires a scenario with prefill and decode pools, and must not exceed the prefill pool's rank capacity (pool nodes × gpus_per_node / (pp × tp × pcp)). |
--decode-instances |
int | 0 | Decode instances for P/D disaggregation. Same rules, against the decode pool. |
--pd-transfer-contention |
bool | false | Concurrent P/D KV handoffs share the fabric links they cross: each link is divided max-min fairly among the handoffs on it, from the kernel's PDTransferDemand. A handoff alone still takes exactly PDTransferTime. Run and replay alike (INV-13). |
P/D disaggregation. Whether a request is disaggregated is the router's decision: the EndpointPickerConfig needs a disagg-profile-handler with a P/D decider (always-disagg-pd-decider or prefix-based-pd-decider); prefill and decode pods carry llm-d.ai/role labels automatically. See Routing. A scenario with prefill and decode pools runs one kernel per pool; the KV handoff is priced by the kernel's PDTransferTime over the scenario's fabric between the two instances' placements. Refused: P/D topology over a colocated scenario; a disaggregated scenario without --prefill-instances/--decode-instances; pools that differ in block size, dp or draft configuration; a pd_transfer.connector other than NIXL's (NixlConnector, NixlPullConnector, NixlPushConnector, MultiConnector); shared (--prefill-decode-instances) or encode instances. The scenario's offload block (or --kv-offload-config) gives each pool its own tier; see Latency models for the handoff (decode-side load, prefill KV hold, contention).
Router¶
Every cluster run routes with the llm-d router (the Endpoint Picker, EPP) embedded in-process. Its inputs are the deployment's, so the --scenario states them (#1950): the deployment's router: block and each pool's labels. Each input is parsed by the router's own code; a value the real router rejects is rejected with the router's message. See Routing for the mapping, the supported plugins, what is refused at startup, and the mapping from removed BLIS routing and admission flags to llm-d configuration.
| Scenario field | Description |
|---|---|
router.epp_flags |
The llm-d router's (EPP's) command-line flags, verbatim, one entry per flag. Default: a standalone router whose pool is every simulated pod (--endpoint-selector=llm-d.ai/inference-serving=true --endpoint-target-ports=8000). |
router.endpoint_picker_config |
EndpointPickerConfig file, as the EPP reads it with --config-file. Default: the router's built-in default configuration. Refused together with an EPP flag --config-file or --config-text. |
router.manifests |
Kubernetes manifest files. The router reads InferencePool, InferenceObjective and InferenceModelRewrite objects; other kinds are ignored. |
pools[].labels |
Labels on the pool's simulated model-server pods, so an InferencePool selector or label filter from a real deployment matches. A label every pool states with one value is on every pod; any other is on its pool's pods only. |
Paths are relative to the scenario file; a file that cannot be read is refused at startup. --epp-flags, --epp-config, --epp-manifests and --pod-labels were removed (unknown flags), as --tp was. The flags below model the environment around the router, not the deployment, and stay on run and replay:
| Flag | Type | Default | Description |
|---|---|---|---|
--gateway-latency |
int64 | 0 | Microseconds from a request's arrival to the router's first look at it (network and proxy hops before the Endpoint Picker). Must be >= 0. |
--epp-scrape-jitter |
int64 | 0 | Upper bound (µs) of the seeded phase offset of each endpoint's metrics collection; 0 = every endpoint is scraped in phase. Must be >= 0. |
--kv-event-delay |
int64 | 0 | Microseconds from an engine publishing its KV-cache events (at the end of a step) to the router's precise-prefix-cache-producer ingesting them. Must be >= 0. Recorded in the trace header. |
Recorded in the trace. The resolved router inputs are written to the TraceV2 header (--trace-output); the EndpointPickerConfig (and a --config-file EPP flag) is inlined as --config-text so the header carries the configuration itself. blis replay rebuilds the recorded router from the header. A replay whose scenario states no router replays the recorded one; a replay whose scenario states a router (a router: block or pool labels) that differs from the header's, or whose router environment flags differ from it, is refused (INV-13).
Pod labels. BLIS sets llm-d.ai/inference-serving=true on every pod and llm-d.ai/role (prefill, decode, prefill-decode, encode) from the scenario's pools, in addition to pools[].labels; blis-schemas refuses a pool label llm-d.ai/role that contradicts the pool's role.
Objectives. Request priorities come from the InferenceObjective objects in the manifests, which the router reconciles only for an InferencePool (--pool-name); a request whose objective has none gets priority 0. examples/llm-d/inferencepool.yaml defines a pool and one objective per SLO class (critical 4, standard 3, batch -1, sheddable -2, background -3); examples/llm-d/scenarios/llama-3.1-70b-instruct-h200-tp4-4node-inferencepool.yaml routes with it. Each request carries its SLO class in the x-llm-d-inference-objective header and its tenant in x-llm-d-inference-fairness-id. See Admission and Flow Control.
SLO Tier Priorities¶
Each SLO class has an integer priority. Engine-side, the mapping drives priority scheduling (--scheduler priority-fcfs) and, with --preemption-policy priority, preemption victim selection. It follows the GAIE convention where negative priority = sheddable. Router-side priorities come from InferenceObjective objects (above), not from this mapping.
Default priorities:
| SLO Class | Priority | Sheddable? |
|---|---|---|
critical |
4 | No |
standard |
3 | No (default for an empty or unknown class) |
batch |
-1 | Yes |
sheddable |
-2 | Yes |
background |
-3 | Yes |
Custom overrides: set priority.slo_priorities in the policy bundle. Unspecified classes keep their defaults; values must be in [-100, 100].
priority:
slo_priorities:
batch: 0 # batch is no longer sheddable for engine scheduling
critical: 10
The mapping lives in sim/slo_priority.go (SLOPriorityMap); InvertForVLLM converts it to the instance convention (lower = more urgent) when a request is enqueued.
Scheduling and Priority¶
Per-instance policies that control request ordering within the wait queue. Maps to PolicyConfig.
| Flag | Type | Default | Description |
|---|---|---|---|
--scheduler |
string | "fcfs" | Scheduler: fcfs, priority-fcfs, sjf, reverse-priority. |
--preemption-policy |
string | "fcfs" | Preemption victim selection: fcfs (tail-of-batch, default) or priority (least-urgent SLO tier evicted first, matching vLLM --scheduling-policy priority). Priority mode evicts the running request with the highest Request.Priority value (vLLM convention: background=7 is evicted first). |
See Core Engine: Scheduling for policy details.
Workload Configuration¶
Workload Modes¶
BLIS supports three workload specification modes, in order of precedence:
| Mode | Trigger | Description |
|---|---|---|
| Workload-spec YAML | --workload-spec <path> |
Multi-client workload with per-client distributions. Highest priority. |
| CLI distribution | --workload distribution (default) |
Single-client Gaussian distribution controlled by CLI flags. |
| Preset | --workload <name> |
Named preset read from the catalog (<catalog>/workloads/<name>.yaml, #1769): chatbot, contentgen, summarization, multidoc. Needs --catalog / BLIS_CATALOG, which blis run already requires. |
Distribution Mode Flags¶
Used when --workload distribution (the default) and no --workload-spec is set.
| Flag | Type | Default | Description |
|---|---|---|---|
--rate |
float64 | 1.0 | Request arrival rate in requests/second. |
--num-requests |
int | 100 | Total number of requests to generate. |
--prompt-tokens |
int | 512 | Mean prompt (input) token count. |
--prompt-tokens-stdev |
int | 256 | Standard deviation of prompt tokens. |
--prompt-tokens-min |
int | 2 | Minimum prompt token count. |
--prompt-tokens-max |
int | 7000 | Maximum prompt token count. |
--output-tokens |
int | 512 | Mean output token count. |
--output-tokens-stdev |
int | 256 | Standard deviation of output tokens. |
--output-tokens-min |
int | 2 | Minimum output token count. |
--output-tokens-max |
int | 7000 | Maximum output token count. |
--prefix-tokens |
int | 0 | Prefix token count for prefix caching simulation. Additive to prompt tokens. |
Workload-Spec YAML¶
The --workload-spec flag loads a YAML file defining multi-client workloads:
aggregate_rate: 100 # Total arrival rate in requests/second
num_requests: 1000
seed: 42
horizon: 1000000000 # Ticks (microseconds)
clients:
- id: "interactive"
rate_fraction: 0.6 # 60% of aggregate rate
prefix_group: "chat"
prefix_length: 512
arrival:
process: "poisson"
input_distribution:
type: "gaussian"
params:
mean: 256
std_dev: 128
min: 2
max: 4096
output_distribution:
type: "exponential"
params:
mean: 128
- id: "batch"
rate_fraction: 0.4
arrival:
process: "gamma"
cv: 2.0
input_distribution:
type: "gaussian"
params:
mean: 1024
std_dev: 512
min: 2
max: 7000
output_distribution:
type: "gaussian"
params:
mean: 512
std_dev: 256
min: 2
max: 7000
Supported arrival processes: poisson, gamma (with cv parameter), weibull (with cv parameter), constant.
Supported token distributions: gaussian, exponential, pareto_lognormal, constant, empirical.
When --workload-spec is set, CLI --seed, --horizon, and --num-requests still override the YAML values if explicitly provided.
Trace Files¶
| Flag | Type | Default | Description |
|---|---|---|---|
--workload-spec |
string | "" | Path to workload-spec YAML. |
--defaults-filepath |
string | "defaults.yaml" | Path to defaults.yaml (the LoRA cost block; see defaults.yaml). |
--trace-output |
string | "" | Export workload as TraceV2 files (<prefix>.yaml + <prefix>.csv). |
Policy Bundle¶
The --policy-config flag loads engine-level policy and infrastructure configuration from a single YAML file. Strict parsing rejects unknown keys. Admission, routing and flow control are not part of a bundle; they are the llm-d router's (Router).
priority:
slo_priorities: # optional: override engine-level SLO class priorities
batch: 0 # defaults: critical=4, standard=3, batch=-1, sheddable=-2, background=-3
scheduler: "fcfs"
preemption:
policy: "priority" # fcfs (default) or priority (least-urgent SLO tier evicted first)
# Node pool infrastructure (optional; omit for single-pool mode)
# Every pool's gpu_type must equal the scenario's cluster.hardware, and gpu_type must be
# unique across pools (#1537). See docs/guide/cluster.md.
node_pools:
- name: "gpu-pool-1"
gpu_type: "h200" # must equal the scenario's cluster.hardware
gpus_per_node: 8
gpu_memory_gib: 141.0
initial_nodes: 2
min_nodes: 1
max_nodes: 4
provisioning_delay:
mean: 30.0 # seconds
stddev: 5.0 # 0 = constant delay
# Instance lifecycle (Phase 1A — all zero/empty = backward-compatible defaults)
instance_lifecycle:
loading_delay:
mean: 10.0 # seconds to load model weights onto GPU
stddev: 1.0 # 0 = constant delay
warm_up_request_count: 5 # requests served before leaving WarmingUp state
warm_up_ttft_factor: 2.0 # TTFT multiplier applied to warm-up requests (≥ 1.0)
drain_policy: "WAIT" # IMMEDIATE | WAIT | REDIRECT
warm_start_initial_instances: false # true = startup instances skip loading_delay (model pre-deployed); autoscaler-added instances always pay loading_delay
CLI flags override policy bundle values when explicitly set. For example, --scheduler sjf overrides the bundle's scheduler setting.
Node pools and instance lifecycle are YAML-only
node_pools and instance_lifecycle have no corresponding CLI flags. They must be set via --policy-config. Omitting them is safe — the simulator falls back to single-pool, no-lifecycle mode for full backward compatibility.
Decision Tracing¶
| Flag | Type | Default | Description |
|---|---|---|---|
--trace-level |
string | "none" | Trace verbosity: none or decisions. |
--counterfactual-k |
int | 0 | Record the top-k endpoints the router scored, with their state, per routing decision. Requires --trace-level decisions. |
--summarize-trace |
bool | false | Print trace summary after simulation. Requires --trace-level decisions. |
See Routing: Decisions and Cluster Architecture.
Fitness Evaluation¶
| Flag | Type | Default | Description |
|---|---|---|---|
--fitness-weights |
string | "" | Fitness function weights. Format: metric:weight,metric:weight,... |
When configured, BLIS computes a single fitness score from aggregated metrics. Latency metrics are normalized via 1/(1 + value/1000) where value is in ticks (microseconds) and 1000 = 1ms reference (lower is better); throughput metrics via value/(value + reference) where referenceRPS = 100.0 and referenceTPS = 10000.0 (higher is better). Useful for automated policy comparison across multiple simulation runs.
defaults.yaml¶
The defaults.yaml file (located by --defaults-filepath, default defaults.yaml) carries only the LoRA control-plane cost terms and a version. It holds no latency coefficients, no per-model deployment policy and no workload presets: latency coefficients live in blis-registry, named by the scenario; the deployment lives in the scenario; workload presets live in the catalog (<catalog>/workloads/<name>.yaml, #1769).
These are the top-level keys the file may carry, and strict parsing accepts no others (KnownFields(true), R10 — the authoritative list is cmd.Config in cmd/default_config.go; the bundled defaults.yaml is the worked example):
version: 0.0.1
# LoRA control-plane cost terms (#1464). Inert unless a run declares adapters.
lora:
load_base_latency_us: 1500.0
# ... bandwidth, per-rank footprint, per-rank step-overhead tiers
Node pools and the scenario's hardware
When node_pools are configured (via --policy-config), every pool's gpu_type must equal the scenario's cluster.hardware. KV capacity and step time for every placed instance come from the kernel for the scenario's hardware. gpu_type must also be unique across pools (#1537).
CLI Flag Summary by Sub-Config¶
| Sub-Config | Flags |
|---|---|
| Deployment (required) | --scenario, --scenarios, --registry, --catalog (or BLIS_CATALOG) |
| KVCacheConfig | --kv-cpu-blocks, --kv-offload-threshold, --kv-offload-config (block budget and block size: scenario + kernel) |
| BatchConfig | --long-prefill-token-threshold (max_num_seqs, max_num_batched_tokens: scenario) |
| Latency | --speculative-acceptance-rate / --speculative-acceptance-length and the acceptance selectors (everything else: scenario + registry, priced by blis-latency-kernel) |
| PolicyConfig | --scheduler, --preemption-policy |
| WorkloadConfig | --workload (preset read from <catalog>/workloads/<name>.yaml, #1769), --workload-spec, --rate, --concurrency, --num-requests, --prompt-tokens*, --output-tokens*, --prefix-tokens |
| DeploymentConfig | --num-instances, --prefill-instances, --decode-instances, --pd-transfer-contention, --trace-level, --counterfactual-k. YAML-only (no CLI flag): node_pools, instance_lifecycle |
| Router | the scenario's router: block and pools[].labels; --gateway-latency, --epp-scrape-jitter, --kv-event-delay |
| LoRA | --lora-config, --lora-adapter-capacity, --lora-* cost overrides, --defaults-filepath (the lora: block) |
| Top-level | --seed, --horizon, --log, --metrics-path (run and replay), --trace-output, --policy-config, --fitness-weights, --summarize-trace |
blis observe¶
Deprecated
blis observe is deprecated (#1901).
Dispatches a workload to a real inference server and records request-level timing into TraceV2 files for later replay and calibration.
Required¶
| Flag | Type | Default | Description |
|---|---|---|---|
--server-url |
string | "" | Inference server URL (required). |
--model |
string | "" | Model name for API requests (required). |
--trace-header |
string | "" | Output path for TraceV2 header YAML (required). |
--trace-data |
string | "" | Output path for TraceV2 data CSV (required). |
Workload Input¶
| Flag | Type | Default | Description |
|---|---|---|---|
--workload-spec |
string | "" | Path to WorkloadSpec YAML (alternative to --rate + distribution flags). |
--rate |
float64 | 0 | Requests per second for distribution synthesis. |
Optional¶
| Flag | Type | Default | Description |
|---|---|---|---|
--api-key |
string | "" | Bearer token for server authentication. |
--server-type |
string | "vllm" | Server type (vllm, tgi, etc.). |
--max-concurrency |
int | 256 | Maximum simultaneous in-flight requests. |
--warmup-requests |
int | 0 | Number of initial requests to exclude from trace. |
--no-streaming |
bool | false | Disable streaming (use non-streaming HTTP). |
--seed |
int64 | 42 | RNG seed for workload generation. |
--horizon |
int64 | 0 | Observation horizon in microseconds (0 = from spec or unlimited). |
--num-requests |
int | 0 | Maximum requests to generate (0 = from spec or unlimited). |
Distribution Synthesis¶
Used when --rate is set instead of --workload-spec. Same flag names and defaults as blis run.
| Flag | Type | Default | Description |
|---|---|---|---|
--prompt-tokens |
int | 512 | Average prompt token count. |
--prompt-tokens-stdev |
int | 256 | Prompt token standard deviation. |
--prompt-tokens-min |
int | 2 | Minimum prompt tokens. |
--prompt-tokens-max |
int | 7000 | Maximum prompt tokens. |
--output-tokens |
int | 512 | Average output token count. |
--output-tokens-stdev |
int | 256 | Output token standard deviation. |
--output-tokens-min |
int | 2 | Minimum output tokens. |
--output-tokens-max |
int | 7000 | Maximum output tokens. |
--prefix-tokens |
int | 0 | Shared prefix token count. |
--api-format |
string | "completions" | API format: completions (/v1/completions) or chat (/v1/chat/completions). |
--unconstrained-output |
bool | false | Do not set max_tokens (let server decide output length). |
--rtt-ms |
float64 | 0 | Measured network round-trip time in milliseconds (recorded in trace header for calibrate). |
blis replay¶
Replays a captured TraceV2 file (any TraceV2, including one from blis convert) through the discrete-event simulator. Replay runs on the kernel through the same deployment path as blis run, so it requires the same Deployment Inputs and accepts the same sim-config flags — see Simulation Control, KV Cache Configuration, Batch Formation, Latency Model, Cluster Configuration, Router, Scheduling and Priority, Decision Tracing, and Fitness Evaluation. A run's exported trace replayed with identical flags (including --horizon) yields byte-identical stdout (INV-13).
Replay-Specific Flags¶
| Flag | Type | Default | Description |
|---|---|---|---|
--trace-header |
string | "" | Path to TraceV2 header YAML file (required). |
--trace-data |
string | "" | Path to TraceV2 data CSV file (required). |
--results-path |
string | "" | File to write []SimResult JSON (fields: request_id, ttft_us, e2e_us, input_tokens, output_tokens) for blis calibrate consumption. Replay-only — blis run does not register it. |
blis replay also accepts --metrics-path (the aggregate MetricsOutput JSON, documented under
Simulation Control); it is not replay-specific, so it is not repeated in the
table above. The two are complementary rather than alternatives: --results-path writes per-request
rows, --metrics-path writes the run aggregate that blis calibrate --sim-metrics reads.
blis calibrate¶
Deprecated
blis calibrate is deprecated (#1901).
Compares real observed latencies (from blis observe) against simulator predictions (from blis replay) and produces a calibration report with per-metric MAPE, Pearson R, and quality grades.
| Flag | Type | Default | Description |
|---|---|---|---|
--trace-header |
string | "" | Path to TraceV2 header YAML file (from blis observe; required). |
--trace-data |
string | "" | Path to TraceV2 data CSV file (from blis observe; required). |
--sim-results |
string | "" | Path to SimResult JSON file (from blis replay --results-path; required). |
--report |
string | "" | Path to write calibration report JSON (required). |
--warmup-requests |
int | -1 | Number of initial requests to exclude. Default: from trace header warm_up_requests; pass 0 to include all. |
--network-rtt-us |
int64 | -1 | Network RTT in microseconds added to sim-side latencies. Default: from trace header network.measured_rtt_ms. |
--network-bandwidth-mbps |
float64 | 0 | Network bandwidth in Mbps for upload/download delay calculation (0 = no delay). |
blis convert¶
Converts external workload formats into BLIS WorkloadSpec v2 YAML. Three subcommands are available.
blis convert preset¶
Generates a WorkloadSpec from a named preset in the catalog
(<catalog>/workloads/<name>.yaml, #1769 — the same definition blis run --workload and
blis observe --workload read).
| Flag | Type | Default | Description |
|---|---|---|---|
--name |
string | "" | Preset name (e.g., chatbot, summarization, contentgen, multidoc). |
--rate |
float64 | 1.0 | Request rate in requests/second. |
--num-requests |
int | 100 | Number of requests. |
--catalog |
string | "" | Catalog clone root holding workloads/<name>.yaml. No default; BLIS_CATALOG is the fallback (the flag wins when both are set). |
blis convert servegen¶
Converts a ServeGen data directory into WorkloadSpec format.
| Flag | Type | Default | Description |
|---|---|---|---|
--path |
string | "" | Path to ServeGen data directory. |
blis convert inference-perf¶
Converts an inference-perf YAML specification into WorkloadSpec format.
| Flag | Type | Default | Description |
|---|---|---|---|
--spec |
string | "" | Path to inference-perf YAML spec. |
blis compose¶
Merges multiple WorkloadSpec v2 YAML files into a single combined specification.
| Flag | Type | Default | Description |
|---|---|---|---|
--from |
string (repeatable) | (none) | Path to v2 WorkloadSpec YAML file. Can be repeated to merge multiple specs. |