跳转至

重计算CPU卸载指南

概述

RecomputeCPUOffloadConnector 用于保存被解码端重计算调度器抢占的请求的KV缓存。当HBM KV块不足时,RecomputeScheduler 可能会抢占正在运行的解码请求。如果没有此连接器,请求将回退到原始重计算路径,并可能被发送回预填充节点重新执行预填充。启用重计算CPU卸载后,已计算的KV块会在HBM块被重用前从HBM复制到CPU DRAM,并在请求再次被调度时复制回HBM。

此功能专为在线P/D分离部署场景设计,其中解码节点针对解码吞吐量进行了调优,无法在抢占后高效地重计算长预填充。该功能为可选启用,并优先保证正确性。

在典型的解码部署中,max_num_batched_tokens 通常设置为 max_num_seqs * (1 + num_spec_tokens) 左右,使得解码节点主要调度每个请求的一个新token(如果启用了MTP,则加上推测token)。这对解码来说是高效的,但对于抢占后重计算长提示词来说则太小。重计算CPU卸载避免了在KV状态可以本地保存时将此类请求发送回完整的提示词重计算路径。

关键概念

  • 重计算抢占:当解码端HBM KV缓存耗尽时,RecomputeScheduler 可以抢占正在运行的请求,并在之后恢复它。
  • CPU DRAM保存RecomputeCPUOffloadConnector 将被抢占请求的已计算KV块存储在CPU内存中。
  • H2D恢复:当被抢占的请求再次被调度时,连接器在模型前向传播前恢复已保存的KV块。
  • 回退行为:如果未配置连接器、未启用重计算调度器或CPU卸载容量不足,vLLM 将回退到原始重计算行为。
  • MultiConnector集成:在P/D分离部署中,使用 MultiConnector 将P/D连接器(如 MooncakeConnectorV1)与解码节点上的 RecomputeCPUOffloadConnector 结合使用。

配置参数

RecomputeCPUOffloadConnector 通过 kv-transfer-config 进行配置。

参数 描述
kv_connector 必须设置为 RecomputeCPUOffloadConnector
kv_role 在解码节点上设置为 kv_consumer
cpu_bytes_to_use_per_rank 可选且推荐。每个rank/卡用于重计算卸载的CPU内存预算(字节)。如果设置,它将覆盖 cpu_bytes_to_use / world_size
cpu_bytes_to_use 可选。此vLLM实例的总CPU内存预算(字节)。连接器将其除以 world_size 以获得每个rank的预算。这不如 cpu_bytes_to_use_per_rank 直接,并且在DP部署中更容易配置错误。默认总值为8 GiB。
enable_offload_prefix_caching 可选。为具有相同前缀缓存哈希的完整哈希块启用CPU块共享。默认值为 false;除非明确测试前缀共享,否则保持禁用状态。

当您希望每个rank/卡使用相同的卸载容量时,请优先使用 cpu_bytes_to_use_per_rank。例如,将 cpu_bytes_to_use_per_rank 设置为 17179869184 以分配每个rank/卡16 GiB。

如果使用 cpu_bytes_to_use,请记住它会被 world_size 除。在典型的P/D解码部署中,这意味着该值会被活跃的解码DP大小除。例如,启动DP2TP8解码服务时,将 cpu_bytes_to_use 设置为16 GiB会给每个DP rank的卡大约8 GiB的重计算卸载空间。为避免歧义,新部署请使用 cpu_bytes_to_use_per_rank

scheduler_config.recompute_scheduler_enable must also be enabled in additional-config on P/D-disaggregated Decode nodes:

--additional-config '{"scheduler_config":{"recompute_scheduler_enable":true}}'
`scheduler_config.recompute_scheduler_enable` is only valid in P/D-disaggregated mode
(`kv_role` is `kv_producer` or `kv_consumer`). Do not enable it in PD-mixed
mode (`kv_role` is `kv_both`).

Docker共享内存

重计算CPU卸载会为卸载的KV块分配固定的CPU张量。在Docker中运行时,请确保容器的共享内存足够大。如果 --shm-size 太小,每个卡较大的卸载预算(例如每卡16 GiB)可能无法分配CPU张量,并可能导致服务在启动时OOM或挂起。

对于具有较大重计算卸载预算的典型A3部署,请在启动容器时设置 --shm-size=1024g。以下代码片段遵循DeepSeek-V4-Flash教程中使用的Docker风格:

export IMAGE=quay.io/ascend/vllm-ascend:|vllm_ascend_version|-a3
docker run --rm \
    --name vllm-ascend \
    --shm-size=1024g \
    --net=host \
    --device /dev/davinci0 \
    --device /dev/davinci1 \
    --device /dev/davinci2 \
    --device /dev/davinci3 \
    --device /dev/davinci4 \
    --device /dev/davinci5 \
    --device /dev/davinci6 \
    --device /dev/davinci7 \
    --device /dev/davinci8 \
    --device /dev/davinci9 \
    --device /dev/davinci10 \
    --device /dev/davinci11 \
    --device /dev/davinci12 \
    --device /dev/davinci13 \
    --device /dev/davinci14 \
    --device /dev/davinci15 \
    --device /dev/davinci_manager \
    --device /dev/devmm_svm \
    --device /dev/hisi_hdc \
    -v /usr/local/dcmi:/usr/local/dcmi \
    -v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
    -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
    -v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
    -v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
    -v /etc/ascend_install.info:/etc/ascend_install.info \
    -v /etc/hccn.conf:/etc/hccn.conf \
    -it $IMAGE bash

与P/D分离部署一起使用

在解码节点上,配置 MultiConnector,同时包含P/D连接器和 RecomputeCPUOffloadConnector。P/D连接器处理从预填充到解码的KV传输,而 RecomputeCPUOffloadConnector 处理解码端的抢占保存和恢复。

以下示例使用 MooncakeConnectorV1 进行P/D KV传输。

python3 -m vllm.entrypoints.openai.api_server \
    --model /path/to/model \
    --port 8200 \
    --trust-remote-code \
    --enforce-eager \
    --tensor-parallel-size 1 \
    --data-parallel-size 1 \
    --max-model-len 32768 \
    --block-size 128 \
    --max-num-batched-tokens 4096 \
    --additional-config '{"scheduler_config":{"recompute_scheduler_enable":true}}' \
    --kv-transfer-config \
    '{
      "kv_connector": "MultiConnector",
      "kv_role": "kv_consumer",
      "kv_connector_extra_config": {
        "connectors": [
          {
            "kv_connector": "MooncakeConnectorV1",
            "kv_role": "kv_consumer",
            "kv_port": "28000",
            "kv_connector_extra_config": {
              "prefill": {
                "dp_size": 1,
                "tp_size": 1
              },
              "decode": {
                "dp_size": 1,
                "tp_size": 1
              }
            }
          },
          {
            "kv_connector": "RecomputeCPUOffloadConnector",
            "kv_role": "kv_consumer",
            "kv_connector_extra_config": {
              "cpu_bytes_to_use_per_rank": 17179869184,
            }
          }
        ]
      }
    }'

对于预填充节点,保持正常的P/D连接器配置,例如将 MooncakeConnectorV1 设置为 kv_rolekv_producer

当P/D连接器也需要 kv_load_failure_policy 时,请在顶层 MultiConnectorkv-transfer-config 中配置它,而不是在子连接器内部。

独立连接器示例

RecomputeCPUOffloadConnector 必须与 vLLM-Ascend 的 RecomputeScheduler 一起使用。由于 RecomputeScheduler 仅在P/D分离部署的解码节点上受支持,因此重计算CPU卸载目前也仅适用于P/D分离部署的解码节点。

以下独立的连接器配置仅作为在P/D分离的Decode节点上验证重计算-卸载路径的最小配置片段。它并非PD混合部署模式。在PD混合或普通非P/D部署中,请勿启用重计算CPU卸载;引擎将使用正常的vLLM重计算行为。

from vllm.config import KVTransferConfig

kv_transfer_config = KVTransferConfig(
    kv_connector="RecomputeCPUOffloadConnector",
    kv_role="kv_consumer",
    kv_connector_extra_config={
        "cpu_bytes_to_use_per_rank": 17179869184,
        "enable_offload_prefix_caching": False,
    },
)

对于在线服务:

vllm serve /path/to/model \
    --additional-config '{"scheduler_config":{"recompute_scheduler_enable":true}}' \
    --kv-transfer-config '{
        "kv_connector": "RecomputeCPUOffloadConnector",
        "kv_role": "kv_consumer",
        "kv_connector_extra_config": {
            "cpu_bytes_to_use_per_rank": 17179869184,
            "enable_offload_prefix_caching": false
        }
    }'

工作原理

  1. RecomputeScheduler无法分配足够的HBM KV块时,它会选择一个Decode端正在运行的请求进行抢占。
  2. 在请求的HBM块被重用之前,调度器调用连接器的抢占钩子。如果CPU块足够,连接器记录HBM块到CPU块的映射。
  3. 模型运行器在更新工作器状态之前调用handle_preemptions()。工作器将选定的KV块从HBM复制到固定的CPU张量。
  4. 在所有工作器报告存储完成后,被抢占的请求变为可恢复状态。
  5. 当请求再次被调度时,连接器报告可以从CPU内存恢复的token数量。
  6. 调度器分配新的HBM块,连接器构建CPU块到HBM块的重载映射。
  7. 在模型前向传播之前,工作器将恢复的KV块复制回HBM。前向传播从恢复的KV状态继续执行。

滑动窗口与MTP支持

滑动窗口模型可能包含注意力窗口外token的空块ID逻辑块表。连接器保留逻辑块位置而非压缩非零块ID,因此像[0, 0, 20, 21]这样的块表在CPU端保持为[0, 0, cpu_20, cpu_21]的对齐形式。仅传输非零块。

启用MTP或推测解码时,调度器可能分配预读块。重载路径将H2D范围裁剪为实际分配给恢复请求的GPU块表。

注意事项与限制

  • This feature requires the vLLM V1 engine and the vLLM-Ascend recompute scheduler.
  • The feature is only intended for Decode nodes in P/D disaggregation. It is not supported in PD-mixed or normal non-P/D deployments.
  • Do not enable scheduler_config.recompute_scheduler_enable in PD-mixed deployments. Without P/D-disaggregated Decode-side RecomputeScheduler, recompute CPU offload is not active and vLLM follows the normal recompute path.
  • When running in Docker with a large per-rank offload budget, reserve enough shared memory. For typical A3 deployments with 16 GiB per-card offload, use --shm-size=1024g.
  • enable_offload_prefix_caching is experimental and disabled by default.
  • Current D2H and H2D transfers use basic torch copy operations. They are correctness-oriented and not yet optimized for transfer throughput.
  • Qwen3.5 with async scheduling is not fully supported yet. Disable async scheduling when using recompute CPU offload with Qwen3.5 models.
  • If CPU memory capacity is insufficient, the connector skips offload for that request and the scheduler falls back to the original recompute behavior.

常见问题

我应该配置多少CPU内存?

从能够容纳预期被抢占请求块数量的预算开始。优先使用cpu_bytes_to_use_per_rank,因为它直接控制每个rank/卡的卸载预算。例如,cpu_bytes_to_use_per_rank=17179869184为每个rank/卡提供16 GiB空间。

cpu_bytes_to_use除以world_size。在DP2TP8的Decode服务中,设置cpu_bytes_to_use=17179869184为每个DP rank的卡提供约8 GiB的卸载空间。如果日志显示CPU缓存空闲块不足,请增加预算。

如何知道卸载路径是否激活?

查找类似以下日志:

Recompute preemption offload enabled for request ...
Created recompute offload state for request ...
Prepared recompute offload H2D load for request ...

如果无法准备卸载,日志可能显示CPU缓存空闲块不足,请求将回退到原始的重计算路径。

这与KV缓存CPU卸载相同吗?

不。KV Cache CPU Offload是针对非活跃KV缓存块的前缀缓存卸载路径。RecomputeCPUOffloadConnector专门用于保存被Decode端重计算调度器抢占的请求的KV块。

参考

有关设计背景和实现细节,请参见 #10820: 重计算CPU卸载连接器