[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_create와 mmap 도입
기존 방식은 subprocess.run의 capture_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 하나만 디코딩을 수행합니다.
핵심 로직:
_reference_video_host_leader()를 통해 호스트별 대표 Rank를 선정합니다.- Leader Rank는 비디오를 디코딩하여
memfd에 저장합니다. - Leader는 자신의
/proc/self/fd/{fd}경로를 다른 로컬 Rank들에게 전파합니다. - 다른 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에 빠지는 상황을 원천 차단했습니다.
일반적인 교훈
- 중복 계산 제거: 분산 환경에서 모든 Worker가 동일한 CPU 작업을 수행하고 있다면, 이를 호스트 단위로 묶을 수 없는지 고민해야 합니다.
- OS 레벨 API 활용: Python의 기본 라이브러리만으로는 대용량 데이터 처리에 한계가 있습니다.
memfd,mmap,/proc파일 시스템 등 OS가 제공하는 기능을 활용하면 Zero-copy에 가까운 성능을 낼 수 있습니다. - Graceful Fallback: 최첨단 최적화 기술일수록 환경 의존성이 높습니다. 항상 안전한 기본 동작(Local decode)으로 돌아갈 수 있는 길을 열어두는 것이 시니어 엔지니어의 설계 역량입니다.
이 PR은 대규모 분산 추론 엔진에서 데이터 인입 파이프라인을 어떻게 설계해야 하는지 보여주는 아주 좋은 사례입니다.
참고 자료
- https://man7.org/linux/man-pages/man2/memfd_create.2.html
- https://docs.python.org/3/library/mmap.html
- https://pytorch.org/docs/stable/distributed.html#torch.distributed.all_gather_object
- https://ffmpeg.org/ffmpeg-protocols.html#pipe
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
PR Analysis 의 다른글
- 이전글 [vllm] vLLM에 Dots3 NOTE 모델 네이티브 지원 추가: 멀티모달 및 하이브리드 MLA 최적화
- 현재글 : [sglang] [Diffusion] MiniMax-H3 비디오 인입 최적화: 87.5% 메모리 절감과 Zero-Copy의 마법
- 다음글 [flashinfer] FlashInfer SM120 MoE GEMM 최적화: 웨이브+잔여물 비용 모델 도입
댓글