vLLM 推理流程分析

1. 概述

本文追踪 vLLM V1 引擎中一个完整的推理 step —— 从请求提交到 token 输出、再到 KV cache 更新的全过程。vLLM 的推理采用连续批处理(continuous batching) 模式,每个 step 不区分 prefill/decode 阶段,而是统一调度所有运行中请求的 token 预算。


2. 推理流程全景

Step 循环
  │
  ├─ 1. Scheduler.schedule()
  │     ├─ 遍历 running 请求 → 分配 token 预算 + KV cache block
  │     ├─ 遍历 waiting 请求 → prefix cache 查找 + 新 block 分配
  │     └─ 输出 SchedulerOutput
  │
  ├─ 2. Executor.execute_model(scheduler_output)
  │     └─ GPUModelRunner.execute_model()
  │        ├─ _update_states(): 同步 InputBatch 状态
  │        ├─ _prepare_inputs(): 构建 token_ids, positions, seq_lens, slot_mapping
  │        ├─ _build_attention_metadata(): 构建 block_table + 各 backend 元数据
  │        ├─ _preprocess(): 多模态 encoder / input embedding
  │        ├─ _model_forward(): model(input_ids, positions) → hidden_states
  │        └─ logits = compute_logits(hidden_states[logits_indices])
  │
  ├─ 3. Executor.sample_tokens(grammar_output)
  │     └─ Sampler.forward()
  │        ├─ logprobs / logits processors / penalties
  │        └─ greedy 或 temperature + top-k/top-p 采样
  │
  ├─ 4. Scheduler.update_from_output(scheduler_output, model_output)
  │     ├─ 追加输出 token、检查停止条件
  │     ├─ 释放已完成请求的 KV cache block
  │     └─ 生成 EngineCoreOutput
  │
  └─ 5. OutputProcessor.process_outputs()
        ├─ detokenize(token ID → 文本)
        ├─ logprobs 计算
        └─ 返回 RequestOutput(或放入异步队列)

3. 请求提交

3.1 入口

入口 文件 行号
离线推理 llm.py L194
API 服务器(异步) async_llm.py L524

两种入口均经过以下路径:

# 异步路径(API 服务器)
AsyncLLM.generate()                          # [async_llm.py:524]
   add_request()                            # [async_llm.py:280]
     InputProcessor.process_inputs()        # 预处理输入(tokenize 等)
     OutputProcessor.add_request()          # 注册到输出处理器
     EngineCoreClient.add_request()         # 发送到 EngineCore

3.2 EngineCore 接收请求

core.py:1294EngineCore._handle_client_request() 分发 ADD 类型请求到 preprocess_add_request()core.py:794):

preprocess_add_request():
  ├─ 将 EngineCoreRequest 转换为 Request 对象
  ├─ 附加 grammar state(结构化输出)
  ├─ 管理多模态 receiver cache
  └─ Scheduler.add_request() → 进入 waiting 队列

请求的数据结构:request.pyRequest 对象包含 request_idprompt_token_idssampling_paramsnum_computed_tokens(已计算的 token 数,初始为 0)、status 等。


4. Scheduler 调度

4.1 调度入口

scheduler.py:329Scheduler.schedule() 是每个 step 的入口:

Scheduler.schedule():
  Phase 1: 处理 running 请求
  Phase 2: 处理 waiting 请求
  → 返回 SchedulerOutput

4.2 Phase 1:Running 请求

scheduler.py:364 — 遍历 self.running 队列中的每个请求:

对每个 running 请求:
  ├─ 计算 num_new_tokens:
  │   受 token budget 限制 (max_num_batched_tokens / num_seqs)
  │   decode 阶段: 1 token(或 spec_decode 的 lookahead 数量)
  │   prefill 阶段: 剩余 prompt token 数量
  │
  ├─ kv_cache_manager.allocate_slots(request, num_new_tokens)
  │   [kv_cache_manager.py:236]
  │   ├─ 释放不再需要的 block(如 sliding window 外的旧 block)
  │   ├─ 处理 prefix-cached token(已命中缓存的 block 无需重复计算)
  │   └─ 分配新的物理 block
  │
  └─ 若 block 不足 → 抢占低优先级请求(preemption)

4.3 Phase 2:Waiting 请求

scheduler.py:544 — 遍历 self.waiting 队列:

对每个 waiting 请求:
  ├─ kv_cache_manager.get_computed_blocks(request)
  │   [kv_cache_manager.py:194]
  │   └─ coordinator.find_longest_cache_hit()
  │       [single_type_kv_cache_manager.py:373]
  │       ├─ 计算 token block hashes
  │       ├─ 查找 BlockHashToBlockMap
  │       └─ 返回命中的 KVCacheBlock 列表(prefix caching)
  │
  ├─ allocate_slots() → 为 prompt token 分配新 block
  │
  └─ 若 token budget 充足 → 从 waiting 移入 running

4.4 SchedulerOutput

output.py:181 — 调度结果包含:

字段 说明
scheduled_new_reqs 新加入 running 的请求
scheduled_cached_reqs 命中 prefix cache 的请求
num_scheduled_tokens 每个请求本次调度的 token 数
total_num_scheduled_tokens 总 token 数(用于 CUDA graph 选择)
scheduled_spec_decode_tokens 推测解码 token 数
num_common_prefix_blocks 公共前缀 block 数(用于 cascade attention)
new_block_ids_to_zero 新分配的 block ID(需清零旧数据)
finished_req_ids 需清理的已完成请求

5. 模型执行

core.py:428EngineCore.step() 的调度-执行-采样三步:

def step(self):
    scheduler_output = self.scheduler.schedule()        # 调度
    future = self.model_executor.execute_model(          # 执行
        scheduler_output, non_block=True)
    grammar_output = self.scheduler.get_grammar_bitmask(scheduler_output)
    model_output = future.result()
    if model_output is None:
        model_output = self.model_executor.sample_tokens(grammar_output)  # 采样
    self.scheduler.update_from_output(scheduler_output, model_output)     # 更新

5.1 GPUModelRunner.execute_model()

gpu_model_runner.py:3955 — 模型执行的核心,按顺序完成 6 个子步骤:

5.1.1 _update_states() — 状态同步

gpu_model_runner.py:1116

_update_states(scheduler_output):
  ├─ 移除已完成请求 → 从 InputBatch 中删除
  ├─ 添加新请求 → 创建 CachedRequestState 对象
  │   存储: req_id, prompt_token_ids, num_computed_tokens, block_ids, ...
  ├─ 更新 block IDs → 反映本次调度新分配的 block
  ├─ 更新 num_computed_tokens → 反映 prefix cache 命中
  ├─ 清零新 block (_zero_block_ids) → 防止读到未被写入的 KV cache 位置
  ├─ 压缩 batch → 填补被移除请求留下的空隙
  └─ 可选:重排序 batch → 适应 attention backend 偏好(如 MLA)

核心数据结构是 InputBatchgpu_model_runner.py),它在 GPU 端维护 block_tabletoken_idspositionsseq_lens 等张量。

5.1.2 _prepare_inputs() — 构建输入

gpu_model_runner.py:1863

_prepare_inputs():
  ├─ 计算 positions:
  │   对每个 token: position = num_computed_tokens[req] + offset_in_query
  │   这是 vLLM 管理"已计算多少 token"的关键
  │
  ├─ 收集 input_ids:
  │   从 CPU token tensor 按 index 选取 → GPU flat buffer
  │
  ├─ 计算 query_start_loc:
  │   [0, tokens_req0, tokens_req0+tokens_req1, ...]
  │   FlashAttention 的 varlen 接口需要此信息
  │
  ├─ 计算 seq_lens:
  │   seq_len = num_computed_tokens + num_scheduled_tokens
  │   (prefill 中 num_scheduled_tokens 可能 > 1,decode 中 = 1)
  │
  ├─ block_table.compute_slot_mapping() [L2093]:
  │   对每个 token:
  │     block_number = block_table[req_idx][token_idx // block_size]
  │     offset = token_idx % block_size
  │     slot = block_number * block_size + offset
  │   → 输出 slot_mapping(每个 token 在 KV cache 中的写入位置)
  │
  └─ _calc_spec_decode_metadata(): 推测解码元数据

5.1.3 _build_attention_metadata() — 构建 attention 元数据

gpu_model_runner.py:2183

_build_attention_metadata():
  ├─ 创建 CommonAttentionMetadata [L2280]:
  │   ├─ query_start_loc: 每个请求的 query 起始位置
  │   ├─ seq_lens: 每个请求的序列总长度
  │   ├─ block_table_tensor: [num_seqs, max_blocks] 页表
  │   ├─ slot_mapping: 每个 token 的 cache slot
  │   ├─ positions: 每个 token 的位置编码
  │   ├─ is_prefilling: 每个 token 是否处于 prefill 阶段
  │   ├─ max_query_len: 最大 query 长度
  │   └─ max_seq_len: 最大序列长度
  │
  └─ 对每个 KV cache group:
       backend_metadata = builder.build(common_prefix_len, common_attn_metadata)
       ├─ FlashAttentionMetadataBuilder.build() [flash_attn.py:388]
       │   ├─ 构建 FlashAttentionMetadata(含 block_table, slot_mapping)
       │   ├─ 处理 cascade attention(公共前缀分离)
       │   ├─ FA3 AOT scheduler metadata
       │   └─ DCP(Decode Context Parallelism)支持
       └─ TritonAttentionMetadataBuilder.build() [triton_attn.py:130]
           └─ 构建 Triton 专用的元数据

is_prefilling 的状态判断(gpu_model_runner.py:2270is_prefilling = num_computed_tokens < num_prompt_tokens):

条件 is_prefilling 含义
num_computed_tokens < num_prompt_tokens True 仍有 prompt token 需要计算(prefill 或 chunked prefill 中间块)
num_computed_tokens >= num_prompt_tokens False prompt 已全部计算完毕,进入 decode 阶段

5.1.4 _preprocess() — 预处理

gpu_model_runner.py:3364

_preprocess():
  ├─ 多模态模型:
  │   ├─ 运行 MM encoder(处理图片/音频等)
  │   ├─ 收集多模态 embeddings
  │   └─ model.embed_input_ids() → 混合 text + mm embeddings
  │
  └─ 纯文本模型:
       ├─ 使用原始 token ID 作为 input_ids
       └─ 准备 positions, intermediate_tensors (PP), model_kwargs

5.1.5 _model_forward() — 模型前向传播

gpu_model_runner.py:3668

def _model_forward(self, input_ids, positions, ...):
    hidden_states = self.model(
        input_ids=input_ids,
        positions=positions,
        ...
    )
    return hidden_states

模型内部每一层会调用 Attention.forward()attention.py:437),详见第 6 节。

5.1.6 logits 提取

# 从最后一个 token 位置提取 hidden states
logits_hidden = hidden_states[logits_indices]  # [num_reqs, hidden_size]
# 通过 lm_head 计算 logits
logits = self.model.compute_logits(logits_hidden)  # [num_reqs, vocab_size]

logits_indices 是每个请求的最后一个 token 在 batch 中的位置索引。公式为 query_start_loc[1:] - 1gpu_model_runner.py:2135)。例如 batch 中有 3 个请求,分别调度了 [1, 5, 1] 个 token,query_start_loc = [0, 1, 6, 7],则 logits_indices = [0, 5, 6](取每个请求的最后一个 token)。

5.2 执行结果暂存

结果存储在 ExecuteModelStategpu_model_runner.py:399):包含 logitshidden_statessampling_metadataspec_decode_metadata 等。execute_model() 返回 None,采样延迟到 sample_tokens() 中执行。


6. Attention 执行细节

6.1 Attention 分发

attention.py:437 — 模型每层的 Attention.forward() 是 KV cache 读写和 attention 计算的分发点:

class Attention.forward(query, key, value, kv_cache, attn_metadata, output):
    if impl.forward_includes_kv_cache_update:
        # KV cache 写入融合在 attention 内部(如 Triton、某些 FlashInfer 配置)
        impl.forward(..., kv_cache, attn_metadata, output)
    else:
        # 独立的 KV cache 写入 + attention 计算(FlashAttention 默认路径)
        unified_kv_cache_update(key, value, kv_cache, slot_mapping)  # 先写 KV cache
        unified_attention_with_output(query, kv_cache, attn_metadata, output)  # 再算 attention

6.2 FlashAttention 路径(默认)

flash_attn.py:667FlashAttentionImpl.forward()

def forward(self, query, key, value, kv_cache, attn_metadata, output):
    key_cache, value_cache = kv_cache.unbind(dim=0)
    # key_cache:   [num_blocks, block_size, num_kv_heads, head_size]
    # value_cache: [num_blocks, block_size, num_kv_heads, head_size]

    output[:] = flash_attn_varlen_func(
        query, key_cache, value_cache,
        cu_seqlens_q=attn_metadata.query_start_loc,
        max_seqlen_q=attn_metadata.max_query_len,
        seqlen_k=attn_metadata.seq_lens,
        block_table=attn_metadata.block_table,  # ← 分页的关键
        softmax_scale=self.scale,
        causal=True,
    )

FlashAttention kernel 内部通过 block_table 做逻辑→物理 block 的间接寻址。

6.3 KV Cache 写入

flash_attn.py:850FlashAttentionImpl.do_kv_cache_update()

def do_kv_cache_update(self, key, value, kv_cache, slot_mapping):
    key_cache, value_cache = kv_cache  # 已解绑的 key/value cache tensors
    reshape_and_cache_flash(
        key, value, key_cache, value_cache,
        slot_mapping,     # 每个 token 的目标 slot
        kv_cache_dtype,   # FP8 量化时做格式转换
        k_scale, v_scale,
    )

slot_mapping(形状 [total_tokens])的每个元素指定了对应 token 的 key/value 写入 KV cache 中的哪个 slot。

prefill 与 decode 的 slot_mapping 差异

Prefill (一个请求有 5 个 prompt token):
  slot_mapping = [1040, 1041, 1042, 1043, 1044]   ← 连续写入
  (blocks: [block_65], offsets: [0, 1, 2, 3, 4])

Decode (一个请求生成 1 个 token):
  slot_mapping = [2098]                            ← 单 token 写入
  (block: block_131, offset: 2)

7. 采样

7.1 sample_tokens()

gpu_model_runner.py:4319GPUModelRunner.sample_tokens()

sample_tokens(grammar_output):
  ├─ Apply grammar bitmask(结构化输出约束)
  ├─ _sample(logits, sampling_metadata) [L3481]:
  │   ├─ 无推测解码: self.sampler(logits, sampling_metadata)
  │   └─ 有推测解码: self.rejection_sampler() → 接受/拒绝 draft tokens
  │
  └─ 输出 ModelRunnerOutput:
      ├─ sampled_token_ids: 每个请求采样的 token
      ├─ logprobs: log probabilities
      ├─ req_id_to_index: 请求 ID → batch 索引映射
      └─ spec_decode_metadata: 推测解码结果

7.2 Sampler.forward()

sampler.py:67 — 核心采样逻辑:

Sampler.forward(logits, sampling_metadata):
  Step 1: 计算 logprobs(若需要)
  Step 2: logits → float32
  Step 3: apply_logits_processors() [L366]:
      ├─ allowed_token_ids_mask             (允许的 token 集合)
      ├─ bad_words 排除                     (禁用词)
      ├─ min_tokens / logit_bias            (非 argmax 不变的处理器)
      ├─ apply_all_penalties()              (重复惩罚/频率惩罚/存在惩罚)
      └─ thinking_budget_state_holder      (思维链预算)
  Step 4: sample() [L238]:
      ├─ 若 all_greedy (temperature < epsilon):
      │     → argmax, 直接返回
      └─ 否则:
            ├─ apply temperature
            ├─ min_p 处理器
            ├─ TopKTopPSampler → random sample
            └─ 返回采样结果
  Step 5: gather_logprobs() [L304]:
      ├─ torch.topk() → top-k logprobs
      └─ 计算采样 token 的 rank
  Step 6: 返回 SamplerOutput(sampled_token_ids, logprobs_tensors)

7.3 SamplingMetadata

metadata.py — 包含每个请求的采样参数:temperaturetop_ptop_k、随机数生成器 generators、惩罚参数、logits_processors 等。在 _prepare_inputs() 阶段从 SamplingParams 构建。


8. 调度器更新与请求完成

8.1 update_from_output()

scheduler.py:1283Scheduler.update_from_output()

update_from_output(scheduler_output, model_output):
  对每个被调度的请求:
    ├─ _update_request_with_output() [L1649]:
    │   ├─ 追加 output_token_ids
    │   ├─ check_stop(request, max_model_len):
    │   │   ├─ 命中 stop token → FINISHED_STOPPED
    │   │   ├─ 达到 max_tokens → FINISHED_LENGTH_CAPPED
    │   │   ├─ 停止字符串匹配
    │   │   └─ pooling 完成
    │   └─ 返回 EngineCoreOutput(new_token_ids, finish_reason, logprobs, ...)
    │
    ├─ 若请求停止:
    │   ├─ _handle_stopped_request() [L1631]:
    │   │   ├─ 可恢复请求(streaming input)→ 移回 waiting
    │   │   └─ 不可恢复 → 标记为已完成
    │   └─ _free_request() [L1842]:
    │       └─ kv_cache_manager.free(request)
    │           └─ 递减所有 block 的 ref_cnt
    │               └─ ref_cnt == 0 → 归还到 FreeKVCacheBlockQueue
    │
    └─ 发布 KV cache events

8.2 请求状态流转

request.py:315RequestStatus 枚举:

WAITING → RUNNING → (step 循环)
                  → PREEMPTED(被抢占,回 waiting)
                  → FINISHED_STOPPED
                  → FINISHED_LENGTH_CAPPED
                  → FINISHED_ABORTED
                  → FINISHED_IGNORED
                  → FINISHED_ERROR

9. 输出处理

9.1 OutputProcessor

output_processor.py:576OutputProcessor.process_outputs()

process_outputs(engine_core_outputs):
  ├─ 计算迭代统计
  ├─ IncrementalDetokenizer.update() [L639]:
  │   └─ token ID → 文本(增量解码,保留状态)
  │       └─ 检测 stop strings
  ├─ LogprobsProcessor.update_from_output() [L648]:
  │   └─ 计算 sample logprobs / prompt logprobs
  ├─ req_state.make_request_output() [L651]:
  │   └─ 构建 RequestOutput(文本, token_ids, logprobs, finish_reason)
  └─ 分发:
      ├─ AsyncLLM: put 到 per-request RequestOutputCollector 队列 [L663]
      └─ LLMEngine: 返回 List[RequestOutput] [L666]

9.2 流式输出

对于 streaming 请求,RequestOutputCollector 是一个 AsyncQueue。API 服务器的 /v1/completions/v1/chat/completions endpoint 以 SSE (Server-Sent Events) 格式流式返回每个 RequestOutput


10. KV Cache 在推理中的生命周期

10.1 首次 Prefill

Prompt token IDs: [101, 2023, 3186, 2877, 13]
block_size = 4

Step 1: allocate_slots()
  ├─ 分配 block_0(4 个 slot)→ tokens [101, 2023, 3186, 2877]
  └─ 分配 block_1(1 个 slot)→ token  [13,   -,   -,    -]

Step 2: 构建 slot_mapping
  [0, 1, 2, 3, 4]  → (block_0的4个slot, block_1的1个slot)

Step 3: Attention forward
  ├─ Q = 所有 5 个 token 的 query
  ├─ K, V = 所有 5 个 token 的 key/value
  ├─ 写入 KV cache(通过 slot_mapping)
  └─ causal mask(每个 token 只能看到自己及之前的 token)

10.2 Decode 迭代

Decode step N:

Step 1: allocate_slots()
  └─ 若当前 block 仍有空间 → 无需新分配
       否则 → 分配新 block

Step 2: slot_mapping = [block_id * block_size + offset]
  └─ 只有一个 slot

Step 3: Attention forward
  ├─ Q = 只有最新 token 的 query(单 token)
  ├─ K, V = 只有最新 token 的 key/value
  ├─ 写入 KV cache(通过 slot_mapping,写到对应 slot)
  └─ KV cache 中已有之前所有 token 的 K/V
     → block_table 告诉 kernel 如何找到它们

10.3 Prefix Caching 复用

请求 B 与请求 A 共享前缀 [101, 2023, 3186, 2877](4 个 token,block_size=4)

请求 A:
  block_0 (hash=0xABCD) → 存储这 4 个 token 的 KV

请求 B:
  get_computed_blocks() → block_0 命中!
  ├─ touch(block_0): ref_cnt = 1 → 2
  ├─ num_computed_tokens = 4(跳过这 4 个 token 的计算)
  └─ 只需从 block_1 开始分配

11. 完整 Step 调用链

EngineCore.step()                                     [core.py:428]
│
├─ Scheduler.schedule()                               [scheduler.py:329]
│   ├─ Phase 1: 遍历 running 请求                      [scheduler.py:364]
│   │   └─ kv_cache_manager.allocate_slots()           [kv_cache_manager.py:236]
│   │       ├─ remove_skipped_blocks()                 [single_type_kv_cache_manager.py:420]
│   │       ├─ allocate_new_computed_blocks()          [single_type_kv_cache_manager.py:170]
│   │       └─ allocate_new_blocks()                   [single_type_kv_cache_manager.py:243]
│   ├─ Phase 2: 遍历 waiting 请求                      [scheduler.py:544]
│   │   ├─ get_computed_blocks()                       [kv_cache_manager.py:194]
│   │   │   └─ coordinator.find_longest_cache_hit()    [single_type_kv_cache_manager.py:373]
│   │   └─ allocate_slots()
│   └─ 返回 SchedulerOutput
│
├─ Executor.execute_model(scheduler_output)            [core.py:430]
│   └─ GPUModelRunner.execute_model()                  [gpu_model_runner.py:3955]
│       ├─ _update_states()                            [gpu_model_runner.py:1116]
│       │   ├─ 移除已完成请求
│       │   ├─ 添加新请求 → CachedRequestState
│       │   ├─ 更新 block IDs / num_computed_tokens
│       │   └─ 压缩 batch
│       ├─ _prepare_inputs()                           [gpu_model_runner.py:1863]
│       │   ├─ 计算 positions
│       │   ├─ 收集 token_ids                           [gpu_model_runner.py:1950]
│       │   ├─ 计算 query_start_loc / seq_lens
│       │   └─ block_table.compute_slot_mapping()      [gpu_model_runner.py:2093]
│       ├─ _build_attention_metadata()                 [gpu_model_runner.py:2183]
│       │   ├─ CommonAttentionMetadata                  [gpu_model_runner.py:2280]
│       │   └─ 各 backend MetadataBuilder.build()
│       │       ├─ FlashAttentionMetadataBuilder       [flash_attn.py:388]
│       │       └─ TritonAttentionMetadataBuilder      [triton_attn.py:130]
│       ├─ _preprocess()                               [gpu_model_runner.py:3364]
│       │   └─ MM encoder / input embedding
│       ├─ _model_forward()                            [gpu_model_runner.py:3668]
│       │   └─ model(input_ids, positions, ...)
│       │       └─ 每层 Attention.forward()            [attention.py:437]
│       │           ├─ KV cache 写入 (unified_kv_cache_update)
│       │           │   └─ reshape_and_cache_flash()   [cache_kernels.cu:304]
│       │           └─ Attention 计算
│       │               └─ flash_attn_varlen_func()    [flash_attn.py:667]
│       │                   └─ 内部通过 block_table 寻址 KV cache
│       └─ logits = compute_logits(hidden_states[logits_indices])
│
├─ Executor.sample_tokens(grammar_output)              [core.py:434]
│   └─ GPUModelRunner.sample_tokens()                  [gpu_model_runner.py:4319]
│       └─ Sampler.forward()                           [sampler.py:67]
│           ├─ apply_logits_processors()               [sampler.py:366]
│           ├─ sample() (greedy / top-k-top-p)         [sampler.py:238]
│           └─ gather_logprobs()                       [sampler.py:304]
│
├─ Scheduler.update_from_output(output)                [scheduler.py:1283]
│   ├─ _update_request_with_output()                   [scheduler.py:1649]
│   │   ├─ 追加 output_token_ids
│   │   └─ check_stop() → finish_reason
│   ├─ _handle_stopped_request()                       [scheduler.py:1631]
│   ├─ _free_request() → kv_cache_manager.free()       [scheduler.py:1842]
│   └─ 返回 EngineCoreOutputs
│
└─ OutputProcessor.process_outputs(outputs)             [output_processor.py:576]
    ├─ IncrementalDetokenizer.update()                 [output_processor.py:639]
    ├─ LogprobsProcessor.update_from_output()          [output_processor.py:648]
    └─ RequestOutput → 返回或放入异步队列

12. 关键文件索引

组件 文件 核心行号
LLM 入口 llm.py L194
AsyncLLM async_llm.py L280, L524
EngineCore core.py L428 (step), L794 (add_request), L1294
Scheduler scheduler.py L329 (schedule), L1283 (update), L1649 (_update_request)
KVCacheManager kv_cache_manager.py L194 (get_computed_blocks), L236 (allocate_slots), L429 (free)
GPUModelRunner gpu_model_runner.py L1116 (_update_states), L1863 (_prepare_inputs), L2183 (_build_attention_metadata), L3668 (_model_forward), L3955 (execute_model), L4319 (sample_tokens)
Attention 层 attention.py L437
FlashAttention 后端 flash_attn.py L388 (MetadataBuilder), L667 (forward), L850 (do_kv_cache_update)
Sampler sampler.py L67 (forward), L238 (sample), L366 (apply_logits_processors)
OutputProcessor output_processor.py L576
请求数据结构 request.py RequestStatus L315

本站访问量

This site uses Just the Docs, a documentation theme for Jekyll.