본문으로 건너뛰기

[vllm] vLLM에 DeepSeek DeepSelect 커널 통합: Sparse Attention 성능 극대화

PR 링크: vllm-project/vllm#56464 상태: Merged | 변경: +829 / -52

들어가며

vLLM의 Sparse Attention 인덱서 경로에서 TopK 연산은 추론 성능을 결정짓는 핵심 병목 구간 중 하나입니다. 기존 vLLM은 persistent, cooperative, per_row 등 다양한 백엔드를 상황에 맞춰 사용해왔으나, 최신 하드웨어(Blackwell 아키텍처)의 잠재력을 완전히 끌어내기에는 한계가 있었습니다. 본 PR은 DeepSeek의 고성능 TopK 커널 라이브러리인 DeepSelect를 vLLM에 통합하여, 특히 대규모 배치 환경에서 압도적인 성능 향상을 달성했습니다.

코드 분석

1. CMake 빌드 시스템 통합 (CMakeLists.txt, cmake/external_projects/deepselect.cmake)

DeepSelect는 FetchContent를 통해 외부 프로젝트로 관리됩니다. 특정 아키텍처(sm_100a/sm_103a)와 CUDA 12.9 이상에서만 컴파일되도록 설계되어, 호환성 문제를 방지했습니다.

# cmake/external_projects/deepselect.cmake
if(${CMAKE_CUDA_COMPILER_VERSION} VERSION_GREATER_EQUAL 12.9)
    list(APPEND DEEPSELECT_SUPPORT_ARCHS "10.0f")
endif()

# ... (중략) ...

define_extension_target(
    _deepselect_C
    DESTINATION vllm
    SOURCES ${DeepSelect_SOURCES}
    USE_SABI 3
    WITH_SOABI)

2. 백엔드 디스패처 구현 (vllm/model_executor/layers/indexer_topk.py)

새로운 SparseIndexerTopk 모듈을 통해 auto 모드 시 하드웨어와 배치 크기에 따라 최적의 커널을 선택하도록 구현되었습니다. 기존의 cooperativepersistent 커널과 동일한 인터페이스를 유지하면서도, DeepSelect를 우선순위로 배치했습니다.

# vllm/model_executor/layers/indexer_topk.py
class SparseIndexerTopk(nn.Module):
    def forward(self, logits: torch.Tensor, top_k: int, end: torch.Tensor, ...) -> torch.Tensor:
        # 백엔드 선택 로직
        backend = self._resolve_backend(logits, top_k)
        if backend == "deep_select":
            return deep_select_topk(logits, top_k, end=end)
        # ... 기존 백엔드 폴백 ...

왜 이게 좋은가

성능 수치

NVIDIA GB200 환경에서 측정한 결과, DeepSelect는 기존 기본값이었던 persistentcooperative 커널 대비 비약적인 속도 향상을 보여줍니다.

Shape DeepSelect 기존 기본값 (persistent/cooperative)
bs=256, kv=1M 191us 616us
bs=64, kv=1M 88us 132us

교훈

  1. 커널 특화의 중요성: 범용적인 torch.topk 대비 특정 연산(Sparse Indexer)에 최적화된 커널은 수십 배의 성능 차이를 만듭니다.
  2. 점진적 통합: FetchContentoptional=True 설정을 통해 기존 시스템을 깨뜨리지 않고 새로운 고성능 커널을 선택적으로 도입하는 아키텍처가 중요합니다.
  3. 안전장치: 리뷰 과정에서 발견된 NaN 처리 문제나 max(0, ...) 클램핑 이슈는 고성능 커널 도입 시 경계 조건(Edge case) 검증이 얼마나 중요한지 잘 보여줍니다.

리뷰 피드백 반영

리뷰어 ywang96의 지적에 따라, FlashInfer 임포트를 지연(Lazy import)시켜 CUDA 초기화 오류를 방지했고, abort_when_nan_found 옵션을 False로 설정하여 CUDA 그래프 캡처 시 발생할 수 있는 런타임 트랩 문제를 해결했습니다. 이러한 세심한 디버깅이 실제 프로덕션 환경에서의 안정성을 보장합니다.

참고 자료

⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.

댓글

관련 포스트

PR Analysis 의 다른글