본문으로 건너뛰기

[sglang] [Diffusion] MiniMax-H3 비디오 인입 최적화: 87.5% 메모리 절감과 Zero-Copy의 마법

PR 링크: sgl-project/sglang#34563 상태: Merged | 변경: +381 / -26

들어가며

최근 Diffusion 기반의 비디오 생성 모델이 발전함에 따라, 모델의 입력으로 들어가는 '참조 비디오(Reference Video)'의 전처리 성능이 중요해지고 있습니다. 특히 Multi-GPU 환경에서 각 GPU Rank(Worker)가 동일한 비디오를 독립적으로 디코딩하는 방식은 심각한 자원 낭비를 초래합니다.

sgl-project/sglang에 제출된 이 PR은 MiniMax-H3 모델의 비디오 인입(Ingress) 과정을 최적화하여, 8-GPU 호스트 기준 메모리 사용량을 87.5% 절감하고 디코딩 속도를 2배 이상 향상시켰습니다. 핵심 아이디어는 "호스트당 한 번만 디코딩하고, 결과물을 로컬 Worker들이 공유하자"는 것입니다.

코드 분석: 무엇이 바뀌었는가?

1. Python Pipe의 한계 극복: memfd_createmmap 도입

기존 방식은 subprocess.runcapture_output=True를 사용했습니다. 이는 FFmpeg의 출력을 Python의 bytes 객체로 캡처하는데, 데이터가 클 경우 Python 내부에서 여러 번의 바이트 복사와 병합(Aggregation)이 발생하여 CPU와 메모리에 부하를 줍니다.

Before:

# 기존: FFmpeg 출력을 stdout 파이프로 직접 캡처
decoded = subprocess.run(
    command,
    check=True,
    capture_output=True,
)
payload = decoded.stdout

After:

# 개선: 리눅스의 익명 파일 디스크립터(memfd)를 생성하여 FFmpeg이 직접 쓰게 함
output_fd = os.memfd_create("sglang-h3-reference-video", flags=os.MFD_CLOEXEC)

# ... FFmpeg 실행 시 pipe:{output_fd} 전달 ...

# 파일 내용을 메모리에 매핑 (Zero-copy에 가까운 접근)
payload = mmap.mmap(output_fd, payload_size, access=mmap.ACCESS_WRITE)

os.memfd_create를 통해 생성된 익명 파일은 디스크 I/O 없이 메모리 상에 존재하며, mmap을 통해 Python 객체로 매핑함으로써 불필요한 바이트 복사 오버헤드를 제거했습니다.

2. Host-Level 공유 디코딩 (Shared Ingress)

가장 큰 변화는 _decode_reference_video_shared 함수의 도입입니다. 이전에는 모든 Rank가 각자 FFmpeg을 실행했지만, 이제는 호스트 내의 'Leader' Rank 하나만 디코딩을 수행합니다.

핵심 로직:

  1. _reference_video_host_leader()를 통해 호스트별 대표 Rank를 선정합니다.
  2. Leader Rank는 비디오를 디코딩하여 memfd에 저장합니다.
  3. Leader는 자신의 /proc/self/fd/{fd} 경로를 다른 로컬 Rank들에게 전파합니다.
  4. 다른 Rank들은 해당 경로를 os.open하고 mmap하여 동일한 물리 메모리 페이지를 공유합니다.

After (Shared Logic):

if is_leader:
    leader_fd = os.memfd_create("sglang-h3-reference-video-shared", ...)
    payload_size = _write_reference_video_to_fd(command, leader_fd)
    leader_state = (f"/proc/{os.getpid()}/fd/{leader_fd}", payload_size, None)

# 모든 Rank가 Leader의 파일 경로 정보를 공유받음
states = _all_gather_world_objects(group, leader_state)
local_path, payload_size, _ = states[leader]

# 타 Rank들은 Leader가 만든 fd를 열어서 메모리 매핑
map_fd = os.open(local_path, os.O_RDWR)
mapping = mmap.mmap(map_fd, payload_size, access=mmap.ACCESS_COPY)

3. 견고한 Fallback 메커니즘

공유 메모리 방식은 강력하지만, 컨테이너 환경의 보안 정책(seccomp)이나 /proc 접근 제한으로 인해 실패할 수 있습니다. 이 PR은 이러한 상황에서도 시스템이 멈추지 않도록 정교한 Fallback을 구현했습니다.

if owner_error is not None:
    # 에러 발생 시 모든 Rank가 함께 로컬 디코딩 모드로 전환하여 분산 환경의 Divergence 방지
    return _decode_reference_video_local(command)

왜 이게 좋은 최적화인가?

1. 압도적인 자원 절감 (Performance)

PR 본문에 명시된 수치에 따르면, 8-GPU H200 호스트에서 5초 분량의 비디오(1344x768) 처리 시:

  • 메모리 점유: 2.97 GB → 371 MB (87.5% 감소)
  • 디코딩 시간: 0.546s → 0.244s (2배 이상 빨라짐)
  • Peak RSS: 743 MB → 369 MB

이는 단순히 속도만 빨라진 것이 아니라, 남는 메모리를 모델 가중치나 KV Cache에 더 할당할 수 있게 함으로써 전체적인 처리량(Throughput) 향상에 기여합니다.

2. Bit-Exact 유지

성능을 위해 품질을 타협하지 않았습니다. Lanczos scale, 24 FPS, RGB24 transformation 등 기존의 FFmpeg 그래프를 그대로 유지하면서 데이터 전달 방식만 최적화했기 때문에, 최종 결과물은 이전 방식과 Byte-for-byte로 완벽히 일치합니다.

3. 분산 시스템의 안정성

all_gather_object를 통해 모든 Rank가 동일한 상태(성공/실패)를 공유하게 함으로써, 특정 Rank만 디코딩에 실패하여 전체 Collective 통신이 Deadlock에 빠지는 상황을 원천 차단했습니다.

일반적인 교훈

  1. 중복 계산 제거: 분산 환경에서 모든 Worker가 동일한 CPU 작업을 수행하고 있다면, 이를 호스트 단위로 묶을 수 없는지 고민해야 합니다.
  2. OS 레벨 API 활용: Python의 기본 라이브러리만으로는 대용량 데이터 처리에 한계가 있습니다. memfd, mmap, /proc 파일 시스템 등 OS가 제공하는 기능을 활용하면 Zero-copy에 가까운 성능을 낼 수 있습니다.
  3. Graceful Fallback: 최첨단 최적화 기술일수록 환경 의존성이 높습니다. 항상 안전한 기본 동작(Local decode)으로 돌아갈 수 있는 길을 열어두는 것이 시니어 엔지니어의 설계 역량입니다.

이 PR은 대규모 분산 추론 엔진에서 데이터 인입 파이프라인을 어떻게 설계해야 하는지 보여주는 아주 좋은 사례입니다.

참고 자료

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

댓글

관련 포스트

PR Analysis 의 다른글