Files
2026-07-13 12:24:33 +08:00

276 lines
9.0 KiB
ReStructuredText

GDS Backend
==================
.. warning::
This page documents the behavior of LMCache's in-process mode (deprecated). Please consider using :doc:`LMCache MP mode </mp/index>` for better feature support and performance. For the MP mode equivalent of this page, see :doc:`/mp/l2_storage/index`.
.. _gds-overview:
Overview
--------
This backend will work with any file system, whether local, remote, and remote
with GDS-based optimizations. Remote file systems allow for multiple LMCache
instances to share data seamlessly. The GDS (GPU-Direct Storage) optimizations
are used for zero-copy I/O from GPU memory to storage systems. Supports both
NVIDIA cuFile and AMD hipFile for GPU-direct storage.
Ways to configure LMCache GDS Backend
-----------------------------------------
**1. Environment Variables:**
.. code-block:: bash
# 256 Tokens per KV Chunk
export LMCACHE_CHUNK_SIZE=256
# Path to store files
export LMCACHE_GDS_PATH="/mnt/gds/cache"
# GDS Buffer Size in MiB
export LMCACHE_GDS_BUFFER_SIZE="8192"
# Disabling CPU RAM offload is sometimes recommended as the
# CPU can get in the way of GPUDirect operations
export LMCACHE_LOCAL_CPU=False
**2. Configuration File**:
Passed in through ``LMCACHE_CONFIG_FILE=your-lmcache-config.yaml``
Example ``config.yaml``:
.. code-block:: yaml
# 256 Tokens per KV Chunk
chunk_size: 256
# Disable local CPU
local_cpu: false
# Path to file system, local, remote or GDS-enabled mount
gds_path: "/mnt/gds/cache"
# GDS Buffer Size in MiB
gds_buffer_size: 8192
Multi-Path (Multi-Device) Support
---------------------------------
When a system has multiple NVMe drives, you can distribute GDS I/O across them
by specifying a comma-separated list of paths in ``gds_path``. The
``gds_path_sharding`` option controls how each GPU worker selects its path.
Currently only ``"by_gpu"`` is supported (the default), which selects a path
based on the device index (``device_id % num_paths``), so traffic is spread
evenly across the drives without any manual pinning.
**Why this helps:** a single PCIe Gen 4 x4 NVMe tops out at ~7 GB/s. With four
drives the aggregate bandwidth can reach ~28 GB/s, matching what multi-GPU
systems need for KV cache eviction and prefetch.
**Environment variables:**
.. code-block:: bash
export LMCACHE_GDS_PATH="/mnt/nvme0/cache,/mnt/nvme1/cache,/mnt/nvme2/cache,/mnt/nvme3/cache"
export LMCACHE_GDS_PATH_SHARDING="by_gpu"
**YAML config:**
.. code-block:: yaml
gds_path: "/mnt/nvme0/cache,/mnt/nvme1/cache,/mnt/nvme2/cache,/mnt/nvme3/cache"
gds_path_sharding: "by_gpu"
With the above configuration on a 4-GPU node:
- ``cuda:0`` writes to ``/mnt/nvme0/cache``
- ``cuda:1`` writes to ``/mnt/nvme1/cache``
- ``cuda:2`` writes to ``/mnt/nvme2/cache``
- ``cuda:3`` writes to ``/mnt/nvme3/cache``
If there are more GPUs than paths, the assignment wraps around (e.g. ``cuda:4``
maps back to ``/mnt/nvme0/cache``). A single path (no commas) works exactly as
before.
All directories are created automatically at startup. Every path in the list
must reside on a filesystem that the rest of the GDS configuration expects
(e.g., all paths on GDS-capable mounts when using cuFile).
**Read behavior:** on startup the backend scans **all** configured paths for
previously-stored KV cache entries, regardless of GPU affinity. This means a
``cuda:0`` worker whose write affinity is ``/mnt/nvme0/cache`` will still
discover entries that were written to ``/mnt/nvme1/cache`` by ``cuda:1`` in a
prior run. Writes, however, always go to the single affinity-selected path.
.. code-block:: text
Startup scan (read): iterate ALL gds_paths → populate hot_cache
Runtime writes: only the affinity path (device_id % num_paths)
Runtime reads: look up hot_cache first; on miss, check ALL
gds_paths on disk → load from whichever path
the entry lives on
GDS Buffer Size Explanation
---------------------------
The backend currently pre-registers buffer space to speed up GDS operations. This buffer space
is registered in VRAM so options like ``--gpu-memory-utilization`` from ``vllm`` should be considered
when setting it. For example, a good rule of thumb for H100 which generally has 80GiBs of VRAM would
be to start with 8GiB and set ``--gpu-memory-utilization 0.85`` and depending on your workflow fine-tune
it from there.
Using AMD hipFile
-----------------
.. note::
hipFile is alpha software and has been tested on limited hardware.
For full installation details, see the
`hipFile install guide <https://github.com/ROCm/rocm-systems/blob/develop/projects/hipfile/INSTALL.md>`__.
**Prerequisites:**
- **ROCm >= 7.2** with ``amdgpu-dkms >= 30.20.1``
(see the `ROCm quick start installation guide <https://rocm.docs.amd.com/projects/install-on-linux/en/latest/install/quick-start.html>`__)
- **Supported storage:** local NVMe drives only
- **Supported filesystems:** ext4 (mounted with ``data=ordered``) and xfs
- **Kernel:** ``CONFIG_PCI_P2PDMA`` must be enabled
**Quick install (Ubuntu 24.04):**
.. code-block:: bash
sudo apt install libmount-dev wget
# Install nightly hipFile packages
wget https://github.com/ROCm/hipFile/releases/download/nightly/hipfile_0.2.0.70200-nightly.9999.24.04_amd64.deb
wget https://github.com/ROCm/hipFile/releases/download/nightly/hipfile-dev_0.2.0.70200-nightly.9999.24.04_amd64.deb
sudo dpkg -i hipfile-dev_0.2.0.70200-nightly.9999.24.04_amd64.deb hipfile_0.2.0.70200-nightly.9999.24.04_amd64.deb
You can verify that the HIP libraries and kernel support AIS (AMD Infinity Storage) by running:
.. code-block:: bash
/opt/rocm/bin/ais-check
Successful output will show ``True`` for ``Kernel P2PDMA support``, ``HIP runtime``, and ``amdgpu``.
**LMCache configuration:**
To use AMD hipFile instead of NVIDIA cuFile, set the GDS backend:
**Environment Variables:**
.. code-block:: bash
export LMCACHE_GDS_BACKEND=hipfile
**Configuration File:**
.. code-block:: yaml
gds_backend: "hipfile"
Note: The ``gds_buffer_size`` configuration is used for both cuFile and hipFile buffers.
Setup Example
-------------
.. _gds-prerequisites:
**Prerequisites:**
- A Machine with at least one GPU. You can adjust the max model length of your vllm instance depending on your GPU memory.
- A mounted file system. A file system supportings GDS will work best.
- vllm and lmcache installed (:doc:`Installation Guide <../../getting_started/installation>`)
- Hugging Face access to ``meta-llama/Llama-3.1-8B-Instruct``
.. code-block:: bash
export HF_TOKEN=your_hugging_face_token
**Step 1. Create cache directory under your file system mount:**
To find all the types of file systems supporting GDS in your system, use `gdscheck` from NVIDIA:
.. code-block:: bash
sudo /usr/local/cuda-*/gds/tools/gdscheck -p
Check with your storage vendor on how to mount the remote file system.
(For example, if you want to use a GDS-enabled NFS driver, try the modified [NFS
stack](https://vastnfs.vastdata.com/), which is an open source driver that
works with any standard [NFS
RDMA](https://datatracker.ietf.org/doc/html/rfc5532) server. More
vendor-specific instructions will be added here in the future).
Create a directory under the file systew mount (the name here is arbitrary):
.. code-block:: bash
mkdir /mnt/gds/cache
**Step 2. Start a vLLM server with file backend enabled:**
Create a an lmcache configuration file called: ``gds-backend.yaml``
.. code-block:: yaml
local_cpu: false
chunk_size: 256
gds_path: "/mnt/gds/cache"
gds_buffer_size: 8192
If you don't want to use a config file, uncomment the first three environment variables
and then comment out the ``LMCACHE_CONFIG_FILE`` below:
.. code-block:: bash
# LMCACHE_LOCAL_CPU=False \
# LMCACHE_CHUNK_SIZE=256 \
# LMCACHE_GDS_PATH="/mnt/gds/cache" \
# LMCACHE_GDS_BUFFER_SIZE=8192 \
LMCACHE_CONFIG_FILE="gds-backend.yaml" \
vllm serve \
meta-llama/Llama-3.1-8B-Instruct \
--max-model-len 65536 \
--kv-transfer-config \
'{"kv_connector":"LMCacheConnectorV1", "kv_role":"kv_both"}'
POSIX fallback
--------------
In some cases, libcufile implements its own internal POSIX fallback without `GdsBackend` being aware.
In others, an error such as `RuntimeError: cuFileHandleRegister failed (cuFile err=5030, cuda_err=0)` may be throwned.
Thus, backend can be configured to fallback to its own POSIX implementation when the usage of the GDS APIs is not successful.
To force `GdsBackend` not use GDS APIs for any reason, you can override its behavior via configuration:
.. code-block:: yaml
use_gds: false
Or via environment variable:
.. code-block:: bash
LMCACHE_USE_GDS=False
The ``gds_backend`` field (default: ``cufile``) selects which GDS library to use. Supported
backends are ``cufile`` (NVIDIA cuFile) and ``hipfile`` (AMD hipFile):
.. code-block:: yaml
use_gds: true
gds_backend: "cufile" # or "hipfile"
Note that under this mode it would still use CUDA APIs to map and do operations the pre-registered GPU memory.