본문으로 건너뛰기

LMCache MP 모드 vs Non-MP 모드

[!tldr] 업무 관점 takeaway 우리(FDP plugin)는 MP 모드의 L2AdapterInterface만 구현하면 된다. Non-MP legacy는 건드릴 필요 없음. 다만 raw_block의 "공유 core 패턴" (Core 위에 두 wrapper를 얹는 구조)은 베껴 쓸 가치 있음 — 나중에 Non-MP 호환 요구가 생기면 wrapper만 추가하면 되는 구조.


한 줄 정의

모드한 줄
MP (Multi-Process)LMCache가 **별도 프로세스(서버)**로 떠 있고, vLLM들이 ZMQ로 접속해 캐시 요청을 보내는 형태
Non-MPLMCache가 vLLM 프로세스 안 라이브러리로 동작 (vLLM이 import lmcache해서 직접 호출)

현재 권장 = MP 모드. Non-MP는 legacy 호환 + 단일 프로세스 시나리오용으로 남아 있다.


왜 두 모드가 존재하는가

LMCache는 처음에 vLLM 안 라이브러리(Non-MP)로 시작했다. 다음 문제가 드러나 MP 모드가 도입됐다:

  • vLLM 추론 스레드와 LMCache의 Python 작업(해싱, 메모리 관리, L2 I/O)이 같은 프로세스 안에서 GIL 경쟁 → 추론 latency 영향
  • 노드 위 vLLM pod가 여러 개일 때 L1 캐시를 공유 못 함 (각자 자기 프로세스 안에 들고 있음)
  • LMCache 쪽 버그가 나면 vLLM 프로세스가 같이 죽음
  • CPU 메모리(캐시)와 GPU 메모리(추론) 자원 스케일이 묶여 있음

프로세스 / 통신 구조 비교

Non-MP (legacy, vLLM 임베드)

┌────────────────────────── vLLM 프로세스 ──────────────────────────┐
│ vLLM 추론 코드 │
│ │ Python 함수 호출 (in-process) │
│ ▼ │
│ LMCacheEngine │
│ ├─ L1 (CPU memory) │
│ └─ StorageBackendInterface │
│ └─ StoragePluginInterface (Mooncake, S3, raw_block …) │
└──────────────────────────────────────────────────────────────────┘

▼ (옵션) Local SSD / Remote KV store
  • 통신: 함수 호출 (같은 Python 프로세스)
  • 진입 인터페이스: StoragePluginInterfaceStorageBackendInterface
  • 비동기 모델: asyncio event loop (vLLM이 깔아 둠 → plugin은 run_coroutine_threadsafe)

MP (현재 권장, 별도 서버)

┌── vLLM Pod 1 ──┐ ┌── vLLM Pod 2 ──┐ ┌── vLLM Pod N ──┐
│ vLLM client │ │ vLLM client │ │ vLLM client │
└────────┬───────┘ └────────┬───────┘ └────────┬───────┘
└─────────── ZMQ (DEALER/ROUTER, tcp) ───┘


┌────────────────────────────────────────────┐
│ lmcache server (별도 프로세스) │
│ MessageQueueServer (mq.py) │
│ MPCacheEngine (server.py) │
│ StorageManager (distributed/) │
│ ├─ L1Manager (CPU memory + TTL lock) │
│ ├─ StoreController │
│ ├─ PrefetchController │
│ └─ EvictionController │
│ L2AdapterInterface (raw_block, s3 …) │
└────────────────────────────────────────────┘

▼ Local SSD / Remote KV store
  • 통신: ZMQ DEALER/ROUTER (tcp). RequestType enum으로 명령 dispatch.
  • 진입 인터페이스: L2AdapterInterface (lmcache/v1/distributed/l2_adapters/base.py)
  • 비동기 모델: eventfd 3개 + select.poll (controller가 직접 관리)

인터페이스 비교 (★ FDP plugin 구현 관점)

항목Non-MPMP
추상 클래스StoragePluginInterfaceL2AdapterInterface
위치v1/storage_backend/abstract_backend.py:424v1/distributed/l2_adapters/base.py
메서드 형식async coroutine 위주 + prefix-only get/containssubmit_* (non-blocking) + pop_* / query_* + 3개 eventfd
비동기 트리거asyncio loop (vLLM 제공)eventfd → controller select.poll
등록 방법extra_config.storage_plugin.<name> (yaml)--l2-adapter JSON + register_l2_adapter_*
동시성asyncio 단일 스레드StoreController + PrefetchController 동시 호출 → thread-safe 필수
락 책임없음L2-side lock refcount 직접 구현 (lookup-and-lock → load → unlock)

공유 Core 패턴 (raw_block이 모범 사례)

같은 디바이스를 두 모드 다 지원하려는 표준 패턴 — Core 하나 위에 두 wrapper를 얹는다.

RawBlockCore
(슬롯 할당 / 인덱스 / 체크포인트 / lock refcount)
▲ ▲
│ │
RustRawBlockBackend RawBlockL2Adapter
(StoragePluginInterface) (L2AdapterInterface)
= Non-MP wrapper = MP wrapper
prefix-only get/contains non-blocking + eventfd
asyncio.run_coroutine_.. ThreadPoolExecutor 3개

FDP plugin 설계 시 이 패턴을 베껴 쓸 것. Phase 0에서는 MP wrapper만 만들고, Non-MP 호환이 필요해지면 Core만 공유해서 Non-MP wrapper 추가.


FDP Plugin 구현 시 체크리스트

MP만 짠다 (L2AdapterInterface + plugin 또는 native_plugin 타입).

신경 써야 할 것:

  • eventfd 3개 (store/lookup/load) — lmcache.v1.platform.create_event_notifier()로 생성
  • submit_*은 non-blocking, 결과는 pop_* / query_*로 따로 회수
  • thread-safe (StoreController + PrefetchController 동시 호출)
  • L2-side lock refcount (lookup_and_lockloadunlock)

필요 없는 것:

  • asyncio event loop (framework가 안 깔아 줌)
  • Non-MP의 prefix-only get/contains 인터페이스

TP > 1 주의: MP는 현재 per_tp_device_paths 거부 → TP별 디바이스 분산이 필요하면 MP 쪽 별도 PR이 선행돼야 함. Phase 0에서 우리는 단일 디바이스로 시작.


핵심 차이 요약

항목Non-MP (legacy)MP (권장)
프로세스vLLM 안 임베드별도 서버 (lmcache server)
통신in-process 함수 호출ZMQ tcp (DEALER/ROUTER)
L1 캐시 공유pod별 따로노드 안 모든 pod가 공유
GIL 경쟁있음없음 (다른 프로세스)
추상 클래스StoragePluginInterfaceL2AdapterInterface
비동기 모델asyncioeventfd + poll
per_tp_device_paths지원거부 (raw_block_l2_adapter.py:147-150)
향후 방향유지보수 모드활성 개발

관련 페이지

  • [[LMCache-아키텍처]] — 2-mode 구조 전체 그림
  • [[L2-어댑터]] — MP 전용 L2AdapterInterface 상세 계약
  • [[Plugin-Pipeline]] — plugin 타입으로 FDP 로직 외부 주입
  • [[raw_block-종단-분석]] — raw_block 전계층, FDP 삽입 지점 H1-H8
  • [[raw_block-개선-Task]] — M1/M2(io_uring), S1(eviction) 착수 조건
  • [[Issue-3394-NonMP-Eviction]] — Non-MP eviction 부재 이슈 (S1)
  • [[LMCache-동시성-비동기-기초]] — 두 모드의 완료 알림(Future vs eventfd) 상세