Prefill/decode 分离#

通过分离 prefill 和 decode 阶段来部署 LLM,以提高资源利用率和成本优化。

警告

此功能需要 vLLM v1,这是默认引擎。对于使用 vLLM v0 的旧部署,请先升级到 v1。

Prefill/decode 分离将 prefill 阶段(处理输入提示)与 decode 阶段(生成 token)分开。这种分离提供了

  • 独立优化:您可以独立地使用不同的配置优化 prefill 和 decode。

  • 减少干扰:Prefill 操作会干扰 decode 操作,反之亦然,在不可预测的流量高峰期间会降低性能。分离消除了这种争用。

  • 独立扩展:您可以根据需求独立扩展每个阶段。

  • 成本优化:您可以为不同的工作负载使用不同的节点类型,从而利用异构集群。

vLLM 提供了几种用于分离服务的 KV 传输后端

  1. NIXLConnector:基于网络的 KV 缓存传输,使用 NVIDIA Inference Xfer Library (NIXL),支持 UCX、libfabric 和 EFA 等各种后端。设置简单,配置最少。

  2. LMCacheConnectorV1:高级缓存解决方案,支持各种存储后端,包括与 NIXL 集成。

何时使用 prefill/decode 分离#

当出现以下情况时,请考虑此模式

  • 您的工作负载模式多变,prefill 和 decode 对资源的需求不同。

  • 您希望通过为不同阶段使用不同的硬件来优化成本。

  • 您的应用程序需要高吞吐量,这可以从解耦 prefill 和 decode 中受益。

使用 NIXLConnector 进行部署#

NIXLConnector 在 prefill 和 decode 服务器之间提供基于网络的 KV 缓存传输,配置最少。

先决条件#

如果您使用 ray-project/ray-llm Docker 镜像,NIXL 已经安装。否则,请安装它

uv pip install nixl

NIXL wheel 捆绑了其支持的后端(UCX、libfabric、EFA 等)。这些共享二进制文件可能不是您硬件和网络堆栈的最新版本。如果您需要最新版本,请针对目标后端库从源代码构建 NIXL。有关详细信息,请参阅 NIXL 安装指南

基本部署#

以下示例显示了如何使用 NIXLConnector 进行部署

from ray.serve.llm import LLMConfig, build_pd_openai_app
import ray.serve as serve

# Configure prefill instance
prefill_config = LLMConfig(
    model_loading_config={
        "model_id": "meta-llama/Llama-3.1-8B-Instruct"
    },
    engine_kwargs={
        "kv_transfer_config": {
            "kv_connector": "NixlConnector",
            "kv_role": "kv_both",
        }
    }
)

# Configure decode instance
decode_config = LLMConfig(
    model_loading_config={
        "model_id": "meta-llama/Llama-3.1-8B-Instruct"
    },
    engine_kwargs={
        "kv_transfer_config": {
            "kv_connector": "NixlConnector",
            "kv_role": "kv_both",
        }
    }
)

pd_config = dict(
    prefill_config=prefill_config,
    decode_config=decode_config,
)

app = build_pd_openai_app(pd_config)
serve.run(app)

生产 YAML 配置#

对于生产部署,请使用 YAML 配置文件

# Example: Basic NIXLConnector configuration for prefill/decode disaggregation
# nixl_config.yaml

applications:
  - args:
      prefill_config:
        model_loading_config:
          model_id: meta-llama/Llama-3.1-8B-Instruct
        engine_kwargs:
          kv_transfer_config:
            kv_connector: NixlConnector
            kv_role: kv_producer
            engine_id: engine1
        deployment_config:
          autoscaling_config:
            min_replicas: 2
            max_replicas: 4
      
      decode_config:
        model_loading_config:
          model_id: meta-llama/Llama-3.1-8B-Instruct
        engine_kwargs:
          kv_transfer_config:
            kv_connector: NixlConnector
            kv_role: kv_consumer
            engine_id: engine2
        deployment_config:
          autoscaling_config:
            min_replicas: 6
            max_replicas: 10

    import_path: ray.serve.llm:build_pd_openai_app
    name: pd-disaggregation-nixl
    route_prefix: "/"

使用以下命令部署

serve deploy nixl_config.yaml

配置参数#

  • kv_connector:设置为 "NixlConnector" 以使用 NIXL。

  • kv_role:设置为 "kv_both",适用于 prefill 和 decode 实例。

使用 LMCacheConnectorV1 进行部署#

LMCacheConnectorV1 提供高级缓存,支持多种存储后端。

先决条件#

安装 LMCache

uv pip install lmcache

场景 1:LMCache 与 NIXL 后端#

此配置使用 LMCache 和基于 NIXL 的存储后端进行网络通信。

以下是 LMCache 与 NIXL 集成的 Ray Serve 配置示例

# Example: LMCacheConnectorV1 with NIXL backend configuration

applications:
  - args:
      prefill_config:
        model_loading_config:
          model_id: meta-llama/Llama-3.1-8B-Instruct
        engine_kwargs:
          kv_transfer_config:
            kv_connector: LMCacheConnectorV1
            kv_role: kv_producer
            kv_connector_extra_config:
              discard_partial_chunks: false
              lmcache_rpc_port: producer1
        deployment_config:
          autoscaling_config:
            min_replicas: 2
            max_replicas: 2
        runtime_env:
          env_vars:
            LMCACHE_CONFIG_FILE: lmcache_prefiller.yaml
            LMCACHE_USE_EXPERIMENTAL: "True"

      decode_config:
        model_loading_config:
          model_id: meta-llama/Llama-3.1-8B-Instruct
        engine_kwargs:
          kv_transfer_config:
            kv_connector: LMCacheConnectorV1
            kv_role: kv_consumer
            kv_connector_extra_config:
              discard_partial_chunks: false
              lmcache_rpc_port: consumer1
        deployment_config:
          autoscaling_config:
            min_replicas: 6
            max_replicas: 6
        runtime_env:
          env_vars:
            LMCACHE_CONFIG_FILE: lmcache_decoder.yaml
            LMCACHE_USE_EXPERIMENTAL: "True"

    import_path: ray.serve.llm:build_pd_openai_app
    name: pd-disaggregation-lmcache-nixl
    route_prefix: "/"

为 prefill 实例创建 LMCache 配置(lmcache_prefiller.yaml

local_cpu: False
max_local_cpu_size: 0
max_local_disk_size: 0
remote_serde: NULL

enable_nixl: True
nixl_role: "sender"
nixl_receiver_host: "localhost"
nixl_receiver_port: 55555
nixl_buffer_size: 1073741824 # 1GB
nixl_buffer_device: "cuda"
nixl_enable_gc: True

为 decode 实例创建 LMCache 配置(lmcache_decoder.yaml

local_cpu: False
max_local_cpu_size: 0
max_local_disk_size: 0
remote_serde: NULL

enable_nixl: True
nixl_role: "receiver"
nixl_receiver_host: "localhost"
nixl_receiver_port: 55555
nixl_buffer_size: 1073741824 # 1GB
nixl_buffer_device: "cuda"
nixl_enable_gc: True

注意

环境变量 LMCACHE_CONFIG_FILE 必须指向 Ray Serve 容器或工作程序环境中可访问的现有配置文件。确保这些配置文件已正确挂载或在您的部署环境中可用。

场景 2:LMCache 与 Mooncake 存储后端#

此配置使用 LMCache 和 Mooncake 存储,一个高性能的分布式存储系统。

以下是 LMCache 与 Mooncake 集成的 Ray Serve 配置示例

# Example: LMCacheConnectorV1 with Mooncake store configuration

applications:
  - args:
      prefill_config:
        model_loading_config:
          model_id: meta-llama/Llama-3.1-8B-Instruct
        engine_kwargs:
          kv_transfer_config: &kv_transfer_config
            kv_connector: LMCacheConnectorV1
            kv_role: kv_both
        deployment_config:
          autoscaling_config:
            min_replicas: 2
            max_replicas: 2
        runtime_env: &runtime_env
          env_vars:
            LMCACHE_CONFIG_FILE: lmcache_mooncake.yaml
            LMCACHE_USE_EXPERIMENTAL: "True"

      decode_config:
        model_loading_config:
          model_id: meta-llama/Llama-3.1-8B-Instruct
        engine_kwargs:
          kv_transfer_config: *kv_transfer_config
        deployment_config:
          autoscaling_config:
            min_replicas: 1
            max_replicas: 1
        runtime_env: *runtime_env

    import_path: ray.serve.llm:build_pd_openai_app
    name: pd-disaggregation-lmcache-mooncake
    route_prefix: "/"

为 Mooncake 创建 LMCache 配置(lmcache_mooncake.yaml

# LMCache configuration for Mooncake store backend
chunk_size: 256
local_device: "cpu"
remote_url: "mooncakestore://storage-server:49999/"
remote_serde: "naive"
pipelined_backend: false
local_cpu: false
max_local_cpu_size: 5
extra_config:
  local_hostname: "compute-node-001"
  metadata_server: "etcd://metadata-server:2379"
  protocol: "rdma"
  device_name: "rdma0"
  master_server_address: "storage-server:49999"
  global_segment_size: 3355443200  # 3.125 GB
  local_buffer_size: 1073741824    # 1 GB
  transfer_timeout: 1

警告

对于 Mooncake 部署

  • 确保 etcd 元数据服务器正在运行,并且可以通过指定地址访问。

  • 验证您是否已正确配置 RDMA 设备和存储服务器,并且它们是否可访问。

  • 在容器化部署中,挂载具有适当读取权限的配置文件(例如,chmod 644)。

  • 确保配置文件中引用的所有主机名和 IP 地址都可以从部署环境中解析。

配置参数#

  • kv_connector:设置为 "LMCacheConnectorV1"

  • kv_role:对于 prefill 设置为 "kv_producer",对于 decode 设置为 "kv_consumer"

  • kv_buffer_size:KV 缓存缓冲区的大小。

  • LMCACHE_CONFIG_FILE:指定配置文件路径的环境变量。

测试您的部署#

在使用 LMCacheConnectorV1 进行部署之前,请启动所需的服务

# Start etcd server if not already running
docker run -d --name etcd-server \
  -p 2379:2379 -p 2380:2380 \
  quay.io/coreos/etcd:latest \
  etcd --listen-client-urls http://0.0.0.0:2379 \
       --advertise-client-urls https://:2379

# For Mooncake backend, start the Mooncake master
# See https://docs.lmcache.ai/kv_cache/mooncake.html for details
mooncake_master --port 49999

使用聊天补全请求进行测试

curl -X POST "https://:8000/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Llama-3.1-8B-Instruct",
    "messages": [
      {"role": "user", "content": "Explain the benefits of prefill/decode disaggregation"}
    ],
    "max_tokens": 100,
    "temperature": 0.7
  }'

最佳实践#

  • 选择合适的后端:对于更简单的部署,请使用 NIXLConnector。当您需要高级缓存或多个存储后端时,请使用 LMCacheConnectorV1。

  • 监控 KV 传输开销:确保分离的好处大于网络传输成本。监控延迟和吞吐量。

  • 独立扩展:通过单独监控每个阶段的资源利用率来利用独立扩展的优势。

  • 使用实际工作负载进行测试:在生产部署之前,使用您的实际流量模式验证性能改进。

  • 确保网络连接:对于 NIXLConnector,请验证 prefill 和 decode 实例是否可以通过网络进行通信。

  • 保护 etcd 访问:对于 LMCacheConnectorV1,请确保您的 etcd 服务器得到妥善保护,并且仅供授权服务访问。

故障排除#

Prefill 和 decode 实例无法通信#

  • 验证实例之间的网络连接,并确保有足够的带宽用于 KV 传输。

  • 检查您的网络是否支持您正在使用的后端(例如,用于高性能部署的 RDMA)。

  • 对于 NIXLConnector,请确保在所有节点上都正确安装了 NIXL。

  • 验证防火墙规则和安全组是否允许 prefill 和 decode 实例之间的通信。

找不到 LMCache 配置#

  • 验证 LMCACHE_CONFIG_FILE 环境变量是否指向一个现有文件。

  • 确保 Ray Serve 工作程序环境可以访问该配置文件。

  • 检查文件是否具有适当的读取权限。

另请参阅#