일괄 추론을 통한 추론 효율성 증대
2020년 겨울
Yuanhao Wu
수석 알고리즘 엔지니어
2023년부터 마켓에 출시되는 제품의 경우, 로고와 로고 위치 변경이 예정되어 있습니다. 이에 실제 제품은 사진 및 영상 속 이미지와 다를 수 있습니다.
Z by HP 데이터 사이언스 글로벌 앰배서더인 Yuanhao Wu의 콘텐츠는 HP 제품 지원을 통해 제작되었습니다.
알고리즘 엔지니어라면 일상 업무를 진행하며 모델을 온라인으로 가져오는 문제에 늘 직면하게 됩니다. 까다로운 정도가 덜한 상황에는 웹 프레임워크를 통해 각 사용자 요청에 모델을 호출하고 결과를 추론 및 반환하여 문제를 처리할 수 있습니다. 하지만 이런 간단한 구현으로는 GPU를 최대로 사용하지 못하는 경우가 많고, 고성능이 필요한 상황에는 적합하지 않습니다.
최적화 방법에는 여러 가지가 있는데, 한 가지 유용한 팁은 각 요청에 대한 추론을 여러 요청에 대한 추론으로 한 번에 변경하는 것입니다. 작년 이맘때쯤, 이를 해내려고 소소한 도구를 개발했고 'InferLight'라는 다소 대단한 이름을 붙였습니다. 솔직히 말해서 InferLight는 제대로 구현되지 않았는데, 그래서 최근에 Shannon Technology의 Service-Streamer를 참고해서 리팩터링을 진행했습니다.
이 기능은 간단해 보여도 구현 과정에서 많은 Python 비동기 프로그래밍 지식을 필요로 하며, 현대 GPU의 병렬 연산 성능을 활용해야 합니다.
아키텍처
먼저 모델의 온라인 추론 처리량을 개선하려면 추론 서비스를 비동기화해야 합니다. 웹 서비스의 경우 비동기화는 모델이 연산하는 동안 프로그램이 다른 요청을 처리할 수 있음을 의미합니다. Python의 경우, 제가 주로 사용하는 Sanic과 같이 훌륭한 Asyncio 기반 프레임워크로 비동기 서비스를 구현할 수 있습니다. 추론은 연산 집약적인 작업이지만, 여러 추론 요청을 집계하고, GPU의 병렬 연산 성능을 효율적으로 활용하며, 일괄 추론 결과를 해당 요청자에게 올바르게 반환할 수 있도록 하자는 목표를 세웠습니다.
이러한 목표를 달성하려면 다음 모듈이 필요합니다.
- 프런트 엔드 서비스: 요청을 수신하고 결과를 반환하는 데 사용됩니다. Http, PRC 등 다양한 프로토콜일 수 있으며, 독립적인 프로세스입니다.
- 추론 워커: 모델 초기화, 일괄 추론 데이터 구성, 추론 계산을 담당하며, 독립적인 프로세스입니다.
- 작업 대기열: 프런트 엔드 서비스가 요청을 수신하여 계산 작업을 작업 대기열로 전송합니다. 추론 워커는 대기열을 수신하고 모델 추론에 의해 매번 소규모 배치를 추출합니다.
- 결과 대기열: 추론이 완료된 후 추론 워커는 결과를 결과 대기열에 전송합니다. 프런트 엔드 서비스는 대기열을 수신하고 추론 결과를 가져옵니다.
- 결과 분배: 작업 대기열에 작업을 전송하기 전에 고유 작업 식별자를 생성해야 합니다. 결과 대기열에서 결과를 검색한 후 식별자에 따라 작업에 해당하는 결과를 확인할 수 있습니다.
작업 대기열 및 결과 대기열은 여러 방법으로 구현할 수 있으며, Kafka 및 Redis와 같이 발달된 특정 미들웨어를 사용할 수 있습니다. 외부 의존을 삼가고자 이번에는 Python의 네이티브 멀티 프로세스 대기열을 사용하기로 했습니다. 결과 대기열은 프런트 엔드 서비스 프로세스의 하위 스레드를 통해 수신되고 배포됩니다.
구현
추론 워커는 비교적 단순합니다. 로드하는 모델과 데이터 처리 단계가 다양하기 때문에 추론 워커를 사용 시 상속되고 특정 메서드를 구현하는 기본 클래스로 설계했습니다.
이와 함께 프런트 엔드 서비스에서 추론 요청의 수신, 결과 수집 및 배포를 수행하는 데 사용되는 래퍼 클래스가 있습니다.
사용된 데이터 구조 중 일부는 다음과 같이 정의됩니다.
사용 사례 및 테스트 결과
여기서는 위의 구성 요소를 정서 분석 BERT 모델과 함께 사용할 수 있는 방법을 보여 줍니다.
먼저 모델을 정의합니다.
그런 다음 BaseInferLightWorker를 상속하고 세 가지 함수를 구현하여 전체 워커 클래스를 가져옵니다.
마지막으로, 서비스를 구축합니다.
유명한 Apache의 AB 도구로 몇 가지 테스트를 해봤습니다. HP Z4 워크스테이션에서 위 앱을 실행하여 워커 프로세스가 RTX 6000 GPU에서 실행되고 있는지 확인했습니다.
AB -n 1000 -c 32 http://localhost:8888/batched_predict로 다음과 같은 결과를 얻었습니다.
일괄 추론을 사용하지 않는 또 다른 간단한 구현의 테스트 결과는 다음과 같습니다.
보시다시피 일괄 추론을 통해 처리량이 약 2.5배 증가했습니다! 벤치마크를 수행할 때 일괄 추론을 통해 GPU 활용도 역시 훨씬 높아진다는 점도 확인했습니다.
InferLight 오픈 소스를 게시했는데, 여기에서 확인하실 수 있어요. 효과적으로 사용하시기를 바랍니다. :)