본문 바로가기
Dev Notes/ML

C++에서 ONNX runtime 사용하기

by yooonlp 2023. 6. 11.

C++에서 ONNX runtime을 사용 방법에 대한 설명을 듣고 정리해보았습니다.

 

ONNX runtime를 사용하는 이유?

  • Open Neural Network Exchange (ONNX) → 프레임워크 상호운용성 및 하드웨어 최적화 접근성을 위한 라이브러리
  • ML 모델의 공통 표준 포맷
  • Tensorflow, Keras, Pytorch 모델 → onnx export 가능
  • ML 모델의 제품화, 라이브러리화, API화
  • ML 모델 암호화

(*onnx로 포맷 변환은 메모리 누수 등의 문제와는 관련없음, *.pt, *.pth등의 파일을 표준 포맷을 변환하는 것)

 

 

C++로 ONNX runtime 사용하기

  • export된 onnx 모델 경로에 위치(encoder.onnx 등의 *.onnx 포맷의 변환된 형태)
  • Onnx 세션을 만들어서 사용한다. 언어별 세션 생성방법은 공홈을 참고하면 된다.
  • 다음 코드에서는 세션을 생성하고, 멀티프로세싱을 위한 스레드 풀을 만들고 있다.
Ort::Session* OnnxComponent::CreateOnnxSession(std::string strPathName)
{
    Ort::SessionOptions session_options;
    session_options.SetIntraOpNumThreads(1);
    session_options.SetInterOpNumThreads(1);
    session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);
    return new Ort::Session(m_Environment, strPathName.c_str(), session_options);
}
  • Tensorflow의 thread 세팅하는 함수와 같은 역할을 한다. ({inter, intra}_op_parallelism_threads)

Thread pool이 무엇인가?

Process와 Thread의 차이는?

Process가 만들어지면 process 내부에 thread가 만들어진다.

Multi-thread를 만든다는 것은 프로세스 안에 쓰레드1,2,3,..를 만드는 것을 의미한다.

Multi-thread 와 Multi-process의 차이

 

Thread Pool을 사용한다는 것

각 쓰레드는 큐를 계속 보고 있음, 각 쓰레드가 먼저 끝나면 잡을 또 가져가서 처리한다. 예를 들어 쓰레드를 두 개 만든다. 큐를 만들어놓고, 큐에다가 job1, job2,…를 넣고, 각 쓰레드는 큐를 계속 보고 있다, 각 쓰레드가 먼저 끝나면 잡을 또 가져가서 처리한다.

 

Inference 과정에서는..?

  • 접속할때마다 스레드를 만든다고 가정하자. 두명의 접속자가 인퍼를 한다면, 스레드 풀은 한개고, 프로세스 한 개에 스레드 여러개를 만들어도 큐는 하나이기 때문에, 큐 길이만 늘어나서 속도가 늘어난다.
  • 이는 여러개의 프로세스를 만드는 걸로 모델 서빙을 해결할 수 있으나, 이 경우, 요청을 매번 어느 프로세스로 보내는가는 서버에서 잘 관리할 것.
  • 파이썬으로 멀티프로세싱하는 경우, Ray를 사용하자

 

 

참고해볼만한 Onnx runtime C++ 예제

https://github.com/leimao/ONNX-Runtime-Inference