[vLLM] Plugin & Hardware: 플러그인 시스템과 하드웨어 플랫폼
들어가며
vLLM은 NVIDIA GPU뿐만 아니라 AMD GPU, Intel XPU, Google TPU, AWS Neuron 등 다양한 하드웨어를 지원한다. 이를 가능하게 하는 것이 vllm/plugins/의 플러그인 시스템과 vllm/platforms/의 하드웨어 추상화 레이어다.
공식 문서
vLLM 공식 문서: Plugin System
핵심 구조/코드 분석
플러그인 그룹
DEFAULT_PLUGINS_GROUP = "vllm.general_plugins" # 모든 프로세스에서 로드
IO_PROCESSOR_PLUGINS_GROUP = "vllm.io_processor_plugins" # process0에서만 로드
PLATFORM_PLUGINS_GROUP = "vllm.platform_plugins" # 플랫폼 감지 시 로드
STAT_LOGGER_PLUGINS_GROUP = "vllm.stat_logger_plugins" # async 서빙 시 로드
플러그인을 용도별로 네 그룹으로 분류한다. 각 그룹은 로드 시점과 프로세스 범위가 다르다. general_plugins는 API 서버, 엔진 코어, 워커 모든 프로세스에서 로드되고, io_processor_plugins는 API 서버(process0)에서만 로드된다.
entry_points 기반 플러그인 발견
def load_plugins_by_group(group: str) -> dict[str, Callable[[], Any]]:
from importlib.metadata import entry_points
allowed_plugins = envs.VLLM_PLUGINS
discovered_plugins = entry_points(group=group)
plugins = dict[str, Callable[[], Any]]()
for plugin in discovered_plugins:
if allowed_plugins is None or plugin.name in allowed_plugins:
try:
func = plugin.load()
plugins[plugin.name] = func
except Exception:
logger.exception("Failed to load plugin %s", plugin.name)
return plugins
Python의 entry_points 메커니즘을 사용하여 설치된 패키지에서 플러그인을 자동으로 발견한다. VLLM_PLUGINS 환경변수로 허용할 플러그인을 제어할 수 있다.
플랫폼 자동 감지
def cuda_platform_plugin() -> str | None:
try:
pynvml = import_pynvml()
pynvml.nvmlInit()
is_cuda = pynvml.nvmlDeviceGetCount() > 0 and not vllm_version_matches_substr("cpu")
if is_cuda:
return "vllm.platforms.cuda.CudaPlatform"
except Exception:
return None
def tpu_platform_plugin() -> str | None:
if envs.VLLM_TPU_USING_PATHWAYS:
return "tpu_inference.platforms.tpu_platform.TpuPlatform"
try:
import libtpu
return "vllm.platforms.tpu.TpuPlatform"
except Exception:
return None
CUDA, TPU, ROCm, XPU 등을 순차적으로 감지한다. NVIDIA GPU는 pynvml로 감지하고, TPU는 libtpu 패키지 존재 여부로 판단한다. 엣지 케이스도 처리한다 - GPU 머신에서 CPU 빌드 vLLM을 사용하는 경우, vllm_version_matches_substr("cpu")로 CUDA를 비활성화한다.
IO Processor 플러그인
# vllm/plugins/io_processors/interface.py
class IOProcessorPlugin:
"""IO 프로세서 플러그인 인터페이스"""
IO 프로세서 플러그인은 요청/응답의 전처리/후처리를 커스터마이즈할 수 있다. 예를 들어 커스텀 토크나이저나 프롬프트 변환 로직을 플러그인으로 추가할 수 있다.
LoRA Resolver 플러그인
# vllm/plugins/lora_resolvers/
├── filesystem_resolver.py # 파일시스템에서 LoRA 어댑터 로드
├── hf_hub_resolver.py # HuggingFace Hub에서 LoRA 로드
LoRA 어댑터의 위치를 해석하는 resolver도 플러그인으로 구현되어 있다. 파일시스템과 HuggingFace Hub을 기본 제공하며, S3나 GCS 같은 커스텀 스토리지 지원도 플러그인으로 추가할 수 있다.
안전한 중복 로드 방지
plugins_loaded = False
def load_general_plugins():
global plugins_loaded
if plugins_loaded:
return
plugins_loaded = True
plugins = load_plugins_by_group(group=DEFAULT_PLUGINS_GROUP)
for func in plugins.values():
func()
멀티프로세스 환경에서 각 프로세스가 독립적으로 load_general_plugins를 호출하므로, 전역 플래그로 중복 로드를 방지한다. 주석에 "플러그인은 여러 번 로드되어도 문제 없어야 한다"고 명시하고 있다.
왜 이 설계인가
-
entry_points 선택: pip/setuptools의 entry_points는 Python 생태계의 표준 플러그인 메커니즘이다. 별도의 플러그인 레지스트리 서버 없이, 패키지 설치만으로 플러그인이 자동 등록된다. vLLM을 포크하지 않고도 기능을 확장할 수 있다.
-
그룹별 분리: 모든 플러그인을 한 번에 로드하면, 불필요한 의존성이 로드되어 시작 시간이 늘어나고 보안 위험이 생긴다. 그룹별로 분리하여 필요한 프로세스에서만 필요한 플러그인을 로드한다.
-
VLLM_PLUGINS 화이트리스트: 기본적으로 모든 설치된 플러그인이 로드되지만,
VLLM_PLUGINS환경변수로 허용 목록을 지정할 수 있다. 프로덕션 환경에서 신뢰할 수 있는 플러그인만 로드하도록 제한할 수 있다.
참고 자료
관련 포스트
vLLM 의 다른글
- 이전글 [vLLM] Observability: 추적, 프로파일링, 메트릭
- 현재글 : [vLLM] Plugin & Hardware: 플러그인 시스템과 하드웨어 플랫폼
- 다음글 [vLLM] Preemption & Async Scheduling: 선점과 비동기 스케줄링
댓글