안녕하세요 윤도현입니다. 이번 글에서는 Deepstream의 기본 개념에 대해 정리하였습니다.
관련글
[1] [MLOps] Deepstream 1 - 기본개념
[2][MLOps] Deepstream 2 - 환경세팅(with docker)

1. Deepstream이란?
NVIDIA Deepstream SDK는 여러 영상 스트림을 실시간으로 분석하기 위한 GPU 가속 프레임워크입니다. 한마디로 설명하면 "여러개의 영상을 입력받아 동시에 추론할 수 있도록 최적화"해주는 아주 고마운 도구입니다
2. Deepstream을 써야하는 이유?
제가 Deepstream을 써야겠다고 생각한 이유는 크게 다섯가지 입니다.
- 첫째, 실시간 멀티 스트림(multi-stream) 영상 처리 가능
- Deepstream은 여러 개의 카메라 스트림을 GPU에서 동시에 받아서 실시간으로 추론할 수 있도록 도와줍니다.
- 예를들어 pytorch 모델로 RTSP 스트림 5개를 처리한다고 가정한다면, 대부분의 GPU들은 추론 딜레이 때문에 버벅이고 FPS도 떨어질 것입니다.
- 하지만 Deepstream은 nvstreammux(스트림 멀티플렉서)로 배치처리, TensorRT 최적화, zero-copy memory 공유 등을 활용해서 FPS 드랍없이 가뿐하게 처리합니다.
- 둘째, 복잡한 TensorRT 라이브러리를 추상화
- 만약 TensorRT를 직접 사용한다면 다음과 같은 작업이 필요합니다.
- pytorch 모델을 onnx 모델로 변환
- onnx 모델로 TensorRT 엔진 파일 생성
- GPU 메모리 할당
- Inference 코드 작성
- 하지만 Deepstream을 사용하면 위 과정을 nvinfer 라는 플러그인으로 추상화해서 코드 한줄만으로 처리가 가능합니다.
- 만약 TensorRT를 직접 사용한다면 다음과 같은 작업이 필요합니다.
- 셋째, NVIDIA GPU 리소스를 100% 활용가능
- 일반적으로 저 같은 "범인"들은 아무리 python code로 gpu 메모리를 최적화한다고 해도 NVIDIA GPU 리소스를 100% 활용할 수 없습니다.
- 하지만 Deepstream을 사용하면 NVDEC, DLA, zero-copy 메모리 등 NVIDIA 플랫폼의 가속 기능을 "알아서" 적용해주기 때문에 소모 전력 최소화 + 성능 극대화가 가능하게 됩니다.
- 넷째, 엣지-클라우드 연동 기능
- Deepstream은 AI 추론 결과를 HTTP, MQTT, Kafka 등으로 실시간으로 클라우드 서버에 전송하는 기능을 매우 간단하게 구현할 수 있습니다.
- nvmsgbroker 플러그인을 설정하면 실시간 이벤트 알림, 대시보드 연동 등을 매우 간단하게 구현할 수 있습니다.
이러한 다양한 이유들 때문에 Deepstream을 써야겠다고 마음 먹었습니다.
3. Deepstream 파이프라인 구조

이제 Deepstram의 구조가 어떻게 되어있는지 알아보겠습니다. 그림을 보면서 영상 입력(좌측)부터 클라우드 연동(우측)까지 영상 데이터가 입력되어 어떻게 처리되어서 최종결과가 출력되는지 순서대로 설명해보겠습니다.
- 여러 영상 소스(카메라, RTSP 네트워크 스트림, 동영상 파일 등)로부터 스트림을 입력받아 각 영상을 디코딩합니다.
- 스트림 멀티플렉서(streammux)가 복수개의 입력 스트림을 하나의 배치로 결합합니다.
- 결합된 프레임에 대해 AI 모델로 객체 검출을 수행합니다.
- 객체 추적기로 검출된 객체들을 추적하고 ID를 부여합니다.
- (선택적으로) secondary classifiers로 클래스를 구분합니다.
- 타일러(Tiler)가 다중 영상 스트림을 하나의 화면에 격자 형태로 배열합니다.
- 온스크린 디스플레이를 통해 영상에 추론 결과값(bbox, class 등)을 그려줍니다.
- 메세지 변환/브로커로 클라우드 서버에 메타데이터를 전송합니다.
- 최종적으로 렌더러(renderer)를 통해 화면에 표시하거나 .mp4 파일 등으로 저장합니다.
3.1 입력 및 디코딩
입력 단계에서는 카메라, 파일, 네트워크 스트림 등으로부터 영상을 가져옵니다.
만약 입력받은 영상이 H.264/H.265 등으로 압축되어 있다면, 추론을 위해 디코딩하여 원시 프레임으로 변환해야 합니다. 이때 NVIDIA GPU의 하드웨어 디코더(NVDEC)를 활용하여 매우 빠르게 압축된 영상을 디코딩합니다.
3.2 스트림 멀티플렉서(Gst-nvstreammux)
입력 소스가 여러개일 경우, 스트림 멀티플렉서 단계에서 다수의 영상 스트림을 단일 배치로 결합합니다. NVIDIA Deepstream의 nvstreammux 플러그인을 사용합니다. 예를들어, 4개의 카메라에서 들어온 영상을 배치 크기 4로 묶으면, 추론 엔진은 한 번에 4장의 프레임을 받아서 병렬로 처리할 수 있어 GPU 활용이 극대화 됩니다.
Q. 스트림 멀티플렉서로 배치단위로 묶어서 GPU에 올리면 Out of Memory 에러가 나지 않을까?
: 결론부터 말하면 Deepstream은 이러한 OOM 문제를 막기 위해 여러 가지 최적화 기법을 활용하기 때문에 OOM 문제가 발생하지 않습니다.
예를들어 4개의 스트림을 멀티플렉서로 묶어서 처리하는 경우를 설명해보겠습니다.
스트림 x 1920x1080 x 3ch (RGB) = 약 24MB/frame → 배치당 약 96MB + 메타데이터 + 오버헤드 = 100MB 이상
뿐만 아니라 디코더 출력, 추론 입력, 후처리 출력 등 여러 컴포넌트가 GPU memory를 사용해야 합니다. 이렇게 되면 GPU VRAM은 증가할 수 밖에 없습니다.
그렇다면 Deepstream에서는 이러한 OOM 문제를 어떻게 해결했을까요?
1. zero-copy & NVMM(비디오 메모리 공유) 활용
- Jetson 플랫폼에서는 nvbuf-memory-type=3 설정을 통해 CPU ↔ GPU 간 메모리 복사를 최소화함
- Deepstream은 프레임을 가능한 GPU 메모리 안에서만 공유해서 복사 비용없이 처리
2. Bached Buffer를 한 타이밍만 유지
- nvstreammux는 배치 크기만큼 프레임을 모은 뒤 한 번에 downstream으로 전달
- 추론이 끝나면 GPU 메모리를 즉시 해제하여 메모리 확보
- 즉 프레임 4개씩을 동시에 올리긴 해도 모든 프레임을 메모리에 동시에 올려두고 있지 않기 때문에 메모리 사용량이 비교적 적습니다.
3. Buffer Spill 활용
- GPU에서 메모리가 부족하면 데이터를 일시적으로 CPU 메모리로 넘겨서 계속 파이프라인을 유지
- 쉽게 설명하면 원래는 카메라 → 디코더 → 추론기 흐름이 GPU 메모리 상에서 돌아갑니다.
- 이때, GPU 메모리가 꽉차버리면 디코더를 멈추는 게 아니라 버퍼를 임시 저장소(CPU RAM)로 넘겨서 버텨냅니다.
3.3 객체 탐지(Gst-nvinfer)
NVIDIA TensorRT를 활용하는 nvinfer 플러그인을 통해 사전 학습된 딥러닝 모델로 입력 영상을 추론합니다.
3.4 객체 추적(Gst-nvtracker)
NVIDIA의 nvtracker 플러그인을 통해 검출된 객체들을 식별하고 동일한 객체에 대해 동일한 ID를 부여합니다.DeepStream의 nvtracker는 SORT, DeepSORT 등 다양한 추적 알고리즘을 지원합니다.
3.5 타일러(Gst-nvmultistreamtiler)
타일러는 여러 영상 스트림을 한 화면에 배치하여 출력할 수 있도록 도와줍니다. nvmultistreamtiler 플러그인을 통해 N개의 영상을 마치 격자 타일처럼 배열된 단일 출력 프레임으로 만들어줍니다.
예를들어 4개의 카메라 스트림이 있다면 2x2 형태로 축소된 영상을 하나의 창에 표시합니다. 타일러는 주로 디스플레이 목적으로 사용되며, 각 소스 영상의 해상도를 적절히 축소/이동시켜 하나의 큰 캔버스에 그려넣습니다.
3.6 온스크린 디스플레이(Gst-nvdsosd)
온스크린 디스플레이는 추론 결과를 영상위에 시각적으로 표시해주는 역할을 맡습니다.
간단히 python PIL 라이브러리로 이미지 위에 bbox를 Draw 해주는 기능을 생각하면 이해가 빠를 것 같습니다!
3.7 메세지 변환/브로커(Gst-nvmsgconv/Gst-nvmsgbroker)
메세지 변환/브로커는 Edge-to-Cloud 연동을 위해 메세지 프로토콜 변환/전송 역할을 맡습니다.
nvmsgconv와 nvmsgbroker 플러그인을 통해 추론 결과 메타데이터를 클라우드(예를들어 모니터링 서버)로 보내기 좋은 형태로 변환해줍니다. 예를들어, 검출된 객체들의 class, bbox 좌표 등을 JSON 같은 구조 메세지로 변환한 뒤 HTTP 프로토콜로 모니터링 서버에 전달할 수 있습니다!
3.8 싱크(Sink)
Sink는 Gstreamer 파이프라인 마지막에 위치해서 데이터를 어떻게 할지 최종결정하는 역할입니다.
예를들어,
- fakesink: 데이터를 받아놓고 아무 것도 안 함 (그냥 버림)
- filesink: 데이터를 받아서 파일로 저장
- udpsink: 데이터를 네트워크로 전송
- nveglglessink: 데이터를 화면에 표시
이중 데이터를 화면에 표시하는 싱크(nveglglessink)를 렌더러라고 부릅니다(렌더러는 싱크의 하위 개념입니다).
이 단계에서 최종 데이터를 파일로 저장할지, 네트워크를 통해 모니터링 서버로 전송할지 등을 결정합니다.
여기까지 DeepStream 프레임워크의 기본 개념에 대해 알아봤습니다.

Reference
[1] https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_Overview.html
[3] https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_sample_configs_streams.html
'기본기 > MLOps' 카테고리의 다른 글
[MLOps] Deepstream 3 - 실습(Multi-stream Pose Estimation) (0) | 2025.03.27 |
---|---|
[MLOps] DeepStream 2 - 환경세팅(with docker) (0) | 2025.03.26 |
[MLOps] Airflow 3 - 실습(ML 모델 학습/실험 자동화) (0) | 2025.03.25 |
[MLOps] Airflow 2 - 환경세팅(with docker) (0) | 2025.03.25 |
[MLOps] Airflow 1 - 기본개념 (0) | 2025.03.25 |