For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.nvidia.com/dynamo/llms.txt. For full content including API reference and SDK examples, see https://docs.nvidia.com/dynamo/llms-full.txt.
Использование HiCache
В этом руководстве описано, как запускать Hierarchical Cache (HiCache) SGLang с Dynamo и как KV router Dynamo интегрируется с HiCache для tier-aware выбора worker'ов, когда worker'ы разделяют внешний pool, такой как Mooncake.
Обзор
SGLang HiCache расширяет RadixAttention многоуровневым KV cache, который прозрачно перемещает pages между GPU HBM, host memory и необязательным external storage backend, например Mooncake. Полное описание самого HiCache — reference флагов, storage backends, memory layouts, prefetch policies — см. в документации SGLang:
Что Dynamo добавляет поверх HiCache:
- Tier-aware routing. KV router отслеживает, на каком уровне cache находится каждый block (GPU / Host / External), и использует это при оценке candidate workers, а не только device overlap.
- Shared-pool awareness. Когда настроен external backend вроде Mooncake, router запрашивает shared pool параллельно со своим indexer'ом, чтобы можно было снижать стоимость prefill для блоков, которые может получить любой worker, а не только блоков, которые есть локально у кандидата.
Если вы запускаете одного worker'а с HiCache и без shared pool, никакая конфигурация со стороны Dynamo не требуется — worker по-прежнему отправляет KV events в router как обычно.
Запуск SGLang с HiCache
Запустите worker с включенным HiCache:
python -m dynamo.sglang \
--model-path Qwen/Qwen3-0.6B \
--page-size 64 \
--enable-hierarchical-cache \
--hicache-ratio 2 \
--hicache-write-policy write_through \
--hicache-storage-backend nixl \
--skip-tokenizer-init
Затем запустите frontend:
python -m dynamo.frontend --http-port 8000
Флаги HiCache (--enable-hierarchical-cache, --hicache-ratio, --hicache-write-policy, --hicache-storage-backend, --hicache-mem-layout и т. д.) являются нативными для SGLang — Dynamo передает их без изменений. Полный reference флагов и рекомендации по настройке см. в документе SGLang's best-practices.
Tier-aware маршрутизация общего KV cache
Когда вы масштабируете систему до нескольких worker'ов SGLang, которые разделяют внешний pool, например Mooncake, router Dynamo можно сделать tier-aware. Он отслеживает размещение по уровням по событиям worker'ов и напрямую опрашивает shared pool, чтобы блоки, закэшированные где угодно в кластере, а не только на GPU candidate worker'а, учитывались при scoring worker'ов.
Зачем
По умолчанию radix tree router'а отражает только блоки, находящиеся в GPU HBM на каждом worker'е. HiCache незаметно понижает блоки до host memory и далее до Mooncake по мере заполнения device pool, но router не видит этих переходов. Worker, у которого полный prefix запроса находится на host + Mooncake, выглядит так же, как cold worker. В итоге router считает, что "можно получить из Mooncake за миллисекунды" и "нужно пересчитать с нуля" — это одно и то же.
Модель событий
HiRadixCache SGLang выдает события BlockStored / BlockRemoved, которые несут поле medium на каждом переходе между уровнями:
| Transition | Event emitted |
|---|---|
| Fresh prefill writes blocks to GPU | store(GPU) |
| GPU → Host copy (after async DMA completes) | store(CPU_PINNED) |
| GPU evicted, block still resident on Host | remove(GPU) |
| Host evicted (block gone from all worker tiers) | remove(CPU_PINNED) |
Host → GPU promotion (load_back) | store(GPU) |
| External → Host prefetch (L2 materialization) | store(CPU_PINNED) |
CPU_PINNED — это значение, которое HiRadixCache SGLang фактически выдает для блоков host-tier (page-locked memory). Далее в руководстве используется CPU_PINNED, чтобы совпадать с on-the-wire строкой; "Host" — это концептуальное имя уровня.
Несколько свойств, на которые опирается router:
- Порядок.
store(new_tier)отправляется доremove(old_tier), поэтому блок никогда не становится невидимым для router во время перехода. - Безопасность DMA.
store(CPU_PINNED)для копии GPU→Host откладывается до тех пор, покаfinish_event.synchronize()не подтвердит, что DMA завершилась — события никогда не срабатывают до того, как байты реально окажутся в памяти. - Отслеживание по уровням. Блок может одновременно находиться на GPU и Host. Router записывает оба состояния и выбирает уровень с наивысшим приоритетом при оценке overlap.
Как это работает
flowchart LR
Worker["SGLang Worker<br/>(HiRadixCache)"]
Mooncake["Mooncake<br/>shared pool"]
Router["Dynamo KV Router<br/>per-tier radix tree"]
Worker -- "KV events (store/remove + medium)" --> Router
Worker -- "writes pages" --> Mooncake
Router -- "batch_query on each request" --> Mooncake
Для каждого запроса router выполняет два lookup параллельно:
- Its own radix tree, built from worker KV events (per-tier).
- A batch query to the Mooncake master for blocks reachable from the shared pool.
Если запрос к shared pool не удается, router откатывается к scoring только по indexer'у и пишет warning. Запрос при этом все равно проходит.
Оценка
Для каждого candidate worker router вычисляет logit (меньше — лучше):
# Without shared cache
adjusted_prefill_blocks = max(
prefill_blocks
- overlap_score_credit * device_overlap_blocks
- host_cache_hit_weight * host_overlap_blocks
- disk_cache_hit_weight * disk_overlap_blocks,
0,
)
logit = prefill_load_scale * adjusted_prefill_blocks + decode_blocks
# With shared cache
shared_beyond = shared_cache_hits.hits_beyond(device_overlap_blocks)
adjusted_prefill_blocks = max(
prefill_blocks
- overlap_score_credit * device_overlap_blocks
- host_cache_hit_weight * host_overlap_blocks
- disk_cache_hit_weight * disk_overlap_blocks
- shared_cache_multiplier * shared_beyond,
0,
)
logit = prefill_load_scale * adjusted_prefill_blocks + decode_blocks
hits_beyond(n) считает страницы shared-cache на позициях >= n — "страницы за пределами моего device prefix, которые я все еще могу забрать из Mooncake вместо пересчета."
Разбор примера. Запрос состоит из 4 блоков, shared_cache_multiplier = 0.5, block_size = 1, overlap_score_credit = 1.0 (максимальный credit за device-local overlap). Shared pool содержит блоки 0–3.
| Worker | Device overlap | hits_beyond | Device credit | Shared credit | Adjusted prefill | Logit |
|---|---|---|---|---|---|---|
| W0 | 2 (A, B) | 2 (C, D) | 2.0 | 1.0 | 1.0 | 1.0 — wins |
| W1 | 0 | 4 (A, B, C, D) | 0.0 | 2.0 | 2.0 | 2.0 |
W0 выигрывает, потому что сочетает device-local reuse с попаданиями в shared pool за пределами device prefix. Множитель задает соотношение стоимости fetch из Mooncake относительно нового GPU compute — 0.5 означает, что "получить из shared вдвое дешевле, чем пересчитать".
Требования
Tier-aware shared cache routing требует изменений в SGLang из sgl-project/sglang#22894 ("fix(hicache): emit KV events for L2 host cache insertions"). Этот PR еще не слит в main SGLang. Пока он не попадет в релиз SGLang, функция недоступна из обычного pip install sglang — нужно собирать SGLang из ветки PR (gh pr checkout 22894 && pip install -e python/ из репозитория SGLang). Этот раздел будет обновлен минимальной требуемой версией, когда #22894 выйдет в релизе.
Без PR #22894 события worker'ов несут только medium=GPU, и router не видит размещение на уровне Host — независимо от конфигурации Mooncake.
Также потребуется:
- Запущенный Dynamo router с
--shared-cache-type hicache(см. Configuration). - Доступный Mooncake master с хоста Dynamo frontend. Worker-side конфигурация Mooncake (master address, page size, TP/PP layout, split-head layout) публикуется автоматически через metadata регистрации каждого worker'а, если worker запущен с
--hicache-storage-backend mooncake.
Настройка
Известное ограничение в 1.2.0. Если на worker'е SGLang одновременно заданы --enable-metrics и --disable-piecewise-cuda-graph, процесс может упасть при первой записи в KV-cache из-за гонки в upstream thread pool mooncake-transfer-engine. Ниже эти флаги не используются; сбор метрик по процессам через dynamo.frontend не затрагивается. Исправление на стороне mooncake отслеживается upstream.
SGLang worker — HiCache с Mooncake storage:
python -m dynamo.sglang \
--model-path Qwen/Qwen3-0.6B \
--page-size 64 \
--enable-hierarchical-cache \
--hicache-ratio 2 \
--hicache-write-policy write_through \
--hicache-storage-backend mooncake \
--hicache-storage-backend-extra-config '{"master_server_address": "mooncake-master.internal:50051"}' \
--skip-tokenizer-init
Запускайте дополнительные worker'ы на других GPU / хостах с той же конфигурацией Mooncake, чтобы они подключались к тому же cluster.
Dynamo frontend — включите tier-aware routing:
python -m dynamo.frontend \
--http-port 8000 \
--router-mode kv \
--shared-cache-type hicache \
--shared-cache-multiplier 0.5
Конфигурация
| Флаг | Переменная окружения | По умолчанию | Описание |
|---|---|---|---|
--shared-cache-type | DYN_SHARED_CACHE_TYPE | none | none отключает запросы к shared pool; hicache включает запросы к Mooncake. |
--shared-cache-multiplier | DYN_SHARED_CACHE_MULTIPLIER | 0.5 | Коэффициент скидки для попаданий из shared pool. 0.0 выполняет запросы, но игнорирует их; 0.5 считает shared hit вдвое дешевле device hit; 1.0 приравнивает shared и device hits. |
Per-request overrides доступны через RouterConfigOverride.shared_cache_multiplier для A/B-экспериментов без перезапуска router'а.
Дополнительные флаги на worker'е не требуются. Когда задан --hicache-storage-backend mooncake, Dynamo публикует необходимые metadata (page size, TP/PP layout, master address) через blob ModelRuntimeConfig.engine_specific worker'а под ключом sglang_hicache_mooncake.
Проверка
События несут medium. Запустите worker с --log-level debug и проверьте лог:
python -m dynamo.sglang ... --log-level debug 2>&1 | grep -E 'BlockStored|BlockRemoved'
# BlockStored(block_hashes=[...], medium=CPU_PINNED)
# BlockRemoved(block_hashes=[...], medium=GPU)
Если medium отсутствует или всегда равен GPU, worker запущен на сборке SGLang без PR #22894.
Router видит shared pool. На Prometheus endpoint frontend'а доступны две новые histogram:
| Metric | Meaning |
|---|---|
router_shared_cache_hit_rate | Fraction of request blocks found in the shared pool (0.0–1.0). |
router_shared_cache_beyond_blocks | Blocks in the shared pool beyond the selected worker's device overlap. |
curl -s localhost:8000/metrics | grep shared_cache
Устранение неполадок
| Симптом | Вероятная причина | Исправление |
|---|---|---|
shared_cache_hit_rate is always 0 | Mooncake master недоступен с хоста router'а | Проверьте сетевой путь; router пишет Shared cache query failed, когда не может достучаться до Mooncake. |
События всегда несут только medium=GPU | В SGLang отсутствует PR #22894 | Пересоберите SGLang из ветки PR. |
| Worker'ы зарегистрированы, но router никогда не спрашивает shared cache | У --shared-cache-type остался default none | Установите --shared-cache-type hicache на frontend. |
| Запросы идут, но выбранный worker почти не меняется | --shared-cache-multiplier 0.0 | Увеличьте multiplier — типичный стартовый диапазон 0.3–0.7. |
| Предупреждения о несовпадении page size | У router --page-size не совпадает с --page-size worker'а | Они должны совпадать; router хэширует pages, используя page size worker'а. |
| Router пишет "no workers have HiCache enabled" | Ни один worker не опубликовал metadata sglang_hicache_mooncake | Убедитесь, что worker'ы запущены с --hicache-storage-backend mooncake. |
Дополнительные материалы
- Проектирование SGLang HiCache и Лучшие практики SGLang HiCache
- Mooncake — shared KV store, используемое как внешний уровень
- SGLang PR #22894 — prerequisite для событий с аннотацией уровня
- Руководство KVBM — собственный block manager Dynamo, альтернатива HiCache
- События KV для пользовательских engine — контракт протокола событий для backend'ов, отличных от SGLang