DeepInfer Explained

Config classes

IntermediateReferenceabout 16 min read

Code version: DeepInfer @ 9bd9cf2 · 2026-10-21

In one sentence

The engine reads all its settings from one EngineArgs object, which becomes four config objects at start-up.

Use this page to look up one setting. The page deepinfer/config.py: the four config classes explains the code of deepinfer/config.py. The page Environment variables lists the DEEPINFER_* environment variables, which are a second, separate way to set the engine.

From keyword arguments to config objects#

  1. LLM(model, **kwargs) adds its own defaults and makes an EngineArgs (deepinfer/entrypoints/llm.py:67-81).
  2. EngineArgs.__post_init__ uses the model path as the tokenizer path if you give no tokenizer. It also sets two environment variables if they are not set (deepinfer/engine/arg_utils.py:48-60).
  3. LLMEngine.from_engine_args calls create_engine_configs() (deepinfer/engine/llm_engine.py:460-469). That method makes the four objects in this order: ModelConfig, CacheConfig, ParallelConfig, SchedulerConfig (deepinfer/engine/arg_utils.py:62-114).
  4. The engine gives the same four objects to the driver Worker. It gives copies to each CP follower process as spawn arguments (deepinfer/engine/llm_engine.py:377-413).
  5. Some fields are empty at first. Other files fill them later, during start-up (the "Set later" rows below).
ObjectMain readers
ModelConfigtokenizer loader, model loader, Worker, ModelRunner. Four of its fields are also copied into model_cfg.gpt, which the model layers read (deepinfer/config.py:82-94).
CacheConfigWorker (memory profile), CacheEngine, the two BlockManager objects, the statistics logger.
ParallelConfigWorker (ranks and process groups), ModelRunner, the TCP address of the rendezvous.
SchedulerConfigThe C++ scheduler: its constructor reads nine attributes from the Python object (csrc/engine/scheduler.hpp:94-108). Also ModelRunner.

EngineArgs#

EngineArgs is a dataclass in deepinfer/engine/arg_utils.py (deepinfer/engine/arg_utils.py:17-46). The column "LLM default" shows the value that you get through the offline class LLM, when it is different.

Field, type, defaultMeaningGoes to
model
str, required (deepinfer/engine/arg_utils.py:21)
Path of the Hugging Face checkpoint folder.ModelConfig.model
served_model_name
str, "deepinfer-model" (deepinfer/engine/arg_utils.py:22)
A name. Nothing reads it.ModelConfig
tokenizer
str | None, None (deepinfer/engine/arg_utils.py:23)
Tokenizer folder. None means the model folder (deepinfer/engine/arg_utils.py:49-50).ModelConfig
trust_remote_code
bool, False (deepinfer/engine/arg_utils.py:24)
Allow Python code from the checkpoint in the tokenizer loader.ModelConfig
load_format
str, "auto" (deepinfer/engine/arg_utils.py:25)
"auto" loads the weights. "dummy" makes random weights.ModelConfig
seed
int, 0 (deepinfer/engine/arg_utils.py:26)
LLM: 0 (deepinfer/entrypoints/llm.py:62)
Random seed. Each rank adds its global rank.ModelConfig
max_model_len
int | None, None (deepinfer/engine/arg_utils.py:27)
Maximum tokens of one sequence, prompt and output. None becomes 4096.ModelConfig, SchedulerConfig
data_parallel_size
int, 0 (deepinfer/engine/arg_utils.py:28)
Number of DP replicas. 0 means "compute it" (ParallelConfig).ParallelConfig
context_parallel_size
int, 1 (deepinfer/engine/arg_utils.py:29)
Ranks per engine for context parallelism.ParallelConfig
expert_parallel_size
int, 1 (deepinfer/engine/arg_utils.py:30)
LLM: 1 (deepinfer/entrypoints/llm.py:59)
Ranks that share the experts (expert parallelism).ParallelConfig
engram_parallel_size
int, 0 (deepinfer/engine/arg_utils.py:31)
Ranks of one Engram group. 0 means "compute it".ParallelConfig
engine_rank
int, 0 (deepinfer/engine/arg_utils.py:32)
The engine rank of this process.ParallelConfig
engine_group_rank
int, 0 (deepinfer/engine/arg_utils.py:33)
Offset of the rendezvous port, for independent worlds on one host.ParallelConfig
gpu_memory_utilization
float, 0.90 (deepinfer/engine/arg_utils.py:34)
LLM: 0.9 (deepinfer/entrypoints/llm.py:63)
gpu_memory_utilization: the share of device memory for weights, activations and KV cache.CacheConfig
max_num_batched_tokens
int | None, None (deepinfer/engine/arg_utils.py:35)
Token budget of one step. None means "compute it".ModelConfig, SchedulerConfig
max_num_seqs
int, 256 (deepinfer/engine/arg_utils.py:36)
Maximum sequences that run at the same time.ModelConfig, SchedulerConfig
disable_log_stats
bool, False (deepinfer/engine/arg_utils.py:37)
LLM: True (deepinfer/entrypoints/llm.py:67)
Turn off the statistics log. The engine gets log_stats = not disable_log_stats (deepinfer/engine/llm_engine.py:466).LLMEngine
revision
str | None, None (deepinfer/engine/arg_utils.py:38)
Model version for the tokenizer loader.ModelConfig
tokenizer_revision
str | None, None (deepinfer/engine/arg_utils.py:39)
Tokenizer version for the tokenizer loader.ModelConfig
stop_preempted_request
bool, True (deepinfer/engine/arg_utils.py:40)
LLM: False (deepinfer/entrypoints/llm.py:68)
On preemption: True stops the request, False computes it again.SchedulerConfig
engine_type
EngineType, NORMAL (deepinfer/engine/arg_utils.py:41)
NORMAL does prefill and decode. PROMPT and COMPLETION are for a split deployment (deepinfer/engine/engine_type.py:11-13).ModelConfig, ParallelConfig and LLMEngine; the engine later writes its value into SchedulerConfig (deepinfer/engine/arg_utils.py:78, deepinfer/engine/arg_utils.py:105, deepinfer/engine/llm_engine.py:252)
chunked_prefill
bool, False (deepinfer/engine/arg_utils.py:42)
Allow a long prompt to run in several prefill steps (chunked prefill). The examples set True (examples/_config.py:120).SchedulerConfig
ignore_len
int, 128 << 20 (deepinfer/engine/arg_utils.py:43)
Translated comment: "accept requests of all lengths by default". Nothing reads it.ModelConfig
tokens_per_block
int, -1 (deepinfer/engine/arg_utils.py:44)
Optional check value. If it is not -1, it must equal the block size that the model gives (128).only the check
lookahead_tokens
int, 0 (deepinfer/engine/arg_utils.py:45)
Passed to the C++ scheduler. The offline example sets min(1, nextn) (examples/offline_inference.py:56).CacheConfig
offline_inference
bool, False (deepinfer/engine/arg_utils.py:46)
LLM: True (deepinfer/entrypoints/llm.py:79)
Stored as LLMEngine.offline_inference (deepinfer/engine/llm_engine.py:195). Nothing reads it.LLMEngine

LLM-only arguments. decode_sequence (default True) is not an engine setting. LLM keeps it and uses it to decode the output text (deepinfer/entrypoints/llm.py:64, deepinfer/entrypoints/llm.py:82). All other LLM keyword arguments go to EngineArgs through **kwargs. An unknown name raises TypeError from the dataclass constructor. LLM also sets TOKENIZERS_PARALLELISM=false if it is not set (deepinfer/entrypoints/llm.py:69).

Side effects of __post_init__. It sets DEEPINFER_ZERO_OVERHEAD_SCHEDULING to 1 for NORMAL and COMPLETION engines, and DEEPINFER_USE_MULTIMODAL_POOL to 1 except for COMPLETION. It sets each one only if the variable is not set, and then calls environ.rearm (deepinfer/engine/arg_utils.py:51-60, deepinfer/engine/engine_type.py:15-17). So ZOS is on when ModelConfig computes runtime_max_model_len.

ModelConfig#

Constructor: deepinfer/config.py:43-80. The constructor also loads the model config.json (the last row).

Field, type, defaultMeaningSet at, read by
model
str
Checkpoint folder.Set: deepinfer/config.py:59
Read: load_model_config (deepinfer/config.py:90), get_model (deepinfer/model_executor/model_loader.py:72), the multimodal processor (deepinfer/ve/multimodal_processor.py:76), the decode-curve cache key (deepinfer/worker/model_runner.py:571)
tokenizer
str
Tokenizer folder.Set: deepinfer/config.py:60
Read: get_hf_tokenizer (deepinfer/engine/llm_engine.py:200-201)
trust_remote_code
bool
See EngineArgs.Set: deepinfer/config.py:61
Read: deepinfer/engine/llm_engine.py:202
load_format
str
"auto" or "dummy", lower case after the check.Set: deepinfer/config.py:62-63, deepinfer/config.py:119
Read: "dummy" skips the checkpoint (deepinfer/engine/llm_engine.py:241)
seed
int
Base seed.Set: deepinfer/config.py:64
Read: set_random_seed(seed + global_rank) (deepinfer/worker/base.py:170-172)
revision, tokenizer_revision
str | None, None
Versions for the tokenizer loader.Set: deepinfer/config.py:65-66
Read: deepinfer/engine/llm_engine.py:203-204
max_num_seqs
int
See EngineArgs.Set: deepinfer/config.py:68
Read: state-buffer size (deepinfer/worker/base.py:242, deepinfer/worker/base.py:271), statistics (deepinfer/engine/stats_logger.py:370); copy in model_cfg.gpt
max_model_len
int, 4096 if None
Maximum sequence length.Set: deepinfer/config.py:69
Read: goes to SchedulerConfig (deepinfer/engine/arg_utils.py:110); error text (deepinfer/engine/llm_engine.py:449)
runtime_max_model_len
int, derived
runtime_max_model_len (formula).Set: deepinfer/config.py:70
Read: KV cache check (deepinfer/engine/llm_engine.py:446), block-table width (deepinfer/worker/model_runner.py:115), memory profile (deepinfer/worker/model_runner.py:411); the model_cfg.gpt copy: attention buffers (deepinfer/model_executor/models/v4_modules/attn.py:77, deepinfer/model_executor/models/v4_modules/index_attn.py:95)
max_num_batched_tokens
int, derived
Token budget of one step.Set: deepinfer/config.py:71
Read: statistics (deepinfer/engine/stats_logger.py:361); the model_cfg.gpt copy: prefill buffer size (deepinfer/model_executor/model_loader.py:120)
ignore_len
int, -1 (EngineArgs passes 128 << 20)
Not used.Set: deepinfer/config.py:73
Read: nothing
served_model_name
str, "deepinfer-model"
Not used.Set: deepinfer/config.py:74
Read: nothing
dtype
torch.dtype, always torch.bfloat16
Default dtype while the model is built.Set: deepinfer/config.py:75
Read: deepinfer/model_executor/model_loader.py:70
use_compressed_tokenizer
bool, False
Engram models: also make compressed token ids.Set: deepinfer/config.py:76; set later from the Engram config (deepinfer/engine/arg_utils.py:88-91)
Read: deepinfer/engine/llm_engine.py:564, deepinfer/worker/base.py:306, deepinfer/worker/model_runner.py:468
engram_tokenizer
str, the tokenizer path
The tokenizer.json of the compressed tokenizer.Set: deepinfer/config.py:77; set later (deepinfer/engine/arg_utils.py:91)
Read: deepinfer/worker/base.py:309
engine_type
EngineType, NORMAL
Engine kind.Set: deepinfer/config.py:78
Read: only the model_cfg.gpt copy, for example deepinfer/model_executor/models/deepseek.py:356, deepinfer/model_executor/models/v4_modules/mlp.py:172
model_cfg
AttrDict
The parsed config.json: architecture, gpt (all model sizes), vl_aligner and more.Set: deepinfer/config.py:89-94, through deepinfer/model_config_loader.py:8-23
Read: deepinfer/engine/arg_utils.py:83, deepinfer/engine/llm_engine.py:207, deepinfer/model_executor/model_loader.py:73, deepinfer/worker/model_runner.py:84
architecture
str
The one name in architectures of config.json.Set: deepinfer/config.py:91
Read: model class lookup (deepinfer/model_executor/model_loader.py:37-44)

get_vocab_size() returns model_cfg.gpt.vocab_size, a value from the checkpoint, not from the repository (deepinfer/config.py:121-122).

Fields copied into the model config. _load_model_cfg writes max_num_seqs, max_num_batched_tokens, runtime_max_model_len and engine_type into model_cfg.gpt (deepinfer/config.py:82-94). The model layers get only model_cfg.gpt, so they read these copies.

Copies for CP followers. A CP follower gets ModelConfig as a spawn argument, so Python pickles it. __getstate__ leaves out model_cfg and keeps the four copied values. __setstate__ loads config.json again in the new process and writes the four values back:

    def __getstate__(self) -> dict:
        # model_cfg 不可 pickle,改为只传递必要的运行时标量,
        # 由 worker 进程在 __setstate__ 中重新 load model_cfg 后回填。
        state = self.__dict__.copy()
        model_cfg = state.pop("model_cfg", None)
        overrides: dict = {}
        if model_cfg is not None:
            overrides = {k: model_cfg.gpt[k] for k in self._GPT_RUNTIME_ATTRS}
        state["_gpt_runtime_overrides"] = overrides
        return state

    def __setstate__(self, newstate: dict) -> None:
        overrides = newstate.pop("_gpt_runtime_overrides", {})
        self.__dict__.update(newstate)
        self.model_cfg = load_model_config(self.model)
        self.architecture = self.model_cfg.architecture
        for key, value in overrides.items():
            setattr(self.model_cfg.gpt, key, value)

Translated comments (Chinese → English)

  • 97-98 model_cfg cannot be pickled. So pass only the necessary runtime scalars; the worker process loads model_cfg again in __setstate__ and then fills them back in.

CacheConfig#

Constructor: deepinfer/config.py:125-143. Four fields are None at first. Two later start-up steps fill them in the same object, which the engine and the driver Worker share.

Field, type, defaultMeaningSet at, read by
block_size
int; always 128 in this release
Tokens per KV block, before compression.Set: deepinfer/config.py:132, from resolved_tokens_per_block (deepinfer/engine/arg_utils.py:84, deepinfer/model_executor/model_metadata_utils.py:133-135)
Read: C++ scheduler (deepinfer/engine/llm_engine.py:309), KV cache check (deepinfer/engine/llm_engine.py:445), ModelRunner (deepinfer/worker/base.py:95), memory profile (deepinfer/worker/base.py:222, deepinfer/worker/base.py:238), CacheEngine (deepinfer/worker/cache_engine.py:919)
gpu_memory_utilization
float
Share of total device memory.Set: deepinfer/config.py:133
Read: deepinfer/worker/base.py:235
lookahead_tokens
int, 0
Passed to the C++ scheduler. A prefill check there needs cache.num_tokens to be 0 or at least this value (csrc/engine/scheduler.hpp:454-457).Set: deepinfer/config.py:143
Read: deepinfer/engine/llm_engine.py:316
num_gpu_blocks
int | None, None
Number of KV blocks.Set: set by the memory profile: the mean over all ranks, rounded down to even (deepinfer/worker/base.py:264-267)
Read: deepinfer/engine/llm_engine.py:438, KV BlockManager (deepinfer/engine/llm_engine.py:265), deepinfer/worker/cache_engine.py:882, deepinfer/engine/stats_logger.py:410
num_state_seqs
int | None, None
Number of state slots.Set: deepinfer/worker/cache_engine.py:950
Read: state BlockManager (deepinfer/engine/llm_engine.py:266), deepinfer/engine/stats_logger.py:413
bytes_of_state_per_seqs
int | None, None
Bytes of one state slot.Set: deepinfer/worker/cache_engine.py:949
Read: The state manager exists only if it is above 0 (deepinfer/engine/llm_engine.py:266)
bytes_per_block
int | None, None
Bytes of one KV block row (all layers).Set: deepinfer/worker/cache_engine.py:951
Read: only a log line (deepinfer/engine/llm_engine.py:262-264)

ParallelConfig#

Constructor: deepinfer/config.py:150-174. There is no tensor-parallel size: the "model parallel" size is the CP size.

Field, type, defaultMeaningSet at, read by
data_parallel_size
int; 0 becomes max(1, ep // cp)
Number of DP replicas (engines).Set: deepinfer/config.py:161-163
Read: process groups (deepinfer/worker/base.py:322), decode-curve cache key (deepinfer/worker/decode_perf_cache.py:46)
context_parallel_size
int
Ranks per engine.Set: deepinfer/config.py:164
Read: follower spawn (deepinfer/engine/llm_engine.py:370), global rank (deepinfer/worker/base.py:79), process groups (deepinfer/worker/base.py:323)
expert_parallel_size
int
Size of one EP group.Set: deepinfer/config.py:165
Read: deepinfer/worker/base.py:324
engine_rank
int
Index of this engine.Set: deepinfer/config.py:166
Read: global rank engine_rank × cp_size + cp_rank (deepinfer/worker/base.py:79, deepinfer/worker/base.py:329)
data_parallel_rank
int, derived: engine_rank % data_parallel_size
Index inside the DP group.Set: deepinfer/config.py:167
Read: multimodal processor (deepinfer/engine/llm_engine.py:217), deepinfer/worker/base.py:77
engine_group_rank
int
Port offset of the rendezvous address.Set: deepinfer/config.py:168
Read: deepinfer/utils.py:222-230
engine_type
EngineType, NORMAL
Engine kind.Set: deepinfer/config.py:169
Read: CUDA graphs on or off (deepinfer/worker/model_runner.py:73), draft pool (deepinfer/worker/model_runner.py:98), profile kind (deepinfer/worker/model_runner.py:448)
model_parallel_size
int, derived: = context_parallel_size
Ranks that work on one batch.Set: deepinfer/config.py:171
Read: MFU per device (deepinfer/engine/stats_logger.py:209)
engram_parallel_size
int; 0 becomes model_parallel_size × data_parallel_size
Size of one Engram group.Set: deepinfer/config.py:172
Read: deepinfer/worker/base.py:325
world_size
int, derived: max(mp × dp, engram_parallel_size)
Number of ranks in the world group.Set: deepinfer/config.py:173
Read: init_process_group (deepinfer/worker/base.py:334-340)

Worked example. examples/offline_inference.py --ep 4 --cp 2 gives dp_size = max(4 // 2, 1) = 2 (examples/offline_inference.py:24-28). Then model_parallel_size = 2, engram_parallel_size = 2 × 2 = 4, world_size = max(4, 4) = 4. Engine 1 has data_parallel_rank = 1 % 2 = 1, and its ranks are 2 and 3.

SchedulerConfig#

Constructor: deepinfer/config.py:185-206. The C++ Scheduler reads the fields by name from the Python object, once, in its constructor.

Field, type, defaultMeaningSet at, read by
max_num_batched_tokens
int, derived if None
Token budget of one step.Set: deepinfer/config.py:196
Read: csrc/engine/scheduler.hpp:96, output builder (deepinfer/engine/llm_engine.py:745), memory profile (deepinfer/worker/model_runner.py:447)
max_num_seqs
int
Maximum running sequences.Set: deepinfer/config.py:197
Read: csrc/engine/scheduler.hpp:97, CUDA graph sizes (deepinfer/worker/model_runner.py:77), DFlash graphs (deepinfer/worker/model_runner.py:89), draft pool (deepinfer/worker/model_runner.py:99), memory profile (deepinfer/worker/model_runner.py:446)
max_model_len
int
From ModelConfig (already 4096 if it was None).Set: deepinfer/config.py:198
Read: csrc/engine/scheduler.hpp:94; prompt limit (csrc/engine/scheduler.hpp:112)
runtime_max_model_len
int, derived
Same formula as in ModelConfig.Set: deepinfer/config.py:199
Read: csrc/engine/scheduler.hpp:95
stop_preempted_request
bool, False here, but EngineArgs passes True by default
Stop or recompute a preempted request.Set: deepinfer/config.py:200
Read: csrc/engine/scheduler.hpp:98
chunked_prefill
bool, False
Allow prompt chunks.Set: deepinfer/config.py:201
Read: csrc/engine/scheduler.hpp:99
prefill_attempt_interval
int, DEEPINFER_PREFILL_ATTEMPT_INTERVAL (70)
Decode steps between ALL attempt points.Set: deepinfer/config.py:193, deepinfer/config.py:203
Read: csrc/engine/scheduler.hpp:105
prefill_any_attempt_interval
int, DEEPINFER_PREFILL_ANY_ATTEMPT_INTERVAL (100)
Decode steps between ANY attempt points.Set: deepinfer/config.py:194, deepinfer/config.py:205
Read: csrc/engine/scheduler.hpp:107
engine_type
int, no default
EngineType.value: 0, 1 or 2.Set: set by the engine after the KV cache (deepinfer/engine/llm_engine.py:252)
Read: csrc/engine/scheduler.hpp:100
driver_gpu_id
int, no default
First visible device id.Set: set by the engine (deepinfer/engine/llm_engine.py:253)
Read: nothing

Derived values#

runtime_max_model_len (deepinfer/config.py:11-16):

nextn              = DEEPINFER_USE_NEXTN_DECODE                 # default 5
scheduler_overhead = nextn + (nextn + 1 if ZOS on else 0)
draft_overhead     = nextn
runtime_max_model_len = max_model_len + scheduler_overhead + draft_overhead

max_num_batched_tokens (deepinfer/config.py:219-228):

max_num_decoding_tokens = max_num_seqs * (1 + nextn)
if max_num_batched_tokens is given:
    assert max_num_batched_tokens >= max_num_decoding_tokens
    use it
else:
    max(max_model_len, 4096, max_num_decoding_tokens)
ValueEngineArgs defaultsexamples/offline_inference.py
max_model_lenNone → 4096 (deepinfer/config.py:69)32768 (examples/offline_inference.py:53)
max_num_seqs2564 (examples/offline_inference.py:54)
max_num_decoding_tokens256 × 6 = 15364 × 6 = 24
max_num_batched_tokensNone → max(4096, 4096, 1536) = 409632768, given; 32768 ≥ 24 passes (examples/offline_inference.py:52)
runtime_max_model_len (ZOS on)4096 + (5 + 6) + 5 = 411232768 + (5 + 6) + 5 = 32784
runtime_max_model_len (ZOS off)4096 + 5 + 5 = 410632768 + 5 + 5 = 32778

Checks and their errors#

CheckErrorWhere
load_format (lower case) is "auto" or "dummy"AssertionError, no messagedeepinfer/config.py:115-119
config.json has vl_aligner (only multimodal checkpoints)AssertionErrordeepinfer/model_config_loader.py:22
A given max_num_batched_tokens ≥ max_num_seqs × (1 + nextn)AssertionError, no messagedeepinfer/config.py:224-226
tokens_per_block is -1 or equals 128AssertionError with both valuesdeepinfer/engine/arg_utils.py:85-86
gpu_memory_utilization ≤ 1.0ValueError("GPU memory utilization must be less than 1.0. ...")deepinfer/config.py:145-147
expert_parallel_size > 0AssertionErrordeepinfer/config.py:177
(mp × dp) % ep == 0: the EP groups fill the ranks exactlyAssertionErrordeepinfer/config.py:178
engram_parallel_size > 0AssertionErrordeepinfer/config.py:179
world_size divides by mp × dp and by engram_parallel_sizeAssertionErrordeepinfer/config.py:180-181
0 ≤ engine_rank < world_size // mpAssertionErrordeepinfer/config.py:182
Without chunked prefill: max_num_batched_tokens ≥ max_model_lenValueError: "max_num_batched_tokens (...) is smaller than max_model_len (...)"deepinfer/config.py:209-212
Both prefill intervals ≥ 1ValueErrordeepinfer/config.py:213-216; C++ checks again (csrc/engine/scheduler.hpp:106, csrc/engine/scheduler.hpp:108)
A COMPLETION engine needs stop_preempted_request=TrueRuntimeError from TORCH_CHECKcsrc/engine/scheduler.hpp:101-104

Some checks are assert statements. Python removes them when it runs with -O.

Where the docstrings and the code disagree#

Fields that nothing reads#

A search of deepinfer/, csrc/ and examples/ finds no reader for these fields. They are stored and then not used in this release.