Nixl#

概述#

NIXL(NVIDIA 推理传输库)是一个高性能库,旨在加速 AI 推理框架中的点对点通信。它通过模块化插件架构提供对各种类型内存(CPU 和 GPU)和存储的抽象,使得推理管道中不同组件之间的数据传输和协调更加高效。

LMCache 支持将 NIXL 用作存储后端,允许将显存或 CPU 内存保存到存储中。

前提条件#

  • LMCache: 使用 pip install lmcache 安装

  • NIXL: 从 NIXL GitHub repository 安装

  • 模型访问:有效的 Hugging Face 令牌 (HF_TOKEN) 用于 Llama 3.1 8B Instruct

配置 LMCache NIXL 卸载的方法#

配置文件

通过 LMCACHE_CONFIG_FILE=lmcache-config.yaml 传入

示例 lmcache-config.yaml 用于 POSIX 后端:

chunk_size: 256
nixl_buffer_device: cpu
local_cpu_use_hugepages: true  # optional, requires pre-allocated hugepages
extra_config:
  enable_nixl_storage: true
  nixl_backend: POSIX
  nixl_pool_size: 64
  nixl_path: /mnt/nixl/cache/
  use_direct_io: true

关键设置:

  • nixl_buffer_size:NIXL 传输的缓冲区大小。仅限 GPU 模式nixl_buffer_device: cuda)。将其设置为 nixl_buffer_device: cpu 是配置错误,将被拒绝——在 CPU 模式下,NIXL 共享 LocalCPUBackend 的固定池,该池的大小由 max_local_cpu_size 决定。

  • max_local_cpu_size: LocalCPUBackend 的固定池大小(以 GiB 为单位)。在 CPU 模式下,该池与 NIXL 共享,必须能够容纳热缓存和并发的 NIXL I/O。设置为 nixl_buffer_device: cpu 时必须大于 0。默认值:5.0

  • nixl_pool_size: 初始化时为 nixl 后端打开的描述符数量。设置为 0 以启用动态模式。

  • nixl_path: 存储文件将保存的目录(或目录列表)(例如 /mnt/nixl/)。对于将数据存储到文件的 NIXL 后端是必需的。当使用带有 path_sharding 的路径列表时,路径将根据分片策略进行选择。

  • nixl_buffer_device: 指定 NIXL 管理的内存应位于何处。对于 GDSGDS_MTOBJ 后端,支持 cpucuda;对于 POSIXHF3FSAZURE_BLOBDOCA_MEMOS,必须为 cpu。在 CPU 模式下,NIXL 共享 LocalCPUBackend 的固定缓冲区;当 nixl_buffer_device: cpu 时,LocalCPUBackend 始终会被创建,无论 local_cpu 设置如何。local_cpu: false 仍然会抑制热缓存提升——后端仅作为暂存缓冲区,镜像 local_disk 已经如何使用 LocalCPUBackend

  • nixl_backend: 配置用于存储的 nixl 后端。

  • nixl_path_sharding: 当提供多个路径时选择路径的策略。目前仅支持“by_gpu”,该策略根据 GPU 设备 ID 选择路径。

  • local_cpu_use_hugepages: 是否为 LocalCPUBackend 的固定池使用 Linux 大页(2 MiB)(NIXL 在 CPU 模式下共享)。需要预分配的大页(sysctl vm.nr_hugepages)。默认值:false已弃用的别名: extra_config.nixl_use_hugepages — 接受时会发出警告并复制到此字段;将在未来的版本中移除。

备注

在 CPU 模式下,共享分页分配器每个对象消耗一个完整的页面。使用 save_unfull_chunk: true(仅在静态模式下有效——动态模式会拒绝它;请参见“动态模式”→“限制”),部分块仍然占用一个完整的页面,因此有效容量与活动序列中未满最后块的比例成正比地下降。

备注

enable_p2p: truenixl_buffer_device: cpu 一起被拒绝。这个组合在结构上是支持的——两个后端共享 LocalCPUBackend 的固定池,各自运行自己的 NIXL 代理,并且分配通过 LocalCPUBackend.allocate() 路由——但尚未进行端到端的测试,也没有 CI 覆盖。在使用 NIXL CPU 共享池时,请改用 nixl_buffer_device: cudaenable_p2p: true,或者在运行时禁用 enable_p2p

  • nixl_presence_cache: whether to keep an in-DRAM presence cache of keys known to exist, so repeated existence checks for the same key are answered locally instead of via a NIXL query_memory call. Applies to the dynamic backend (nixl_pool_size: 0). Default: false.

  • nixl_presence_cache_only: when true, the dynamic NIXL backend treats the local presence cache (and in-progress put set) as authoritative for existence checks. If a key is not known locally, lookup reports a miss without issuing a NIXL query_memory check. This requires nixl_presence_cache: true and can intentionally produce false negatives for objects that exist in the underlying storage but are absent from local presence metadata — giving "DRAM-only metadata" semantics where a process restart always yields a logically empty cache. Default: false.

    备注

    This is a lookup/existence-check mode, not a "never touch the underlying storage" policy. It gates contains / batched_contains (and the async variant); direct retrieval still reads from the underlying storage. In normal operation a retrieval is only issued for a key that lookup already reported as present, so locally-unknown keys are not fetched. The option is only consulted by the dynamic backend (nixl_pool_size: 0); it is accepted but unused for static configurations.

备注

支持的后端包括:["GDS", "GDS_MT", "POSIX", "HF3FS", "OBJ", "AZURE_BLOB", "DOCA_MEMOS"].

后端特定参数应通过 extra_config.nixl_backend_params 提供。有关具体信息,请参阅 NIXL 文档。

示例 lmcache-config.yaml 用于支持多路径的 POSIX 后端:

chunk_size: 256
nixl_buffer_size: 1073741824 # 1GB
nixl_buffer_device: cpu
extra_config:
  enable_nixl_storage: true
  nixl_backend: POSIX
  nixl_pool_size: 64
  nixl_path:
    - /mnt/nixl/cache0/
    - /mnt/nixl/cache1/
    - /mnt/nixl/cache2/
  nixl_path_sharding: by_gpu
  use_direct_io: True

示例 lmcache-config.yaml 用于使用 S3 API 的 OBJ 后端:

chunk_size: 256
nixl_buffer_device: cpu
max_local_cpu_size: 1  # GiB
extra_config:
  enable_nixl_storage: true
  nixl_backend: OBJ
  nixl_pool_size: 64
  nixl_path: /mnt/nixl/cache/
  nixl_backend_params:
    access_key: <your_access_key>
    secret_key: <your_secret_key>
    bucket: <your_bucket>
    region: <your_region>

示例 lmcache-config.yaml 用于使用 liburing 的 POSIX 后端:

备注

使用带有 liburing 支持的 POSIX 后端需要将 NIXL 构建为支持 liburing。

chunk_size: 256
nixl_buffer_device: cpu
max_local_cpu_size: 1  # GiB
extra_config:
  enable_nixl_storage: true
  nixl_backend: POSIX
  nixl_pool_size: 64
  nixl_path: /mnt/nixl/cache/
  use_direct_io: True
  nixl_backend_params:
    use_uring: "true"

示例 lmcache-config.yaml 用于 AZURE_BLOB 后端,通过 Azure Blob Storage API 进行卸载:

chunk_size: 256
nixl_buffer_device: cpu
max_local_cpu_size: 1  # GiB
extra_config:
  enable_nixl_storage: true
  nixl_backend: AZURE_BLOB
  nixl_pool_size: 64
  nixl_path: /mnt/nixl/cache/
  nixl_backend_params:
    account_url: https://<your_azure_storage_account_name>.blob.core.windows.net
    container_name: <your_container_name>

每个工作节点的端点分配#

当使用 OBJ 后端与多个张量并行 (TP) 工作节点时,您可以通过提供一个端点列表来在多个对象存储端点之间分配工作节点,方法是使用 nixl_endpoint_list。每个工作节点根据其 local_worker_id(其主机内的工作节点 ID)以轮询方式选择一个端点。

extra_config:
  enable_nixl_storage: true
  nixl_backend: OBJ
  nixl_pool_size: 64
  nixl_path: /mnt/nixl/cache/
  nixl_endpoint_list:
    - https://node-0.object-storage:9021
    - https://node-1.object-storage:9021
    - https://node-2.object-storage:9021
  nixl_backend_params:
    access_key: <your_access_key>
    secret_key: <your_secret_key>
    bucket: <your_bucket>
    region: <your_region>

备注

当设置 nixl_endpoint_list 时,nixl_backend_params 中的任何 endpoint_override 值将被忽略(会记录警告)。

nixl_endpoint_list 仅对 OBJ 后端有效;对于所有其他后端(包括 DOCA_MEMOS、AZURE_BLOB 和文件后端)将被忽略。

动态模式#

Nixl 存储后端还支持动态模式,该模式按需创建 nixl 存储描述符,而不是在初始化时创建。

为了使用动态模式,extra_config.nixl_pool_size 应设置为 0。

限制#

  • 动态模式支持对象后端(“OBJ”,“AZURE_BLOB”,“DOCA_MEMOS”)和文件后端(“POSIX”,“GDS”,“GDS_MT”,“HF3FS”)。

  • save_unfull_chunk 必须设置为 False。

示例 lmcache-config.yaml 用于动态模式的 OBJ 后端:

chunk_size: 256
local_cpu: False
save_unfull_chunk: False
enable_async_loading: False # set to True to test async loading
nixl_buffer_device: cpu
max_local_cpu_size: 3  # GiB
extra_config:
  enable_nixl_storage: true
  nixl_backend: OBJ
  nixl_pool_size: 0
  nixl_presence_cache: False
  nixl_async_put: False
  nixl_backend_params:
    access_key: <your_access_key>
    secret_key: <your_secret_key>
    bucket: <your_bucket>
    region: <your_region>
    endpoint_override: https://url-to-object-storage
    ca_bundle: path to self-signed certificate # remove this line if not using self-signed certificate

示例 lmcache-config.yaml 用于动态模式的 AZURE_BLOB 后端:

chunk_size: 256
local_cpu: False
save_unfull_chunk: False
enable_async_loading: False # set to True to test async loading
nixl_buffer_device: cpu
max_local_cpu_size: 3  # GiB
extra_config:
  enable_nixl_storage: true
  nixl_backend: AZURE_BLOB
  nixl_pool_size: 0
  nixl_presence_cache: False
  nixl_async_put: False
  nixl_backend_params:
    account_url: https://<your_azure_storage_account_name>.blob.core.windows.net
    container_name: <your_container_name>

DOCA_MEMOS 后端 (NVIDIA CMX)#

DOCA_MEMOS 将 KV Cache 存储在 NVIDIA CMX(上下文内存存储)上,这是一个通过 NIXL 访问的 BlueField-4 上下文内存层。它是一种对象风格的后端(类似于 OBJ),支持静态模式(nixl_pool_size > 0)和动态模式(nixl_pool_size = 0)。nixl_buffer_device 必须为 cpunixl_endpoint_list 不支持 DOCA_MEMOS。

对象名称是 128 位小写十六进制字符串:NIXL DOCA_MEMOS 插件将对象名称作为字符串传递,并在设备端进行十六进制解码,因此每个名称恰好是 32 个十六进制字符。在动态模式下,此名称是缓存键的截断 SHA-256,因此名称是不透明的(它们不携带任何模型/块调试信息),并且唯一性在 128 位上是概率性的。

chunk_size: 256
nixl_buffer_device: cpu
max_local_cpu_size: 1  # GiB
extra_config:
  enable_nixl_storage: true
  nixl_backend: DOCA_MEMOS
  nixl_pool_size: 64
  nixl_backend_params:
    # refer to NIXL DOCA_MEMOS plugin docs for connection params