딥러닝(Deep Learning)/Etc.

[TRTIS] Triton Inference Server - 3 (Ensemble Model 사용해보기)

내 이름인데 윤기를 왜 못써 2024. 4. 27. 21:25

목차

    이전 글에 이어서 Triton Inference Server 사용 튜토리얼을 저번 글에 이어서 작성해 보겠다.

    아래 시리즈를 따라서 튜토리얼을 진행하는 것을 추천한다.

    1. 2024.03.30 - [딥러닝(Deep Learning)/Etc.] - [TRTIS] Triton Inference Server 사용해보기 - 1 (개요 및 설치)
    2. 2024.04.21 - [딥러닝(Deep Learning)/Etc.] - [TRTIS] Triton Inference Server 사용해보기 - 2 (서버 실행, 모델 배포 맛보기)

    이번 글에서는 저번 튜토리얼에 이어서 Triton Inference Server에서 제공하는 Ensemble Model에 대해서 다뤄보겠다.

     

    Ensemble Model

    개요

    Ensemble이라는 단어는 ML 분야에서 많이 들어본 단어일 것이다. 하지만 그 Ensemble과 여기서의 Ensemble은 살짝 다르다. Triton 문서에서 말하길 "Ensemble Model은 하나 이상의 모델의 입력과 출력을 연결하는 파이프라인을 의미한다."라고 말한다.

    즉, Ensemble Model은 여러 모델의 절차를 캡슐화하기 위해서 사용될 것이다. 예를 들어 "전처리 -> 추론 -> 후처리"와 같은 ML에서 일반적인 절차를 위해서 사용될 수 있다. 이로써, Tensor 간 전송의 오버헤드를 피할 수 있고, Triton에 전송하는 요청을 최소화할 수 있다.

     

    그리고 Ensemble Model은 실제 모델이 아니다. 모델 간의 Scheduling을 명시함으로써 연결해 주는 것이지, 실제 모델로써 존재하는 것은 아니다. 설명으로써는 잘 와닿지 않을 수 있다. 준비한 예시를 보고, 다시 잘 이해해 보도록 하자.

    Example

    만약 내가 "작업 A"를 진행하고, "작업 B"를 수행해서 최종 결과를 내고싶다면 어떡할까? 일반적으로는 "작업A"를 수행하는 모델과 "작업B"를 수행하는 모델을 각각 올리고, 클라이언트에서 "작업A"를 수행한 결과를 "작업B"를 수행하도록 입력으로 다시 넣어주면 된다.

    하지만 클라이언트가 모델 배포자가 원하는 의도와 다르게 작업을 진행할 수도 있고, 각각의 작업을 위해 Triton Server에 요청을 보내야 하기에 서버에 부하가 더 걸릴 수도 있다. 그렇기에 각각 분리된 작업을 한 번에 통합적으로 수행하고 배포하기 위해서 존재하는 게 Ensemble Model이다.

     

    예시 모델을 통해서 설명을 진행하겠다.

     

    어떤 모델이 3을 곱하고, 100을 더하는 작업을 수행한다고 생각해 보자. 그럼 우리는 이 모델의 작업을 아래와 같이 각각 두 개로 나눌 수 있다.(설명을 위한 예시이다. 일반적인 ML Task에서는 더 복잡하고 어려운 작업이 포함될 수 있다.)

    1. 3을 곱하는 작업(모델 1)
    2. 100을 더하는 작업(모델 2)

    그럼 각각의 작업을 통합적으로 수행하는 모델을 만들어보겠다. Ensemble Model을 만드는 법은 다른 Model을 만드는 법과 동일하다. 하지만 실제 모델이 아니기에, Version Directory 하위에 `model.py`가 없어도 된다는 차이점이 있다.

    먼저 기본적인 디렉터리 구조를 보자.

    model_repository
    └── ensemble_sample
        ├── 1
        └── config.pbtxt

     

     

    이렇게 실제 모델은 없고, `config.pbtxt`의 조작으로만 Ensemble Model을 만들 수 있다.

    하지만 Ensemble Model은 연결만 해주는 모델이기에, 각각의 과정에서 필요한 Model들은 구성해두어야만 한다.

     

    config.pbtxt

    Ensemble Model에 대한 설정들과 스케줄들이 담겨있다. 한번 바로 전체 파일의 내용을 보자.

    name: "ensemble_sample"
    platform: "ensemble"
    max_batch_size: 0
    
    input [
      {
        name: "input__0"
        data_type: TYPE_FP32
        dims: [-1]
      }
    ]
    
    output [
      {
        name: "output__0"
        data_type: TYPE_FP32
        dims: [-1]
      }
    ]
    
    ensemble_scheduling {
        step [
            {
                model_name: "one_model"
                model_version: -1
                input_map {
                    key: "one_input"
                    value: "input__0"
                }
                output_map {
                    key: "one_output"
                    value: "one_result"
                }
            },
            {
                model_name: "two_model"
                model_version: -1
                input_map {
                    key: "two_input"
                    value: "one_result"
                }
                output_map {
                    key: "two_output"
                    value: "output__0"
                }
            }
        ]
    }

     

     

    이전의 모델들과는 달리 `backend`의 명시가 없고, `platform`이라는 명시가 있다. `platform`에 `ensemble`을 명시해 줌으로써, 이 모델은 Ensemble Model로써 동작할 것을 알려줄 수 있다.

    `max_batch_size`, `input`과 `output`은 똑같이 존재하는데 이 Ensemble Model을 하나의 Model로 인식하기에, 똑같이 필요하다. 이제 가장 중요한 건 `ensemble_scheduling` 블록이다.

     

    이 Ensemble Model이 어떤 방식으로 작동할 것인지 step을 여기서 명시해 준다.

    각 모델의 출력과 입력을 매핑해 주는 방식으로 Ensemble 단계를 정할 수 있다.

     

    우리 예시 모델의 단계를 생각해 보면

    (앙상블 모델의 입력=모델 1의 입력) -> 모델 1의 출력 -> 모델 2의 입력 -> (모델 2의 출력=앙상블 모델의 출력)

     

    으로 인지할 수 있다. 이 것을 각각의 이름으로 매핑해 주는 것이다.

     

    앙상블 모델의 입력 = 모델 1의 입력

     

    각 과정을 매핑하는 것에 주목해서 코드를 보자.

    {
        model_name: "one_model"
        model_version: -1
        input_map {
            key: "one_input"
            value: "input__0"
        }
        output_map {
            key: "one_output"
            value: "one_result"
        }
    },

     

    `step`의 첫 과정은 `one_model`(모델 1)을 수행해야 한다.

    `input_map`에는 `one_model`의 입력인 `one_input`에 대응되는 값을 지정해 준다. 값으로 앙상블 모델의 입력인 `input__0` 을 지정해준다.

     

    출력은 중간 과정에서 쓰일 출력의 이름을 지정해 준다고 생각하면 된다.

    모델 1의 출력인 `one_output`을 `one_result`라는 이름으로 과정에서 사용한다는 말이다.

     

    모델 1의 출력 -> 모델 2의 입력, 모델 2의 출력=앙상블 모델의 출력

     

    이번엔 모델 1의 출력을 모델 2의 입력으로 사용하는 과정과, 모델 2의 출력을 앙상블 모델의 출력으로 사용하는 과정이다.

    {
        model_name: "two_model"
        model_version: -1
        input_map {
            key: "two_input"
            value: "one_result"
        }
        output_map {
            key: "two_output"
            value: "output__0"
        }
    }

     

    위의 내용과 똑같다. 모델 2의 입력 `two_input`의 값으로 이전에 우리가 중간과정에서 사용하기로 정한 `one_result`를 사용한다.

    또한 모델 2의 출력이 앙상블 모델의 출력이 되어야 하기에, 모델 2의 출력 `two_output` 의 값을 앙상블 모델의 출력인 `output__0`로 매핑해 준다.


    이렇게 Ensemble Model을 구성할 수 있다. 물론 ML 모델을 배포할 때에는 더 복잡한 과정이 들어있을 것이기에, 이 설명만으로는 능숙하게 사용이 힘들 수 있다. 하지만 기본이 되는 내용은 되리라 생각하고, 이 것을 더 응용하면 복잡한 모델도 잘 설계할 수 있을 것이다!

     

    Ensemble Model의 설명과 더 복잡한 구조의 예제를 원한다면, 아래 링크들에 들어가서 NVIDIA문서의 추가적인 내용을 확인해 보자.

     

    Triton Architecture — NVIDIA Triton Inference Server

    <!-- # Copyright 2018-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # * Redistributions of

    docs.nvidia.com

     

    tutorials/Conceptual_Guide/Part_5-Model_Ensembles at main · triton-inference-server/tutorials

    This repository contains tutorials and examples for Triton Inference Server - triton-inference-server/tutorials

    github.com

     

    이상 Ensemble Model에 대한 기초적인 설명을 마친다.

     

    튜토리얼 코드

    https://github.com/dbsrlskfdk/triton-tutorial/tree/main/triton_ensemble_sample

     

    triton-tutorial/triton_ensemble_sample at main · dbsrlskfdk/triton-tutorial

    Contribute to dbsrlskfdk/triton-tutorial development by creating an account on GitHub.

    github.com

     

     

    반응형