Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
aa3a14d
feat: add state cache groups to the FPM resource schema
Arsene12358 Oct 30, 2026
8c45017
test: cover state cache groups in the grouped pool and scheduler
Arsene12358 Oct 30, 2026
49c6543
perf: pre-size the grouped lease ranges per projection
Arsene12358 Oct 30, 2026
3837071
feat: accept state cache groups in the Python FPM profile
Arsene12358 Oct 30, 2026
a43bd45
feat: record the probe's prefix-caching settings with runtime memory
Arsene12358 Oct 30, 2026
c94a4dc
docs: document state cache groups in the FPM profile
Arsene12358 Oct 30, 2026
4fc5e42
docs: describe state groups in the allocator notes and tidy test names
Arsene12358 Oct 30, 2026
5bf93cb
docs: split the state group allocator sentence
Arsene12358 Oct 30, 2026
106dc90
docs: define the page, block and block count of a state cache group
Arsene12358 Nov 6, 2026
3ac5c04
feat: map vLLM cache specs by class and record state evidence in the …
Arsene12358 Oct 31, 2026
48489aa
fix: bound vLLM 0.31.0 cache regions by their last page
Arsene12358 Oct 31, 2026
a320df6
fix: record the new cache evidence only for vLLM 0.31.0 runtimes
Arsene12358 Oct 31, 2026
17a86d3
feat: add the vLLM 0.31.0 runtime instrumentation bundle
Arsene12358 Oct 31, 2026
45fde03
fix: take the view kernel block from the storage block only for MLA s…
Arsene12358 Oct 31, 2026
055a198
feat: import vLLM state cache groups and prefix-caching evidence from…
Arsene12358 Oct 31, 2026
31675b7
fix: check vLLM 0.31.0 cache aliasing by block ownership
Arsene12358 Oct 31, 2026
1fc9013
fix: require prefix-caching evidence for vLLM 0.31.0 records and shar…
Arsene12358 Oct 31, 2026
eff51da
fix: keep the 0.27.0 memory path to its legacy cache classes
Arsene12358 Oct 31, 2026
f551673
test: pin the malformed prefix-caching evidence refusal
Arsene12358 Oct 31, 2026
16236cd
feat: accept runtime state cache groups in onboarding import and comp…
Arsene12358 Oct 31, 2026
c1b3d70
fix: compare prefix-caching evidence of every phase with the accepted…
Arsene12358 Oct 31, 2026
548017e
fix: name the fixed state bytes in the grouped KV forward error
Arsene12358 Oct 31, 2026
1076779
docs: describe hybrid cache group import through the vLLM 0.31.0 runt…
Arsene12358 Oct 31, 2026
a6783bd
chore: pin the installed vLLM 0.31.0 source hashes of the GB300 probe…
Arsene12358 Oct 31, 2026
5b4f9d6
fix: keep the runtime memory provenance of vLLM 0.27.0 and 0.28.0 imp…
Arsene12358 Oct 31, 2026
e015953
fix: refuse a state group whose blocks_per_request contradicts its spec
Arsene12358 Oct 31, 2026
8b5a268
fix: say probes only for vLLM 0.31.0 memory and merge bindings into t…
Arsene12358 Oct 31, 2026
142b09e
docs: count three adapters and scope the per-phase prefix-caching checks
Arsene12358 Oct 31, 2026
420ff9b
docs: state the reasons in code comments instead of plan references
Arsene12358 Oct 31, 2026
47a7560
fix: refuse prefix-caching evidence that contradicts the resolved cac…
Arsene12358 Oct 31, 2026
6ad04e9
fix: require the block counts of Mamba state groups and refuse specul…
Arsene12358 Oct 31, 2026
1cc3771
fix: match Mamba layer views with the recorded state tensors
Arsene12358 Oct 31, 2026
4457503
fix: compare the cache geometry of every formal phase with the accept…
Arsene12358 Oct 31, 2026
ecce85d
fix: require the mode of every Mamba state group and the scheduler bl…
Arsene12358 Oct 31, 2026
f23d680
fix: apply the compressed-storage and view kernel block rules on import
Arsene12358 Oct 31, 2026
b1aacd4
fix: re-check seven observer guarantees of vLLM 0.31.0 records on import
Arsene12358 Oct 31, 2026
c25e3e5
docs: limit the block size claim of the compressed-storage comment
Arsene12358 Oct 31, 2026
c5790c8
fix: keep extra cache settings in vLLM 0.27.0 and 0.28.0 provenance
Arsene12358 Oct 31, 2026
d270450
fix: read prefix-caching evidence only from vLLM 0.31.0 records
Arsene12358 Oct 31, 2026
968bc5a
test: cover the prefix-caching evidence check across mixed phases
Arsene12358 Oct 31, 2026
1c72908
fix: require each cache group page to match its layer specs
Arsene12358 Oct 31, 2026
163f71c
fix: recompute the scheduler block sizes and Mamba state views on import
Arsene12358 Oct 31, 2026
459fa67
fix: check the hash block size of schedulers without prefix caching
Arsene12358 Oct 31, 2026
4789c2f
test: reach the per-phase prefix-caching check of the phase binding a…
Arsene12358 Oct 31, 2026
b824610
fix: check Mamba group blocks against the Mamba block size and kernels
Arsene12358 Nov 1, 2026
ab9ef96
docs: name the source of the Mamba block in a test helper docstring
Arsene12358 Nov 1, 2026
ecfacf3
fix: refuse scheduler hash block sizes that vLLM cannot start with
Arsene12358 Nov 1, 2026
1dbd190
docs: limit a test comment to the blocks in prefix caching
Arsene12358 Nov 1, 2026
49f11f0
fix: check scheduler hash block sizes with SlidingWindowMLASpec groups
Arsene12358 Nov 1, 2026
4837618
fix: require one SlidingWindowMLASpec choice to meet every hash rule
Arsene12358 Nov 1, 2026
4003cfe
fix: skip the abstract tokens_per_state of uniform cache group specs
Arsene12358 Nov 1, 2026
34c26d5
test: cover the fallback branches of the scheduler hash block check
Arsene12358 Nov 1, 2026
bda81d8
docs: update observer line citations and a test fake comment
Arsene12358 Nov 1, 2026
83daeef
fix: read the remote config commit from the config object itself
Arsene12358 Nov 2, 2026
43ad239
docs: name the etcd and Dynamo inputs of the stock vLLM 0.31.0 image
Arsene12358 Nov 2, 2026
af47be4
docs: update observer line citations and two notes on the commit read
Arsene12358 Nov 2, 2026
ef70678
docs: say that the GB300 probes observed the GLM groups, and limit st…
Arsene12358 Nov 6, 2026
8713e55
fix: check state group block counts against the recorded vLLM concurr…
Arsene12358 Nov 6, 2026
5b0c794
Merge main into the state cache groups branch
Arsene12358 Nov 8, 2026
46d9f83
Merge the state cache groups branch into the hybrid probe import branch
Arsene12358 Nov 8, 2026
0c96820
Merge main into the hybrid probe import branch
Arsene12358 Nov 9, 2026
7b54ff9
Merge main into the hybrid probe import branch
Arsene12358 Nov 10, 2026
f17160f
fix: tell a hybrid cache record by its layer specs, not by its layer …
Arsene12358 Nov 10, 2026
91bebb4
refactor: remove the phase check that the cache geometry comparison c…
Arsene12358 Nov 10, 2026
26c50f7
feat: bundle the runtime probe for vLLM 0.33.0 and drop the 0.31.0 bu…
Arsene12358 Nov 10, 2026
c84f48e
fix: read the loaded config commit from the pinned snapshot on the pr…
Arsene12358 Nov 10, 2026
dc9dae4
test: pin that an unpinned revision triggers no snapshot lookup on th…
Arsene12358 Nov 10, 2026
dbc388a
feat: record and import the kernel-block views of vLLM 0.33.0
Arsene12358 Nov 10, 2026
4e4165b
docs: describe the kernel-block views in the vLLM 0.33.0 probe notes
Arsene12358 Nov 10, 2026
19347bb
feat: hold the prefill checkpoint blocks of a state group in FPM prof…
Arsene12358 Nov 10, 2026
e5c8142
feat: import one prefill checkpoint block of a Mamba state group
Arsene12358 Nov 10, 2026
a624121
test: pin the refusals of malformed prefill checkpoint evidence
Arsene12358 Nov 10, 2026
5a97692
docs: describe the hybrid runtime probe on vLLM 0.33.0
Arsene12358 Nov 10, 2026
c28839a
docs: cite vLLM 0.33.0 lines in the comments of the hybrid probe path
Arsene12358 Nov 10, 2026
a9eebd1
docs: state the FlashKDA conditions and the unresolved memory of hybr…
Arsene12358 Nov 10, 2026
9d52b1a
Merge main into the hybrid probe import branch
Arsene12358 Nov 10, 2026
5682d5f
fix: import hybrid cache evidence only from vLLM 0.33.0 probe records
Arsene12358 Nov 10, 2026
401d4db
docs: state that a vLLM patch release gets no hybrid cache evidence
Arsene12358 Nov 10, 2026
2f85832
test: import the live GLM-5.3-Flash probe record of vLLM 0.33.0
Arsene12358 Nov 10, 2026
f42cb20
test: rebuild the GLM-5.3-Flash test fakes from the live vLLM 0.33.0 …
Arsene12358 Nov 10, 2026
ab9ba5a
docs: add the measured vLLM 0.33.0 values of the GLM-5.3-Flash probe
Arsene12358 Nov 10, 2026
a53c0a5
docs: scope the scheduler mamba_block_size note to the multiprocess e…
Arsene12358 Nov 10, 2026
18ebfbe
Merge main into the hybrid probe import branch
Arsene12358 Nov 10, 2026
8ca8a23
docs: state the pinned Dynamo scheduler file and correct source citat…
Arsene12358 Nov 10, 2026
a95291a
fix: keep the grouped review line of plain drafts and name state grou…
Arsene12358 Nov 10, 2026
3bba901
test: cover the hybrid import and observer refusals that had no test
Arsene12358 Nov 10, 2026
92d2f02
refactor: remove a layer view refusal that cannot fire
Arsene12358 Nov 10, 2026
5f4200a
chore: keep ruff off the frozen bundle copies of the vLLM 0.33.0 prob…
Arsene12358 Nov 10, 2026
011dd8d
docs: scope the vLLM 0.31.0 import refusal to hybrid probe records
Arsene12358 Nov 10, 2026
02885ca
fix: refuse a prefix match unit that vLLM 0.33.0 rejects for a single…
Arsene12358 Nov 10, 2026
34a356d
docs: note how vLLM 0.33.0 sets the block size of a single cache group
Arsene12358 Nov 11, 2026
fc1dec6
Merge main into the hybrid probe import branch
Arsene12358 Nov 11, 2026
7a88f33
Merge main into the hybrid probe import branch
Arsene12358 Nov 11, 2026
d32900b
ci: switch workflows to renamed AISim runner pools (#861)
saturley-hall Nov 13, 2026
c4eb77f
fix: merge main and retain hybrid runtime probe assets
jasonqinzhou Nov 14, 2026
1c8fa60
fix: observe and validate Mamba startup block reservations
jasonqinzhou Nov 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions crates/core/src/engine/kv_manager/grouped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ impl GroupedKvPool {
.map(|lease| lease.bytes)
}

/// Bytes that the state groups hold for one running request, whatever
/// its context length: the state charge computed when the pool is built,
/// or `u64::MAX` when those bytes overflow.
pub(crate) fn fixed_request_bytes(&self) -> u64 {
self.state.as_ref().map_or(u64::MAX, |state| state.bytes)
}

/// Reserve every group atomically. Expired blocks become reusable in this
/// transition, but failed attempts leave both the lease and pool unchanged.
pub(crate) fn allocate(
Expand Down Expand Up @@ -144,6 +151,8 @@ mod tests {
page_size_bytes: 8,
sliding_window: None,
blocks_per_request: None,
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
},
FpmCacheGroup {
name: "window".into(),
Expand All @@ -153,10 +162,13 @@ mod tests {
page_size_bytes: 6,
sliding_window: Some(3),
blocks_per_request: None,
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
},
],
42,
);
assert_eq!(pool.fixed_request_bytes(), 0);
let mut first = None;
let mut second = None;
assert!(pool.allocate(&mut first, 0, 4)); // 8 + 2 * 6 = 20
Expand Down Expand Up @@ -189,6 +201,8 @@ mod tests {
page_size_bytes: 8,
sliding_window: None,
blocks_per_request: None,
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
},
FpmCacheGroup {
name: "kda".into(),
Expand All @@ -198,10 +212,14 @@ mod tests {
page_size_bytes: 10,
sliding_window: None,
blocks_per_request: Some(2),
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
},
],
100,
);
// Only the state group counts: 2 blocks of 10 bytes.
assert_eq!(pool.fixed_request_bytes(), 20);
let mut lease = None;
assert!(pool.allocate(&mut lease, 0, 4)); // 8 + 2 * 10 = 28
assert_eq!(lease.as_ref().unwrap().blocks(), 3); // 0..1 and the state's 0..2
Expand All @@ -225,6 +243,8 @@ mod tests {
page_size_bytes,
sliding_window: None,
blocks_per_request: Some(blocks),
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
};
let mut pool = GroupedKvPool::new(vec![state("kda", 10, 2), state("tail", 6, 1)], 100);
assert_eq!(pool.required_bytes(0, 0), Some(0));
Expand Down
22 changes: 20 additions & 2 deletions crates/core/src/engine/scheduler/vllm/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2488,6 +2488,18 @@ impl VllmCore {
.map(|request| request.sequence.num_input_tokens()),
max_model_len = self.args.max_model_len,
num_gpu_blocks = self.args.num_gpu_blocks,
grouped_minimum_forward_bytes = self
.kv_manager
.grouped()
.zip(self.state.requests.get(&uuid))
.and_then(|(pool, request)| {
let known_tokens = request.sequence.len();
pool.required_bytes(known_tokens.saturating_sub(1), known_tokens)
}),
grouped_capacity_bytes = self
.kv_manager
.grouped()
.map(GroupedKvPool::capacity_bytes),
"rejecting request that exceeds a worker admission limit"
);
rejected_uuids.push(uuid);
Expand Down Expand Up @@ -3186,8 +3198,14 @@ impl VllmCore {
.ok_or_else(|| anyhow::anyhow!("grouped KV forward byte calculation overflowed"))?;
anyhow::ensure!(
required <= pool.capacity_bytes(),
"request {uuid} grouped KV forward needs {required} bytes for {desired_tokens} scheduled tokens after {effective_computed_before} computed tokens, exceeding the entire {}-byte cache pool; reduce max_num_batched_tokens or increase cache memory",
pool.capacity_bytes()
"request {uuid} grouped KV forward needs {required} bytes for {desired_tokens} scheduled tokens after {effective_computed_before} computed tokens, exceeding the entire {}-byte cache pool{}; reduce max_num_batched_tokens or increase cache memory",
pool.capacity_bytes(),
match pool.fixed_request_bytes() {
0 => String::new(),
fixed => format!(
"; the fixed state blocks of one request take {fixed} bytes of this pool"
),
}
);
}
let mut actual_computed_after = desired_computed_after;
Expand Down
47 changes: 47 additions & 0 deletions crates/core/src/engine/scheduler/vllm/grouped_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ fn group(name: &str, block: u32, bytes: u64, window: Option<u32>) -> FpmCacheGro
page_size_bytes: bytes,
sliding_window: window,
blocks_per_request: None,
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
}
}

Expand All @@ -56,6 +58,8 @@ fn state(name: &str, bytes: u64, blocks: u32) -> FpmCacheGroup {
page_size_bytes: bytes,
sliding_window: None,
blocks_per_request: Some(blocks),
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
}
}

Expand Down Expand Up @@ -241,6 +245,8 @@ fn grouped_oversized_chunk_fails_without_partial_allocation_or_endless_preemptio
.contains("exceeding the entire 8-byte cache pool")
);
assert!(error.to_string().contains("reduce max_num_batched_tokens"));
// Without a state group the message has no sentence about fixed bytes.
assert!(!error.to_string().contains("fixed state blocks"));
assert_eq!(core.state.requests[&id].num_computed_tokens, 8);
assert_eq!(core.state.requests[&id].sequence.num_allocated_tokens(), 8);
assert_eq!(core.mocker_metrics().kv_cache_used_bytes, Some(8));
Expand All @@ -250,6 +256,47 @@ fn grouped_oversized_chunk_fails_without_partial_allocation_or_endless_preemptio
assert_eq!(core.mocker_metrics().kv_cache_used_bytes, Some(0));
}

#[test]
fn grouped_state_blocks_exceeding_the_pool_reject_at_admission() {
// The 16-byte state block alone is larger than the 12-byte pool, so even
// the one-token forward cannot fit and the request never reaches a forward.
let mut core = core(vec![group("full", 4, 4, None), state("kda", 16, 1)], 12, 8);
let id = submit(&mut core, 115, 4, 2);
let mut trace = TraceCollector::default();
let pass = core.execute_pass(&mut trace, 0.0);
assert!(pass.admissions.is_empty());
assert!(
pass.output_signals
.iter()
.any(|output| output.uuid == id && output.rejected)
);
assert_eq!(pass.mocker_metrics.kv_cache_used_bytes, Some(0));
}

#[test]
fn grouped_oversized_chunk_names_the_fixed_state_bytes() {
let mut core = core(
vec![group("window", 4, 4, Some(4)), state("kda", 2, 1)],
9,
8,
);
submit(&mut core, 116, 16, 2);
let mut trace = TraceCollector::default();
// The one-token forward needs one 4-byte window page and the 2-byte state
// block, 6 bytes, so admission passes. The first chunk of 8 tokens needs
// two window pages (8 bytes) and the state block, 10 bytes, above the pool.
let error = core
.try_execute_pass(&mut trace, 0.0)
.unwrap_err()
.to_string();
assert!(error.contains("needs 10 bytes for 8 scheduled tokens after 0 computed tokens"));
assert!(error.contains("exceeding the entire 9-byte cache pool"));
assert!(error.contains("the fixed state blocks of one request take 2 bytes"));
assert!(error.contains("reduce max_num_batched_tokens"));
// The sentence comes before the remedy.
assert!(error.contains("2 bytes of this pool; reduce max_num_batched_tokens"));
}

#[test]
fn grouped_handoff_commands_fail_before_acquiring_state() {
let mut core = core(vec![group("window", 4, 4, Some(4))], 24, 8);
Expand Down
85 changes: 84 additions & 1 deletion crates/core/src/perfmodel/fpm/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ pub struct FpmCacheGroup {
/// for every other kind.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub blocks_per_request: Option<u32>,
/// The `num_prefill_checkpoint_blocks` of a Mamba spec: 0 or 1, and only
/// in a `state` group. In vLLM 0.33.0, a KDA layer that prefills with
/// FlashKDA has one checkpoint block.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prefill_checkpoint_blocks: Option<u32>,
/// The `prefill_checkpoint_alignment` of a Mamba spec, in tokens: 16 for
/// FlashKDA in vLLM 0.33.0. Positive, and only with
/// `prefill_checkpoint_blocks` of 1.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prefill_checkpoint_alignment: Option<u32>,
}

impl FpmCacheGroup {
Expand Down Expand Up @@ -96,6 +106,22 @@ impl FpmCacheGroup {
"blocks_per_request applies only to state cache groups",
));
}
if self
.prefill_checkpoint_blocks
.is_some_and(|blocks| self.kind != FpmCacheKind::State || blocks > 1)
{
return Err(invalid(
"prefill_checkpoint_blocks requires a state group and must be 0 or 1",
));
}
if self
.prefill_checkpoint_alignment
.is_some_and(|alignment| self.prefill_checkpoint_blocks != Some(1) || alignment == 0)
{
return Err(invalid(
"prefill_checkpoint_alignment requires prefill_checkpoint_blocks=1 and must be positive",
));
}
Ok(())
}

Expand Down Expand Up @@ -750,6 +776,8 @@ mod tests {
page_size_bytes: 160,
sliding_window: window,
blocks_per_request: None,
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
}
}

Expand Down Expand Up @@ -1375,6 +1403,38 @@ mod tests {
}
}

#[test]
fn checkpoint_fields_need_a_state_group_and_each_other() {
let blocks_text = "prefill_checkpoint_blocks requires a state group and must be 0 or 1";
let alignment_text = "prefill_checkpoint_alignment requires prefill_checkpoint_blocks=1 and must be positive";
let checkpoint = |blocks, alignment| FpmCacheGroup {
prefill_checkpoint_blocks: blocks,
prefill_checkpoint_alignment: alignment,
..state_group(Some(1))
};
for (blocks, alignment) in [(Some(0), None), (Some(1), None), (Some(1), Some(16))] {
checkpoint(blocks, alignment).validate().unwrap();
}
let attention = FpmCacheGroup {
prefill_checkpoint_blocks: Some(0),
..group(None)
};
assert_eq!(rejection(&attention), blocks_text);
assert_eq!(rejection(&checkpoint(Some(2), None)), blocks_text);
for (blocks, alignment) in [(None, Some(16)), (Some(0), Some(16)), (Some(1), Some(0))] {
assert_eq!(rejection(&checkpoint(blocks, alignment)), alignment_text);
}
// The kind checks run first, so an invalid group keeps its first error.
let unusable = FpmCacheGroup {
prefill_checkpoint_blocks: Some(2),
..state_group(None)
};
assert_eq!(
rejection(&unusable),
"state cache groups require a positive blocks_per_request"
);
}

#[test]
fn state_group_holds_a_fixed_range_for_any_length() {
let state = state_group(Some(2));
Expand Down Expand Up @@ -1415,6 +1475,8 @@ mod tests {
page_size_bytes: 13_045_120,
sliding_window: None,
blocks_per_request,
prefill_checkpoint_blocks: None,
prefill_checkpoint_alignment: None,
};
let attention = pool_group("mla_indexer", FpmCacheKind::Attention, 22, None);
let states = [
Expand Down Expand Up @@ -1458,7 +1520,28 @@ mod tests {
let saved = serde_json::to_value(&state).unwrap();
assert_eq!(saved["kind"], "state");
assert_eq!(saved["blocks_per_request"], 1);
for original in [attention, state] {
// A group saved without the checkpoint fields loads with both absent and saves unchanged.
let earlier = r#"{"name":"state","kind":"state","num_layers":2,"block_size_tokens":16,"page_size_bytes":160,"sliding_window":null,"blocks_per_request":1}"#;
let loaded = serde_json::from_str::<FpmCacheGroup>(earlier).unwrap();
assert_eq!(loaded, state);
assert_eq!(
(
loaded.prefill_checkpoint_blocks,
loaded.prefill_checkpoint_alignment
),
(None, None)
);
assert_eq!(serde_json::to_string(&loaded).unwrap(), earlier);
// Set fields follow the block count in declaration order.
let marked = FpmCacheGroup {
prefill_checkpoint_blocks: Some(1),
prefill_checkpoint_alignment: Some(16),
..state_group(Some(1))
};
assert!(serde_json::to_string(&marked).unwrap().ends_with(
r#""blocks_per_request":1,"prefill_checkpoint_blocks":1,"prefill_checkpoint_alignment":16}"#
));
for original in [attention, state, marked] {
let saved = serde_json::to_string(&original).unwrap();
assert_eq!(
serde_json::from_str::<FpmCacheGroup>(&saved).unwrap(),
Expand Down
2 changes: 1 addition & 1 deletion docs/perf-model/fpm-self-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ For online learning from per-iteration telemetry, continue with
| Parallelism | Whole-pass timing can capture intra-iteration computation and communication. Exact topology/resource identity and query coverage remain required; see [current guided CLI coverage](implementation.md#parallelism-support-and-guided-cli-coverage) for collection automation limits. |
| Self-benchmark serving roles | Aggregated workers collect both prefill and decode. Prefill and decode can also be collected independently with separate accepted configurations. Their role exports must be composed separately for serving; `onboard validate-fpm` currently validates aggregated replay. |
| Self-benchmark GPU execution | Kubernetes by default, or Slurm/Pyxis inside a caller-owned allocation. Both have multi-node launch paths; placement and GPU requirements come from the generated plan. The workflow does not provision the cluster or acquire a Slurm allocation. |
| KV cache | Supports standard per-token KV caches, as used by Llama, Qwen3 and MiniMax-M2. Models with linear-attention state, such as Kimi K3's KDA, use the [measured-profile path](examples.md#example-a-onboard-the-collected-kimi-k3-tp8dcp8-profile), with the KV cache and state-management limits described in that example. Some configs leave the cache geometry to the [runtime probe](implementation.md#cache-geometry-pending-the-runtime-probe): linear-attention and recurrent-state configs, and architectures that intake does not recognize. For them, `onboard init --model-config` stops with guidance to run the probe, which measures the geometry. A cache geometry override for these configs is a claim that `onboard import-observations` checks against that measurement. Importing cache groups other than full or sliding attention (for example recurrent state) is planned. Other KV cache types may also work, but may need changes to the self-benchmarker to initialize their state and measure the forward pass correctly. |
| KV cache | Supports standard per-token KV caches, as used by Llama, Qwen3 and MiniMax-M2. Models with linear-attention state, such as Kimi K3's KDA, use the [measured-profile path](examples.md#example-a-onboard-the-collected-kimi-k3-tp8dcp8-profile), with the KV cache and state-management limits described in that example. Some configs leave the cache geometry to the [runtime probe](implementation.md#cache-geometry-pending-the-runtime-probe): linear-attention and recurrent-state configs, and architectures that intake does not recognize. For them, `onboard init --model-config` stops with guidance to run the probe, which measures the geometry. A cache geometry override for these configs is a claim that `onboard import-observations` checks against that measurement. On vLLM 0.33.0 with the Dynamo scheduler file of the `release/1.7.0` branch that the bundle pins ([source notes](../../../python/aisim/collector/fpm_forward/runtime/instrumentation/vllm-0.33.0.md)), the probe imports recurrent-state and tail caches as `state` groups. Other KV cache types may also work, but may need changes to the self-benchmarker to initialize their state and measure the forward pass correctly. |
| Multimodality | For multimodal models, this workflow covers text generation only; image/audio processing time is excluded. |

Use a source revision containing the required CLI and consumer features; a
Expand Down
Loading
Loading