1 Billion Classifications
요약
본 기술 기사는 대규모 분류 및 임베딩 작업(1B+ 요청 규모)의 비용과 지연 시간을 체계적으로 분석하고 최적화하는 방법을 설명합니다. 단순히 모델을 사용하는 것을 넘어, 다양한 하드웨어 옵션, 배포 방법론, 로드 테스트 도구 등 4가지 핵심 구성 요소를 통합하여 전체 시스템의 효율성을 극대화하는 프레임워크를 제시합니다. 이를 통해 사용자는 특정 규모의 작업을 가장 저렴하고 빠르게 처리할 수 있는 최적의 아키텍처 설계를 할 수 있습니다.
핵심 포인트
- 1B+ 요청 규모의 대규모 분류 및 임베딩 작업은 비용과 지연 시간 측면에서 매우 복잡한 엔지니어링 문제입니다.
- 최적화에는 하드웨어 선택(Inference Endpoints), 배포 방법론(Hugging Face Hub Library), 추론 서버(Infinity/TEI), 로드 테스트 도구(k6) 등 4가지 핵심 구성 요소의 통합이 필수적입니다.
- 제시된 프레임워크를 통해 사용자는 다양한 하드웨어와 모델을 비교하여, 특정 규모의 작업을 가장 비용 효율적으로 처리할 수 있는 구체적인 아키텍처 설계를 할 수 있습니다.
- 최적화 과정은 단일 GPU 기반의 성능 측정(Single GPU)을 시작으로, 필요에 따라 복제된 GPU를 활용하여 처리량(Throughput)을 수평 확장하는 방식으로 진행됩니다.
이러한 작업들은 현대적인 LLM(대규모 언어 모델) 보다 훨씬 작지만, 1B+ 인퍼런스 요청 규모에서는 여전히 매우 비trivial(비자명확/복잡한) 임을 의미합니다. 명확히 하기 위해, 이는 영어 위키백과 144 배에 해당합니다. 비용 관점에서 접근하는 방법에 대한 정보는 거의 본 적이 없으며, 이를 해결하고 싶습니다. 이 블로그는 대규모 분류 및 임베딩 작업의 비용과 지연 시간을 계산하는 방법을 어떻게 하는지 설명합니다. 우리는 다양한 모델 아키텍처를 분석하고 하드웨어 선택에 따른 비용을 벤치마크하며, 자신의 설비를 최적화하기 위한 명확한 프레임워크를 제공합니다. 또한 직접 과정을 거치지 않으려는 경우에도 직관을 구축할 수 있습니다.
질문 몇 가지를 할 수 있습니다:
- 1B 입력을 해결하는 가장 저렴한 구성은 무엇인가요? (Batch Inference)
- 지연 시간을 고려하면서 어떻게 해야 하나요? (Heavy Usage)
이를 실현하기 위한 코드: https://github.com/datavistics/encoder-analysis
tl;dr 이 내용을 재현하지 않겠습니다. 무엇을 찾았는지 알려주세요.
이 가격으로 다음과 같은 비용을 얻을 수 있었습니다:
| Use Case | Classification | Embedding | Vision-Embedding |
|---|---|---|---|
| Model | |||
| lxyuan/distilbert-base-multilingual-cased-sentiments-student | Alibaba-NLP/gte-modernbert-base | vidore/colqwen2-v1.0-merged | |
| Data | |||
| tyqiangz/multilingual-sentiments | sentence-transformers/trivia-qa-triplet | openbmb/RLAIF-V-Dataset | |
| Hardware Type | |||
nvidia-L4 ($0.8/hr) | |||
nvidia-L4 ($0.8/hr) | |||
nvidia-L4 ($0.8/hr) | |||
| Cost of 1B Inputs | |||
| $253.82 | $409.44 | $44,496.51 |
비용과 지연 시간을 평가하기 위해 4 가지 핵심 구성요소가 필요합니다:
Hardware options: 비용 비교를 위한 다양한 하드웨어 Deployment Facilitator: 우리가 선택한 설정으로 모델을 배포할 수 있는 방법 Load Testing: 요청을 보내고 성능을 측정할 수 있는 방법 Inference Server: 선택한 하드웨어에서 모델을 효율적으로 실행할 수 있는 방법
나는 Hardware Options에 대해 Inference Endpoints 를 활용하며, 이는 다양한 하드웨어 선택을 허용하기 때문입니다. 대신 원하는 GPU/고려사항으로 교체할 수 있음을 유의하세요. Deployment Facilitator 에 대해서는 유용한 Hugging Face Hub Library 를 사용하며, 이를 통해 모델을 프로그래밍적으로 쉽게 배포할 수 있습니다.
Inference Server 에 대해서는 Infinity 를 사용하며, 이는 인코더 기반 모델 (그리고 이제 더 많은 것들) 을 서비스하기 위한 훌륭한 라이브러리입니다. TEI 에 대해 이미 작성한 바 있으며, 이는 또 다른 훌륭한 라이브러리입니다. 당신의 사용 사례를 접근할 때 TEI 를 반드시 고려해야 합니다. 이 블로그는 프레임워크 비교에 초점을 맞추지 않고 방법론에 집중합니다. Infinity 는 멀티모달 임베딩 서비스, AMD/Nvidia/CPU/Inferentia 등 다양한 하드웨어 타겟팅, huggingface 의 transformer 라이브러리에 통합되지 않은 새로운 모델을 실행할 수 있는 등의 여러 가지 핵심 강점이 있습니다. 이 중 가장 중요한 것은 대부분의 모델이 기본적으로 호환 가능하다는 것입니다.
Load Testing 에 대해서는 Grafana 에서의 k6 를 사용하며, 이는 go 로 작성된 오픈소스 로드 테스트 도구이며 javascript 인터페이스를 제공합니다. 쉽게 구성할 수 있으며, 높은 성능을 가지며 오버헤드가 낮습니다. 많은 내장 실행자가 있어 매우 유용합니다. 또한 Virtual Users (VUs) 를 사전 할당하여 직접 테스트를 조립하는 것보다 훨씬 현실적입니다.
나는 다양한 흥미로운 점을 다루는 3 개의 사용 사례를 살펴보겠습니다:
| Use-case | Model | Base Architecture | Parameter Count | Interest |
|---|---|---|---|---|
| Classification (Text) | lxyuan/distilbert-base-multilingual-cased-sentiments-student | DistilBertForSequenceClassification | 135M | The distilled architecture is small/fast and ideal for some. |
| ... | ||||
| Optimization 는 까다로운 이슈입니다. 고려할 사항이 많기 때문입니다. 고수준에서 말하면, 저는 중요한 load testing parameters 를 sweep 하고 single GPU 에 대해 가장 잘 작동하는 것을 찾는 것입니다. 대부분의 encoder 모델은 single GPU 에 들어갈 수 있기 때문입니다. Single GPU 의 비용 baseline 을 얻었으면, replica GPUs 의 수를 늘려서 number of GPUs 와 throughput 를 horizontal 로 scale 할 수 있습니다. |
각 use-case 에 대해 저는 다음과 같은 high-level flow 를 사용하겠습니다:
코드에 접근할 수 있으므로, 이 중 어떤 부분을 조정하든 괜찮습니다:
- GPUs
- Deployment process
- Experimentation Framework
- Etc
감정은 상관이 없습니다.
VUs 와 Batch Size 는 중요합니다. 왜냐하면 이는 GPU 에 있는 모든 compute 를 얼마나 잘 활용하는지에 영향을 주기 때문입니다. 충분히 큰 Batch Size 는 Streaming Multiprocessors 와 VRAM 을 완전히 활용하도록 보장합니다. VRAM 이 남는 시나리오도 있지만, throughput 를 증가시키는 bandwidth cost 가 존재할 수 있습니다. 따라서 experimentation 은 도움이 될 수 있습니다. VUs 는 우리가 사용할 수 있는 batch size 를 완전히 활용하도록 보장합니다.
이제 테스트할 주요 parameters 들입니다:
INFINITY_BATCH_SIZE
- This is how many documents will make a forward pass in the batch in the model
- Too low and we won't be utilizing the GPU
- Too high and the GPU can't handle the large input
VUs
-
This is the number of Virtual Users simulating parallel client requests that is sent to K6
-
It can be hard to simulate a large number of users, and each machine will vary.
-
GPUs
-
We have a variety of GPUs available on Inference Endpoints
-
I prioritized those with the best performance/cost ratio
-
CPUs
-
I omitted these since Nvidia-T4s are so cheap that CPUs didn't seem appealing upon light testing. I left some code to test this if a user is interested though!
Your model 에 따라 다음을 고려할 수 있습니다:
- Which Docker image you are using. [
'michaelf34/infinity:0.0.75-trt-onnx'
,
'michaelf34/infinity:0.0.75'
]- There are a number of Infinity Images that can support different backends. You should consider which ones are most applicable to your hardware/model/configuration.
INFINITY_COMPILE
whether or not you want to use torch.compile()
docsINFINITY_BETTERTRANSFORMER
whether or not you want torch to use Better Transformer
K6 는 좋습니다. 왜냐하면 VUs 를 pre-allocate 하고 insidious bugs 를 방지할 수 있기 때문입니다. 요청을 보내는 방식에 대해 매우 유연합니다. 저는 이를 특정한 방식으로 사용했습니다.
k6 experiment 를 호출할 때, 저는 주로 요청의 throughput 와 average latency 가 무엇인지 알고 싶습니다. 그리고 제가 선택한 load testing parameters 에 대한 sanity checks 를 몇 가지 원합니다. 또한 sweep 를 하고자 하므로 많은 experiments 를 원합니다.
저는 shared-iterations
executor (docs) 는 K6 가 VU 수와 반복 횟수 사이를 공유한다는 것을 의미합니다. 테스트는 k6 가 모든 반복을 실행할 때까지 끝납니다. 이는 합리적인 타임아웃을 가지면서도, sweep 에서 load testing parameters choices 를 구분할 충분한 신뢰도를 갖기 위해 충분히 많은 요청을 통과시킬 수 있게 해줍니다. 다른 executor 와 달리, 이는 VU 당 클라이언트가 최대한 열심히 일하고 있다는 것을 확신하게 하여, 가장 저렴한 옵션이 무엇인지 보여줄 것입니다.
I use 10_000 requests† and have a max experiment time of 1 min. So if 10_000 requests aren't finished by 1 minute, then that experiment is over.
export const options = {
scenarios: {
shared_load_test: {
...
-
P95†† and Average Latency
-
Throughput
-
Accuracy (Classification only)
-
Test Duration
-
Successful Requests
-
Format validation
† I use less max requests for the Vision Embeddings given that the throughput is much lower and images are heavy.
†† P95 는 95% 의 요청이 이 시간 내에 완료됨을 의미합니다. 대부분의 사용자에게 최악의 경우 지연 시간을 나타냅니다.
3 개의 노트북을 통해 최적화 워크플로우를 여기에서 찾을 수 있습니다:
The main purpose was to get my experiments defined, launch the correct Inference Endpoint with the right parameters, and launch k6 with the right parameters to test the endpoint.
I made a couple design choices which you may want to think through to see if they work for you:
- I do an exponential increase of VUs then a binary search to find the best value
- I don't treat the results as exactly repeatable
- If you run the same test multiple times you will get slightly different results
- I used an improvement threshold of 2% to decide if I should keep searching
Text Classification can have a variety of use-cases at scale, like Email Filtering, Toxicity Detection in pre-training datasets, etc. The OG classic architecture was BERT, and quickly many other architectures came about. Do note that in contrast to popular decoder models, these need to be fine-tuned on your task before using them. Today I think the following architectures† are the most notable:
-
DistilBERT
-
Good task performance, Great Engineering performance
-
It made some architectural changes from OG Bert and is not compatible for classification with TEI
-
DeBERTa-v3
-
Great task performance
-
Very slow engineering performance†† as its unique attention mechanism is hard to optimize
-
ModernBERT
-
Uses Sequence Packing and Flash-Attention-2
-
Great task performance and great engineering performance††
† Do note that for these models, you typically need to fine-tune this on your data to perform well
†† I'm using "Engineering performance" to denote anticipated latency/throughput
| Category | Values |
|---|---|
| Model | lxyuan/distilbert-base-multilingual-cased-sentiments-student |
| Model Architecture | |
| DistilBERT | |
| Data | |
tyqiangz/multilingual-sentiments (text col) Avg of 100 token (min of 50), multiple languages | |
| Hardware | |
nvidia-L4 ($0.8/hr) nvidia-t4 ($0.5/hr) | |
| Infinity Image | |
| trt-onnx vs default | |
batch_size | |
[16, 32, 64, 128, 256, 512, 1024] | |
vus | |
32 + |
I chose DistilBERT to focus on as it's a great lightweight choice for many applications. I compared 2 GPUs, nvidia-t4
and nvidia-l4
as well as 2 Infinity Docker Images.
You can see the results in an interactive format here or in the space embedded below in the Analysis section. This is the cheapest configuration across the experiments I ran:
Text Embeddings 는 텍스트 입력을 받아 의미 공간으로 투영하는 작업을 설명하는 다소 모호한 방식입니다. 가까운 점은 의미가 비슷하고 먼 점은 의미가 다르며 (아래 예시 참조), 이는 RAG 에서 널리 사용되며 AI 검색의 중요한 부분입니다 (일부 사람들은 이를 좋아합니다).
많은 아키텍처가 호환되며, 가장 성능 좋은 것들은 MTEB Leaderboard 에서 확인할 수 있습니다.
ModernBERT 는 2020 년 DeBERTa 이후 가장 흥미로운 인코더 릴리스입니다. 모든 ahem 현대적인 트릭이 낡고 익숙한 아키텍처에 통합되어 있습니다. 다른 아키텍처보다 덜 탐구되었고 많은 잠재력을 가지고 있으므로 실험하기 좋은 모델입니다. 속도와 성능 측면에서 여러 개선 사항이 있지만, 사용자에게 가장 두드러지는 것은 8k 컨텍스트 윈도우입니다. 더 철저한 이해를 위해 이 블로그를 확인하세요.
Flash Attention 2 는 컴퓨트 능력 요구사항 때문에 더 현대적인 GPU 만 작동하므로, 저는 T4 를 건너뛰고 L4 를 선택했습니다. H100 은 또한 중력형 카테고리에서 매우 잘 작동합니다.
| Category | Values |
|---|---|
| Model | Alibaba-NLP/gte-modernbert-base |
| Model Architecture | |
| ModernBERT | |
| Data | |
sentence-transformers/trivia-qa-triplet (positive col) Avg of 144 tokens std dev of 14. | |
| Hardware | |
nvidia-L4 ($0.8/hr) | |
| Infinity Image | |
| default | |
batch_size | |
[16, 32, 64, 128, 256, 512, 1024] | |
vus | |
32 + |
여기에 인터랙티브 형식으로 결과를 확인하세요. 이는 실험에서 실행한 것들 중 가장 저렴한 구성입니다:
| Category | Best Value |
|---|---|
| Cost of 1B Inputs | $409.44 |
| Hardware Type | |
nvidia-L4 ($0.8/hr) | |
| Infinity Image | |
| default | |
batch_size | |
| 32 | |
vus | |
| 256 |
ColQwen2 는 Qwen2-VL-2B-Instruct 를 기반으로 하며 ColBERT 스타일의 텍스트와 이미지의 다중 벡터 표현을 사용하는 비주얼 리트리버입니다. 위의 인코더에 비해 복잡한 아키텍처를 가지고 있음을 확인할 수 있습니다.
이러한 용도는 대규모에서 이점을 얻을 수 있으며, 예를 들어 e-commerce 검색, 멀티모달 추천, 엔터프라이즈 멀티모달 RAG 등입니다.
ColBERT 스타일은 이전 임베딩 사용 사례와 다릅니다. 입력을 여러 토큰으로 나누고 각 토큰에 대해 벡터를 반환하며 1 개의 벡터 대신 입력에 대한 1 개의 벡터를 반환합니다. Jina AI 에서 훌륭한 튜토리얼을 확인할 수 있습니다. 이는 우수한 의미론적 인코딩과 더 나은 검색을 가져올 수 있지만, 더 느리고 비쌉니다.
이 실험은 비전 임베딩과 ColBERT 스타일 임베딩†을 탐구하므로 매우 흥미롭습니다. ColQwen2/VLMs 에 대해 몇 가지 점을 확인하세요:
- 2B 는 이 블로그에서 본 다른 모델보다 약 15 배 큽니다.
- ColQwen2 는 디코더를 포함한 여러 모델을 가진 복잡한 아키텍처로, 인코더보다 느립니다.
- 이미지는 쉽게 많은 토큰을 소비할 수 있습니다.
- API 비용:
- 이미지 전송은 텍스트 전송보다 느립니다.
- 클라우드에 있다면 더 큰 에그레스 비용을 추가로 encounter 합니다.
†이 내용이 새로고 흥미롭다면 이 더 자세한 블로그를 확인하세요.
nvidia-l4 와 같은 작은 현대 GPU 를 사용하려는 것이었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Hugging Face Blog의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기